Compare commits

..
49 Commits
Author SHA1 Message Date
Martin Hořeňovský ee67ac6b7c v1.9.6 2017-06-27 12:21:48 +02:00
Baruch BursteinandMartin Hořeňovský 8a14af701e If --list-extra-info is specified with --list-test-names-only, only output one list 2017-06-25 17:12:29 +02:00
Martin Hořeňovský 07c6bfc3b9 --extra-info -> --list-extra-info, behaves like other --list-* flags 2017-06-25 17:12:29 +02:00
Baruch BursteinandMartin Hořeňovský 616f7235ef add --extra-info flag
this will add line info to test lists, and test descriptions to the long
form of the test list
2017-06-25 17:12:29 +02:00
Neal CoombesandMartin Hořeňovský 396ecf6021 Cache std::ostringstream between assertions.
This is not thread safe, but I think that was already true of Catch.
The construction/destruction of the std::ostringstream is where the
vast majority of time is spent per assertion.  A simple test of
100000000 CHECK()s is reduced from around 60s to 7.4s
2017-06-25 15:53:59 +02:00
Martin Hořeňovský a6cdcd43aa Added "How to test changes in PR" section to documentation
Also linked it from PR template.

Closes #936
2017-06-22 18:56:10 +02:00
Neal CoombesandMartin Hořeňovský dcab8a5971 Performance improvement in AssertionInfo.
By using char const * instead of std::string we avoid significant
copying per assertion.  In a simple loop with 10000000 CHECKS on
my system, this reduces the run time from 9.8s to 6s.
2017-06-22 18:03:47 +02:00
Martin Hořeňovský 017a63da62 v1.9.5 2017-06-15 13:08:26 +02:00
Martin Hořeňovský b90d0b7267 Disable deprecation warning of std::uncaught_exception
We might prefer to use `std::uncaught_exceptions` in the future, but I
would prefer not to bring in more configuration into Catch Classic

Closes #927
2017-06-15 11:43:31 +02:00
Martin Hořeňovský efba988ccc Fix how GCC version is detected when checking for __COUNTER__
Fixes #928
2017-06-13 18:20:59 +02:00
Phil NashandGitHub 004228efb2 Merge pull request #855 from kainjow/objc-tostring-link
Fix Catch::toString() linker error when main() is compiled as C++
2017-06-11 23:06:38 +01:00
Martin Hořeňovský e0aaba6cf8 Actually link #923 from the documentation 2017-06-06 16:46:46 +02:00
Martin Hořeňovský a09bef23ed Refer to #923 in reporter documentation 2017-06-06 16:43:14 +02:00
Martin Hořeňovský 3e018ef131 Add link to external gcov/lcov example to documentation
An alternate take on #916, that better slots into the existing
documentation.

Closes #916
2017-06-04 12:17:59 +02:00
Martin Hořeňovský adb66f55a7 Don't include warning headers from catch_xmlwriter.hpp
This prevents Catch from disabling `Wpadded` for Clang inside test files
(files that do not define either `CATCH_CONFIG_MAIN` or
`CATCH_CONFIG_RUNNER`).

catch_suppress_warnings.h and catch_reenable_warnings.h should be
included only once*, so that the stitching script includes them as the
first and last header respectively, since it only includes each header
once. This caused a bug, where the first one was included properly, but
the second one was included prematurely, from catch_xmlwriter.hpp, and
thus was guarded by `CATCH_IMPL`.

* At least until the stitching script is changed to accomodate common
warning disabling header.

Fixes #871
2017-06-02 19:10:57 +02:00
Martin Hořeňovský 377c9a746d Cosmetic fixes (whitespace and spelling) 2017-05-27 14:42:54 +02:00
Martin Hořeňovský ea48ae0f75 Add test for #914 (stringify truthy exprs in standard way) 2017-05-27 14:42:05 +02:00
twhittockandMartin Hořeňovský 2d1739b429 ExpressionLhs reconstruction based on value, not truthiness (#914)
Types which are truthy, but have more information than the truthiness in their string conversion were showing up as 'true' or 'false' instead of showing the underlying type's string value.
2017-05-27 14:09:43 +02:00
Martin HořeňovskýandGitHub 1c59034be4 Merge pull request #911 from dvirtz/master
CTest integration script enhancements
2017-05-27 13:52:55 +02:00
Martin Hořeňovský 52a84788e0 Add Inscopix to commercial users
Closes #918
2017-05-27 12:23:35 +02:00
Martin HořeňovskýandGitHub 3e328f55fc Merge pull request #913 from Carrotstrip/master
fixed spelling error in tutorial.md
2017-05-21 11:17:25 +02:00
Austin L WolfgramandGitHub b18e67522f fixed spelling error 2017-05-20 15:10:42 -04:00
dvirtz 4b086bd5b5 added target name to test name and labels 2017-05-18 16:00:18 +03:00
dvirtz aac594aae3 add option to print debug messages 2017-05-18 15:53:35 +03:00
dvirtz a49fa0edbe use absolute path to test files - accroding to CMake docs EXISTS behavior is well-defined only for full paths. 2017-05-18 15:51:44 +03:00
Martin Hořeňovský d271683c14 Added release process notes/checklist/explanation 2017-05-16 21:33:58 +02:00
Martin Hořeňovský 0bb8e1247e Merge branch 'master' of https://github.com/awglyde/Catch 2017-05-16 16:09:51 +02:00
Martin HořeňovskýandGitHub 32d97caf42 Fixed missing ` in tag documentation 2017-05-16 15:45:44 +02:00
Martin Hořeňovský bc93b29789 Expanded tag documentation
It now mentions that most characters are valid as part of tag and other
details.

Closes  #909
2017-05-16 15:28:53 +02:00
Martin Hořeňovský df5cf2d323 Minor fixup in updateVcpkgPackage.py 2017-05-16 14:34:55 +02:00
Martin Hořeňovský b62c0256b2 Merge branch 'master' of https://github.com/philsquared/Catch 2017-05-16 14:34:27 +02:00
Martin Hořeňovský 1ea84cb734 Expanded logging documentation
Closes #884
2017-05-16 14:34:20 +02:00
Martin HořeňovskýandGitHub 2a5d3736e8 Merge pull request #908 from pJunger/patch-1
Typo: Added namespace in method testCaseEnded
2017-05-16 14:05:31 +02:00
Martin Hořeňovský 3dcc923351 v1.9.4 2017-05-16 13:59:29 +02:00
Martin Hořeňovský 589c40077b Typo fix
Somehow I made that in 5ffc8a84cd without noticing
2017-05-16 13:51:17 +02:00
Patrick JungerandGitHub d4e0b1d093 Added namespace in method testCaseEnded
Did not compile as is
2017-05-14 14:11:47 +02:00
Antonio Di MonacoandMartin Hořeňovský b8443e67da Added Win32 UNICODE wmain support (#903)
* Added wmain support
* Added appveyor.yml wmain configuration
* Added wmain configuration flag to CMake
2017-05-11 13:00:03 +02:00
Martin Hořeňovský 5604ec7266 Updated toString documentation
It will need another update when Catch 2 goes live.

Closes #741
2017-05-03 21:09:27 +02:00
Benjamin R. JackandMartin Hořeňovský 6f012f2d1d Added warning if source file cannot be found
If source files are defined using relative paths, CMake will compile the tests, but this script will (sometimes) fail to find and parse the tests from the source files.  I have added an explicit warning when ParseAndAddCatchTests fails to find a source file.
2017-05-01 19:55:17 +02:00
Martin Hořeňovský 98e61c31df Approval tests now see different line endings as ok
This is mostly to deal with WSL, where git will checkout file with CRLF,
but code that uses formatted output will be writing LFs.
2017-04-29 18:06:36 +02:00
Martin Hořeňovský e641485132 Updated approval tests 2017-04-29 17:54:10 +02:00
Martin Hořeňovský a3ceb8f007 Approval tests now can deal with different expansions of errno 2017-04-29 17:52:12 +02:00
Martin Hořeňovský b819432271 Don't clear out all messages upon printing an assertion.
Previously, this would not print out any messages for the last CHECK
```cpp
TEST_CASE("Foo") {
INFO("Test case start");
for (int i = 0; i < 2; ++i) {
INFO("The number is " << i);
CHECK(i == 0);
}
CHECK(false);
}
```

now it does.
2017-04-29 17:50:03 +02:00
Martin Hořeňovský 9ceae8f51f CMake binaries are now conditionally enabled
Defining NO_SELFTEST=1 when cmake configuration is being done now turns
off SelfTest and Benchmark executables. This is for projects that
consume Catch using ExternalProject_Add and don't want to build our
selftest binaries for their unit test suite.

Closes #897
2017-04-28 20:27:10 +02:00
Martin Hořeňovský 5ffc8a84cd Fix order of arguments in CATCH_FAIL and nonvariadic INTERNAL_CATCH_MSG
Fixes #896
2017-04-28 18:30:04 +02:00
JayAndCatchFireandMartin Hořeňovský 6e0fa4be68 Update opensource-users.md
Fixed broken link to LICENSE
2017-04-27 10:29:58 +02:00
Kevin Wojniak e8b31108d6 Fix Catch::toString() linker error when main() is compiled as C++
Fixes #278
2017-03-14 11:54:14 -07:00
Alex Glyde d8f45cd5f1 changing tabs to spaces 2017-03-06 10:55:00 -05:00
Alex Glyde 3afd077b55 teamcity reporter should time durations explicitly 2017-03-06 10:35:03 -05:00
54 changed files with 641 additions and 221 deletions
+3
View File
@@ -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.
-->
+30 -18
View File
@@ -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")
+1 -1
View File
@@ -4,7 +4,7 @@
[![Build Status](https://travis-ci.org/philsquared/Catch.svg?branch=master)](https://travis-ci.org/philsquared/Catch)
[![Build status](https://ci.appveyor.com/api/projects/status/hrtk60hv6tw6fght/branch/master?svg=true)](https://ci.appveyor.com/project/philsquared/catch/branch/master)
<a href="https://github.com/philsquared/Catch/releases/download/v1.9.3/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.9.6/catch.hpp">The latest, single header, version can be downloaded directly using this link</a>
## What's the Catch?
+7 -1
View File
@@ -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:
+39 -4
View File
@@ -25,13 +25,27 @@
# #
# include(ParseAndAddCatchTests) #
# ParseAndAddCatchTests(${PROJECT_NAME}) #
# #
# The following variables affect the behavior of the script: #
# #
# PARSE_CATCH_TESTS_VERBOSE (Default OFF) #
# -- enables debug messages #
# #
#==================================================================================================#
cmake_minimum_required(VERSION 2.8.8)
option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" 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 +61,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
@@ -90,25 +108,42 @@ function(ParseFile SourceFile TestTarget)
else()
set(CTestName "${Name}")
endif()
set(CTestName "${TestTarget}:${CTestName}")
# 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()
list(APPEND Labels ${Tags})
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 "${Tags}")
LABELS "${Labels}")
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()
+1 -1
View File
@@ -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)
+6 -2
View File
@@ -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.
@@ -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)
+1 -1
View File
@@ -13,4 +13,4 @@ fact then please let us know - either directly, via a PR or
- Bloomberg
- NASA
- [Inscopix Inc.](https://www.inscopix.com/)
+21 -2
View File
@@ -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...*
---
+2 -2
View File
@@ -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)
+27 -1
View File
@@ -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
+1 -1
View File
@@ -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 it's [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.
+35
View File
@@ -1,3 +1,38 @@
# 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
+44
View File
@@ -0,0 +1,44 @@
# 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.
## 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.
## vcpkg update
As a last step, optionally update Microsoft's package manager [vcpkg](https://github.com/Microsoft/vcpkg) with Catch's new version. `updateVcpkgPackage.py` can do a lot of neccessary work for you, but it assumes that you have your fork of vcpkg checked out in a directory next to the directory, where you have checked out Catch.
It creates a branch and commits neccessary changes, that you then should review, synchronize and open a PR against.
+1 -1
View File
@@ -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.
+1 -1
View File
@@ -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
+5 -13
View File
@@ -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 {
+1 -1
View File
@@ -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:
+11 -11
View File
@@ -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
+26
View File
@@ -166,6 +166,32 @@ 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 )
return 0;
+9 -7
View File
@@ -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( 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
+18 -10
View File
@@ -13,14 +13,16 @@
namespace Catch {
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)
: macroName( _macroName ),
lineInfo( _lineInfo ),
capturedExpression( _capturedExpression ),
resultDisposition( _resultDisposition )
resultDisposition( _resultDisposition ),
secondArg( _secondArg )
{}
AssertionResult::AssertionResult() {}
@@ -47,24 +49,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 {
+2 -2
View File
@@ -60,7 +60,7 @@
// 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
@@ -152,7 +152,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(); \
+4
View File
@@ -187,6 +187,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 );
@@ -170,7 +170,7 @@
// 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
+3
View File
@@ -31,6 +31,7 @@ namespace Catch {
listTags( false ),
listReporters( false ),
listTestNamesOnly( false ),
listExtraInfo( false ),
showSuccessfulTests( false ),
shouldDebugBreak( false ),
noThrow( false ),
@@ -50,6 +51,7 @@ namespace Catch {
bool listTags;
bool listReporters;
bool listTestNamesOnly;
bool listExtraInfo;
bool showSuccessfulTests;
bool shouldDebugBreak;
@@ -109,6 +111,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; }
+7 -1
View File
@@ -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 );
}
+1 -1
View File
@@ -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:
+2 -2
View File
@@ -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() {}
};
}
+15 -4
View File
@@ -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 );
+1 -1
View File
@@ -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] ){}
+1 -1
View File
@@ -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)();
+7 -2
View File
@@ -47,7 +47,7 @@ namespace Catch {
template<typename T>
ResultBuilder& operator << ( T const& value ) {
m_stream.oss << value;
m_stream().oss << value;
return *this;
}
@@ -80,7 +80,12 @@ namespace Catch {
private:
AssertionInfo m_assertionInfo;
AssertionResultData m_data;
CopyableStream m_stream;
static CopyableStream &m_stream()
{
static CopyableStream s;
return s;
}
bool m_shouldDebugBreak;
bool m_shouldThrow;
+9 -12
View File
@@ -18,26 +18,23 @@
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_stream().oss.str("");
}
ResultBuilder::~ResultBuilder() {
#if defined(CATCH_CONFIG_FAST_COMPILE)
if ( m_guardException ) {
m_stream.oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
m_stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
captureResult( ResultWas::ThrewException );
getCurrentContext().getResultCapture()->exceptionEarlyReported();
}
@@ -60,7 +57,7 @@ namespace Catch {
void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
m_assertionInfo.resultDisposition = resultDisposition;
m_stream.oss << Catch::translateActiveException();
m_stream().oss << Catch::translateActiveException();
captureResult( ResultWas::ThrewException );
}
@@ -82,7 +79,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 ) ) {
@@ -148,13 +145,13 @@ namespace Catch {
data.negate( expr.isBinaryExpression() );
}
data.message = m_stream.oss.str();
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() {
+8 -7
View File
@@ -145,11 +145,12 @@ namespace Catch {
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;
}
@@ -279,7 +280,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 );
@@ -299,7 +300,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();
@@ -331,9 +332,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 );
}
+7
View File
@@ -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 {
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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]);
+1 -1
View File
@@ -25,7 +25,7 @@ namespace Catch {
#else
template <typename T>
struct add_const {
struct add_const {
typedef const T type;
};
+1 -1
View File
@@ -38,7 +38,7 @@ namespace Catch {
}
inline Version libraryVersion() {
static Version version( 1, 9, 3, "", 0 );
static Version version( 1, 9, 6, "", 0 );
return version;
}
-2
View File
@@ -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
+1 -1
View File
@@ -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
@@ -150,6 +150,7 @@ namespace Catch {
}
virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
m_testTimer.start();
StreamingReporterBase::testCaseStarting( testInfo );
stream << "##teamcity[testStarted name='"
<< escape( testInfo.name ) << "']\n";
@@ -166,7 +167,8 @@ 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";
}
private:
@@ -205,6 +207,7 @@ namespace Catch {
}
private:
bool m_headerPrintedForThisSection;
Timer m_testTimer;
};
#ifdef CATCH_IMPL
@@ -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
-------------------------------------------------------------------------------
@@ -940,6 +953,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: 168 | 119 passed | 45 failed | 4 failed as expected
assertions: 968 | 859 passed | 88 failed | 21 failed as expected
@@ -119,7 +119,7 @@ with expansion:
MiscTests.cpp:<line number>:
PASSED:
REQUIRE( (*__error()) == 1 )
REQUIRE( errno == 1 )
with expansion:
1 == 1
@@ -819,7 +819,7 @@ TrickyTests.cpp:<line number>:
PASSED:
REQUIRE( a )
with expansion:
true
0x<hex digits>
TrickyTests.cpp:<line number>:
PASSED:
@@ -2717,14 +2717,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 +2735,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 +4571,7 @@ TrickyTests.cpp:<line number>:
PASSED:
CHECK( True )
with expansion:
true
1
TrickyTests.cpp:<line number>:
PASSED:
@@ -4577,7 +4583,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 +6437,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
-------------------------------------------------------------------------------
@@ -9466,6 +9483,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: 168 | 118 passed | 46 failed | 4 failed as expected
assertions: 970 | 859 passed | 90 failed | 21 failed as expected
@@ -119,7 +119,7 @@ with expansion:
MiscTests.cpp:<line number>:
PASSED:
REQUIRE( (*__error()) == 1 )
REQUIRE( errno == 1 )
with expansion:
1 == 1
@@ -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="78" tests="971" 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">
@@ -237,10 +237,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 +443,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 &lt; 10" type="REQUIRE">
current counter 10
@@ -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
@@ -890,7 +890,7 @@
a
</Original>
<Expanded>
true
0x<hex digits>
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/TrickyTests.cpp" >
@@ -2744,6 +2744,9 @@
2 == 2
</Expanded>
</Expression>
<Info>
this message may be logged later
</Info>
<Info>
this message should be logged
</Info>
@@ -2755,6 +2758,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 +2775,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>
@@ -4677,7 +4695,7 @@ re>"
True
</Original>
<Expanded>
true
1
</Expanded>
</Expression>
<Expression success="true" type="CHECK" filename="projects/<exe-name>/TrickyTests.cpp" >
@@ -4693,7 +4711,7 @@ re>"
!False
</Original>
<Expanded>
!false
!0
</Expanded>
</Expression>
<OverallResult success="true"/>
@@ -6894,6 +6912,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
@@ -10114,7 +10143,7 @@ spanner <OverallResult success="true"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="859" failures="90" expectedFailures="21"/>
<OverallResults successes="859" failures="91" expectedFailures="21"/>
</Group>
<OverallResults successes="859" failures="89" expectedFailures="21"/>
<OverallResults successes="859" failures="90" expectedFailures="21"/>
</Catch>
+28
View 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));
}
+1 -1
View File
@@ -403,5 +403,5 @@ 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.
}
+1 -2
View File
@@ -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);
}
}
}
}
+11 -3
View File
@@ -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)
+1
View File
@@ -96,6 +96,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)
+145 -75
View File
@@ -1,6 +1,6 @@
/*
* Catch v1.9.3
* Generated: 2017-04-25 14:16:29.434734
* Catch v1.9.6
* Generated: 2017-06-27 12:19:54.557875
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@@ -220,7 +220,7 @@
// 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
@@ -927,22 +927,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( 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
@@ -1217,7 +1219,7 @@ namespace Catch {
template<typename T>
ResultBuilder& operator << ( T const& value ) {
m_stream.oss << value;
m_stream().oss << value;
return *this;
}
@@ -1250,7 +1252,12 @@ namespace Catch {
private:
AssertionInfo m_assertionInfo;
AssertionResultData m_data;
CopyableStream m_stream;
static CopyableStream &m_stream()
{
static CopyableStream s;
return s;
}
bool m_shouldDebugBreak;
bool m_shouldThrow;
@@ -1571,7 +1578,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
@@ -1855,7 +1862,7 @@ public:
}
virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
dest = Catch::toString( m_truthy );
dest = Catch::toString( m_lhs );
}
private:
@@ -2272,7 +2279,7 @@ namespace Catch {
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(); \
@@ -3490,16 +3497,16 @@ return @ desc; \
#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 {};
@@ -3938,6 +3945,7 @@ namespace Catch {
listTags( false ),
listReporters( false ),
listTestNamesOnly( false ),
listExtraInfo( false ),
showSuccessfulTests( false ),
shouldDebugBreak( false ),
noThrow( false ),
@@ -3957,6 +3965,7 @@ namespace Catch {
bool listTags;
bool listReporters;
bool listTestNamesOnly;
bool listExtraInfo;
bool showSuccessfulTests;
bool shouldDebugBreak;
@@ -4015,6 +4024,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; }
@@ -5276,6 +5286,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 );
@@ -5804,8 +5818,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 );
@@ -5820,6 +5835,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;
}
@@ -5843,9 +5865,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;
}
@@ -5937,7 +5962,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 );
@@ -6642,11 +6667,12 @@ namespace Catch {
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;
}
@@ -6776,7 +6802,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 );
@@ -6828,9 +6854,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 );
}
@@ -7052,6 +7078,32 @@ 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 )
return 0;
@@ -7981,14 +8033,16 @@ namespace Catch {
namespace Catch {
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)
: macroName( _macroName ),
lineInfo( _lineInfo ),
capturedExpression( _capturedExpression ),
resultDisposition( _resultDisposition )
resultDisposition( _resultDisposition ),
secondArg( _secondArg )
{}
AssertionResult::AssertionResult() {}
@@ -8015,24 +8069,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 {
@@ -8282,7 +8342,7 @@ namespace Catch {
}
inline Version libraryVersion() {
static Version version( 1, 9, 3, "", 0 );
static Version version( 1, 9, 6, "", 0 );
return version;
}
@@ -8634,6 +8694,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() );
@@ -8643,6 +8707,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 {
@@ -8958,7 +9025,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]);
@@ -8975,26 +9042,23 @@ std::string toString( std::nullptr_t ) {
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_stream().oss.str("");
}
ResultBuilder::~ResultBuilder() {
#if defined(CATCH_CONFIG_FAST_COMPILE)
if ( m_guardException ) {
m_stream.oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
m_stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
captureResult( ResultWas::ThrewException );
getCurrentContext().getResultCapture()->exceptionEarlyReported();
}
@@ -9017,7 +9081,7 @@ namespace Catch {
void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
m_assertionInfo.resultDisposition = resultDisposition;
m_stream.oss << Catch::translateActiveException();
m_stream().oss << Catch::translateActiveException();
captureResult( ResultWas::ThrewException );
}
@@ -9038,7 +9102,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 ) ) {
@@ -9104,13 +9168,13 @@ namespace Catch {
data.negate( expr.isBinaryExpression() );
}
data.message = m_stream.oss.str();
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() {
@@ -10001,20 +10065,6 @@ namespace Catch {
};
}
// #included from: catch_reenable_warnings.h
#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
#ifdef __clang__
# ifdef __ICC // icpc defines the __clang__ macro
# pragma warning(pop)
# else
# pragma clang diagnostic pop
# endif
#elif defined __GNUC__
# pragma GCC diagnostic pop
#endif
namespace Catch {
class XmlReporter : public StreamingReporterBase {
@@ -11268,9 +11318,15 @@ namespace Catch {
#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 );
}
@@ -11349,7 +11405,7 @@ int main (int argc, char * const argv[]) {
#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
@@ -11471,5 +11527,19 @@ int main (int argc, char * const argv[]) {
using Catch::Detail::Approx;
// #included from: internal/catch_reenable_warnings.h
#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
#ifdef __clang__
# ifdef __ICC // icpc defines the __clang__ macro
# pragma warning(pop)
# else
# pragma clang diagnostic pop
# endif
#elif defined __GNUC__
# pragma GCC diagnostic pop
#endif
#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED