Compare commits

..

46 Commits

Author SHA1 Message Date
Martin Hořeňovský
7c37501b07 v2.7.2 2019-04-22 23:15:59 +02:00
Martin Hostettler
4a1ca1ab55 TrackerContext: Remove misleading instance static method.
TrackerContext is not used as singleton, so just remove this misleading
method
2019-04-22 16:37:22 +02:00
Will Handley
91b617c462 Added a vector approximate matcher 2019-04-20 10:02:17 +02:00
Martin Hořeňovský
45e552528d Remove home-rolled algorithm replacements
Previously we had them to avoid including <algorithm> in the vector
matchers, but
* we included it anyway, even though we did not use it
* we use <algorithm> anyways in the generators
2019-04-19 17:54:21 +02:00
Martin Hořeňovský
3978e9653b Add more documentation on contributing 2019-04-18 16:18:30 +02:00
Stephen Newell
d6fce7bf34 Fix warnings generated with -Wshadow 2019-04-18 15:30:38 +02:00
Martin Hořeňovský
c3c82f539c Merge pull request #1336 from ax3l/topic-overrideVirtualRedundant
Refactor: override implies virtual
2019-04-18 14:10:24 +02:00
Martin Hořeňovský
c7653811a6 Add basic CPack support
@ThijsWithaar is responsible for giving me the idea, but his PR
had couple of things that meant it was simpler to rewrite it than
to fix and merge it.

Supersedes and closes #1599
2019-04-18 13:47:33 +02:00
JoeyGrajciar
79417b9afc Revert "draft of nttp support"
This reverts commit 0c39409da7.
2019-04-18 11:35:33 +02:00
JoeyGrajciar
11cdd72db9 Merge remote-tracking branch 'refs/remotes/origin/nttp_support' 2019-04-18 11:26:33 +02:00
Jozef Grajciar
0c39409da7 draft of nttp support
added _SIG macros
2019-04-17 21:41:19 +02:00
Martin Hořeňovský
edfac75347 Add test for omitting the 'Filters' heading when there were none 2019-04-16 23:49:22 +02:00
Martin Luelf
ac94bd0520 ParseAndAddCatchTests: Ignore cmake object libraries 2019-04-14 19:10:15 +02:00
Maciej Patro
d4eec016a9 CatchAddTests now adds tags as labels for ctest
- `ctest --print-labels` now will show list of available labels
- `ctest -L <regex>` will allow to run tests with given labels(tags)
2019-04-14 18:59:53 +02:00
Martin Hořeňovský
36fb856163 Fix JUnit reporter output so that it conforms to JUnit schema
The `properties` can only go under the `testsuite` tag, not under
the `testsuites` tag.

Fixes #1598
2019-04-11 13:04:54 +02:00
Martin Hořeňovský
4e32e0a563 Fix vendored dep because upstream is non-responsive
Eventually this needs to be fixed in the textflow project by Phil,
but he has not done so in the half a year this bug has been known
to be there, so...

Closes #1470
Closes #1455
2019-04-10 20:17:25 +02:00
Daniele E. Domenichelli
1e2270b370 ParseAndAddCatchTests: Do not change CMAKE_MINIMUM_REQUIRED_VERSION when included 2019-04-10 10:50:13 +02:00
Daniele E. Domenichelli
5096e39297 ParseAndAddCatchTests: Add scope to functions in order to avoid name collisions 2019-04-10 10:50:13 +02:00
Daniele E. Domenichelli
15ccced6da ParseAndAddCatchTests: Document AdditionalCatchParameters variable 2019-04-10 10:50:13 +02:00
Daniele E. Domenichelli
682617b5b7 ParseAndAddCatchTests: Fix tests not found
When using an optional launcher the target name is not interpreted as a
target, therefore it is not replaced automatically with its path.
2019-04-10 10:50:13 +02:00
Daniele E. Domenichelli
15150c7b46 ParseAndAddCatchTests: Set the ParseAndAddCatchTests_TESTS property
After the script, the ParseAndAddCatchTests_TESTS property for the
target, and for each source file in the target is set, and contains the
list of the tests extracted from that target, or from that file.

This is useful, for example to add further labels or properties to the
tests.
2019-04-10 10:50:13 +02:00
Torfinn Berset
5ce355a38c For macOS builds, disable isDebuggerActive() for non-AppleClang targets. Fixes #1588 2019-04-10 10:19:54 +02:00
Ryan Pavlik
edde6f4736 Fix typos identified by codespell.
Self test baselines also modified accordingly, due to
one typo found in a string in test code.
2019-04-10 09:42:11 +02:00
Martin Hořeňovský
6bc5d172ee Merge pull request #1596 from 50ty/patch-1
IndexOfHideLabel is never used
2019-04-10 09:31:00 +02:00
Stefan Rommel
3079b514d4 IndexOfHideLabel is never used 2019-04-10 08:00:08 +02:00
Martin Hořeňovský
e99f1efd28 Avoid adding a default test spec when none was provided 2019-04-09 11:50:59 +02:00
Martin Hořeňovský
b9dd1936e5 v2.7.1 2019-04-08 13:38:00 +02:00
Martin Hořeňovský
293d617c49 Merge pull request #1592 from robinlinden/fix-cmake-integration-typo
Use correct filename in CMake integration docs
2019-04-08 13:20:41 +02:00
Robin Lindén
7be35af167 Use correct filename in CMake integration docs 2019-04-07 15:41:34 +02:00
Martin Hořeňovský
08147a23f9 Fix ObjC matchers
Closes #1571
2019-04-03 20:32:11 +02:00
Ziv Shahaf
8af8704089 support for printing test filters (PR #1585) 2019-04-03 20:24:52 +02:00
Martin Hořeňovský
3816e99d0c Add GENERATE_COPY and GENERATE_VAR capturing generator macros 2019-03-31 14:11:10 +02:00
Martin Hořeňovský
b77cec05c0 Fix test tag parsing to split [.foo] into [.][foo] 2019-03-29 10:48:56 +01:00
Omer Ozarslan
54089c4c8c Deducing return type of map generator helper (#1576)
* Deduce map return type implicitly

Giving the first template argument to map generator function to deduce
return type is now optional even if the return type is different from
the type generated by mapped generator.
2019-03-24 15:44:22 +01:00
Martin Hořeňovský
296d447452 Merge pull request #1575 from alabuzhev/warning_ntstatus
Suppress warning caused by ntstatus.h inclusion
2019-03-20 15:22:27 +01:00
Alex Alabuzhev
0531965349 Suppress warning caused by ntstatus.h inclusion 2019-03-19 23:57:56 +00:00
Tadeusz Puźniakowski
a1cdff4f18 raspigcd - opensource-users
Added raspigcd that uses Catch2 for tests
2019-03-19 20:35:59 +01:00
Steve Hollasch
4611125801 generators.md: fix extraneous back tick in doc 2019-03-14 09:14:02 +01:00
Clare Macrae
e509012e64 Update blog URL and fic typos in tutorial.md 2019-03-09 18:02:29 +01:00
Clare Macrae
448825db03 Readability improvements for assertions.md 2019-03-09 18:02:29 +01:00
Clare Macrae
0fff8e7791 Add ApprovalTests.cpp to list of open source users 2019-03-09 18:02:29 +01:00
Martin Hořeňovský
68a3c129ac Merge pull request #1562 from claremacrae/patch-2
Update url of blog post
2019-03-09 17:35:08 +01:00
Martin Hořeňovský
1ce5ec9b74 Merge pull request #1565 from inobelar/patch-1
Added override keyword near IntRange::describe() method
2019-03-09 17:33:42 +01:00
Yurii Nakonechnyi
37a4e32319 Added override keyword near IntRange::describe() method 2019-03-09 15:05:27 +02:00
Clare Macrae
0424c9a62c Update url of blog post 2019-03-08 08:56:00 +00:00
Axel Huebl
5347ff9e5f Refactor: override implies virtual
If not used with `final`, override implies `virtual`.
Detected via CodeFactor score.

Another reference on SO:
  https://stackoverflow.com/questions/43466863/isnt-virtual-keyword-redundant-when-override-or-final-specifiers-are-used
2018-07-12 14:27:06 +02:00
75 changed files with 1683 additions and 449 deletions

View File

@@ -47,7 +47,7 @@ class BuilderSettings(object):
@property
def reference(self):
""" Read project version from branch create Conan referece
""" Read project version from branch create Conan reference
"""
return os.getenv("CONAN_REFERENCE", "Catch2/{}".format(self._version))

View File

@@ -12,7 +12,7 @@ at docs/contributing.md. It will tell you how to properly test your changes.
<!--
Describe the what and the why of your pull request. Remember that these two
are usually a bit different. As an example, if you have made various changes
to decrease the number of new strings allocated, thats what. The why probably
to decrease the number of new strings allocated, that's what. The why probably
was that you have a large set of tests and found that this speeds them up.
-->

View File

@@ -19,7 +19,7 @@ set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY})
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
# Gcov evaluation is dependend on the used compiler. Check gcov support for
# Gcov evaluation is dependent on the used compiler. Check gcov support for
# each compiler that is used. If gcov binary was already found for this
# compiler, do not try to find it again.
if (NOT GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN)

View File

@@ -74,7 +74,7 @@ set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY})
get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
foreach (LANG ${ENABLED_LANGUAGES})
# Coverage flags are not dependend on language, but the used compiler. So
# Coverage flags are not dependent on language, but the used compiler. So
# instead of searching flags foreach language, search flags foreach compiler
# used.
set(COMPILER ${CMAKE_${LANG}_COMPILER_ID})

View File

@@ -6,7 +6,7 @@ if(NOT DEFINED PROJECT_NAME)
set(NOT_SUBPROJECT ON)
endif()
project(Catch2 LANGUAGES CXX VERSION 2.7.0)
project(Catch2 LANGUAGES CXX VERSION 2.7.2)
# Provide path for scripts
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
@@ -205,4 +205,15 @@ if (NOT_SUBPROJECT)
${PKGCONFIG_INSTALL_DIR}
)
# CPack/CMake started taking the package version from project version 3.12
# So we need to set the version manually for older CMake versions
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
endif()
set(CPACK_PACKAGE_CONTACT "https://github.com/catchorg/Catch2/")
include( CPack )
endif(NOT_SUBPROJECT)

View File

@@ -5,17 +5,17 @@
[![Build Status](https://travis-ci.org/catchorg/Catch2.svg?branch=master)](https://travis-ci.org/catchorg/Catch2)
[![Build status](https://ci.appveyor.com/api/projects/status/github/catchorg/Catch2?svg=true)](https://ci.appveyor.com/project/catchorg/catch2)
[![codecov](https://codecov.io/gh/catchorg/Catch2/branch/master/graph/badge.svg)](https://codecov.io/gh/catchorg/Catch2)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/byNJIivVphHo170P)
[![Try online](https://img.shields.io/badge/try-online-blue.svg)](https://wandbox.org/permlink/rsEsNO9M0flb5NlQ)
[![Join the chat in Discord: https://discord.gg/4CWS9zD](https://img.shields.io/badge/Discord-Chat!-brightgreen.svg)](https://discord.gg/4CWS9zD)
<a href="https://github.com/catchorg/Catch2/releases/download/v2.7.0/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
<a href="https://github.com/catchorg/Catch2/releases/download/v2.7.2/catch.hpp">The latest version of the single header can be downloaded directly using this link</a>
## Catch2 is released!
If you've been using an earlier version of Catch, please see the
Breaking Changes section of [the release notes](https://github.com/catchorg/Catch2/releases/tag/v2.0.1)
before moving to Catch2. You might also like to read [this blog post](http://www.levelofindirection.com/journal/2017/11/3/catch2-released.html) for more details.
before moving to Catch2. You might also like to read [this blog post](https://levelofindirection.com/blog/catch2-released.html) for more details.
## What's the Catch?

View File

@@ -22,6 +22,39 @@ function(add_command NAME)
set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE)
endfunction()
macro(_add_catch_test_labels LINE)
# convert to list of tags
string(REPLACE "][" "]\\;[" tags ${line})
add_command(
set_tests_properties "${prefix}${test}${suffix}"
PROPERTIES
LABELS "${tags}"
)
endmacro()
macro(_add_catch_test LINE)
set(test ${line})
# use escape commas to handle properly test cases with commans inside the name
string(REPLACE "," "\\," test_name ${test})
# ...and add to script
add_command(
add_test "${prefix}${test}${suffix}"
${TEST_EXECUTOR}
"${TEST_EXECUTABLE}"
"${test_name}"
${extra_args}
)
add_command(
set_tests_properties "${prefix}${test}${suffix}"
PROPERTIES
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
${properties}
)
list(APPEND tests "${prefix}${test}${suffix}")
endmacro()
# Run test executable to get list of available tests
if(NOT EXISTS "${TEST_EXECUTABLE}")
message(FATAL_ERROR
@@ -29,7 +62,7 @@ if(NOT EXISTS "${TEST_EXECUTABLE}")
)
endif()
execute_process(
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-names-only
COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-tests
OUTPUT_VARIABLE output
RESULT_VARIABLE result
)
@@ -47,27 +80,22 @@ elseif(${result} LESS 0)
endif()
string(REPLACE "\n" ";" output "${output}")
set(test)
set(tags_regex "(\\[([^\\[]*)\\])+$")
# Parse output
foreach(line ${output})
set(test ${line})
# use escape commas to handle properly test cases with commans inside the name
string(REPLACE "," "\\," test_name ${test})
# ...and add to script
add_command(add_test
"${prefix}${test}${suffix}"
${TEST_EXECUTOR}
"${TEST_EXECUTABLE}"
"${test_name}"
${extra_args}
)
add_command(set_tests_properties
"${prefix}${test}${suffix}"
PROPERTIES
WORKING_DIRECTORY "${TEST_WORKING_DIR}"
${properties}
)
list(APPEND tests "${prefix}${test}${suffix}")
# lines without leading whitespaces are catch output not tests
if(${line} MATCHES "^[ \t]+")
# strip leading spaces and tabs
string(REGEX REPLACE "^[ \t]+" "" line ${line})
if(${line} MATCHES "${tags_regex}")
_add_catch_test_labels(${line})
else()
_add_catch_test(${line})
endif()
endif()
endforeach()
# Create a list of all discovered tests, which users may use to e.g. set

View File

@@ -44,9 +44,19 @@
# set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC}) #
# just before calling this ParseAndAddCatchTests function #
# #
# The AdditionalCatchParameters optional variable can be used to pass extra argument to the test #
# command. For example, to include successful tests in the output, one can write #
# set(AdditionalCatchParameters --success) #
# #
# After the script, the ParseAndAddCatchTests_TESTS property for the target, and for each source #
# file in the target is set, and contains the list of the tests extracted from that target, or #
# from that file. This is useful, for example to add further labels or properties to the tests. #
# #
#==================================================================================================#
cmake_minimum_required(VERSION 2.8.8)
if (CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.8)
message(FATAL_ERROR "ParseAndAddCatchTests requires CMake 2.8.8 or newer")
endif()
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)
@@ -54,7 +64,7 @@ option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the
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)
function(ParseAndAddCatchTests_PrintDebugMessage)
if(PARSE_CATCH_TESTS_VERBOSE)
message(STATUS "ParseAndAddCatchTests: ${ARGV}")
endif()
@@ -65,7 +75,7 @@ endfunction()
# - full line comments (i.e. // ... )
# contents have been read into '${CppCode}'.
# !keep partial line comments
function(RemoveComments CppCode)
function(ParseAndAddCatchTests_RemoveComments CppCode)
string(ASCII 2 CMakeBeginBlockComment)
string(ASCII 3 CMakeEndBlockComment)
string(REGEX REPLACE "/\\*" "${CMakeBeginBlockComment}" ${CppCode} "${${CppCode}}")
@@ -77,24 +87,29 @@ function(RemoveComments CppCode)
endfunction()
# Worker function
function(ParseFile SourceFile TestTarget)
function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
# If SourceFile is an object library, do not scan it (as it is not a file). Exit without giving a warning about a missing file.
if(SourceFile MATCHES "\\\$<TARGET_OBJECTS:.+>")
ParseAndAddCatchTests_PrintDebugMessage("Detected OBJECT library: ${SourceFile} this will not be scanned for tests.")
return()
endif()
# 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}")
ParseAndAddCatchTests_PrintDebugMessage("parsing ${SourceFile}")
file(STRINGS ${SourceFile} Contents NEWLINE_CONSUME)
# Remove block and fullline comments
RemoveComments(Contents)
ParseAndAddCatchTests_RemoveComments(Contents)
# 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")
ParseAndAddCatchTests_PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property")
set_property(
DIRECTORY
APPEND
@@ -155,7 +170,6 @@ function(ParseFile SourceFile TestTarget)
list(APPEND Labels ${Tags})
list(FIND Labels "!hide" IndexOfHideLabel)
set(HiddenTagFound OFF)
foreach(label ${Labels})
string(REGEX MATCH "^!hide|^\\." result ${label})
@@ -165,26 +179,34 @@ function(ParseFile SourceFile TestTarget)
endif(result)
endforeach(label)
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_LESS "3.9")
PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
ParseAndAddCatchTests_PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
else()
PrintDebugMessage("Adding test \"${CTestName}\"")
ParseAndAddCatchTests_PrintDebugMessage("Adding test \"${CTestName}\"")
if(Labels)
PrintDebugMessage("Setting labels to ${Labels}")
ParseAndAddCatchTests_PrintDebugMessage("Setting labels to ${Labels}")
endif()
# Escape commas in the test spec
string(REPLACE "," "\\," Name ${Name})
# Add the test and set its properties
add_test(NAME "\"${CTestName}\"" COMMAND ${OptionalCatchTestLauncher} ${TestTarget} ${Name} ${AdditionalCatchParameters})
add_test(NAME "\"${CTestName}\"" COMMAND ${OptionalCatchTestLauncher} $<TARGET_FILE:${TestTarget}> ${Name} ${AdditionalCatchParameters})
# Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8")
PrintDebugMessage("Setting DISABLED test property")
ParseAndAddCatchTests_PrintDebugMessage("Setting DISABLED test property")
set_tests_properties("\"${CTestName}\"" PROPERTIES DISABLED ON)
else()
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
LABELS "${Labels}")
endif()
set_property(
TARGET ${TestTarget}
APPEND
PROPERTY ParseAndAddCatchTests_TESTS "\"${CTestName}\"")
set_property(
SOURCE ${SourceFile}
APPEND
PROPERTY ParseAndAddCatchTests_TESTS "\"${CTestName}\"")
endif()
@@ -193,11 +215,11 @@ endfunction()
# entry point
function(ParseAndAddCatchTests TestTarget)
PrintDebugMessage("Started parsing ${TestTarget}")
ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}")
get_target_property(SourceFiles ${TestTarget} SOURCES)
PrintDebugMessage("Found the following sources: ${SourceFiles}")
ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}")
foreach(SourceFile ${SourceFiles})
ParseFile(${SourceFile} ${TestTarget})
ParseAndAddCatchTests_ParseFile(${SourceFile} ${TestTarget})
endforeach()
PrintDebugMessage("Finished parsing ${TestTarget}")
ParseAndAddCatchTests_PrintDebugMessage("Finished parsing ${TestTarget}")
endfunction()

View File

@@ -10,7 +10,7 @@
Most test frameworks have a large collection of assertion macros to capture all possible conditional forms (```_EQUALS```, ```_NOTEQUALS```, ```_GREATER_THAN``` etc).
Catch is different. Because it decomposes natural C-style conditional expressions most of these forms are reduced to one or two that you will use all the time. That said there are a rich set of auxiliary macros as well. We'll describe all of these here.
Catch is different. Because it decomposes natural C-style conditional expressions most of these forms are reduced to one or two that you will use all the time. That said there is a rich set of auxiliary macros as well. We'll describe all of these here.
Most of these macros come in two forms:
@@ -61,7 +61,7 @@ Catch provides a way to perform tolerant comparisons of floating point values th
REQUIRE( performComputation() == Approx( 2.1 ) );
```
Catch also provides a UDL for `Approx`; `_a`. It resides in
Catch also provides a user-defined literal for `Approx`; `_a`. It resides in
the `Catch::literals` namespace and can be used like so:
```cpp
using namespace Catch::literals;

View File

@@ -48,7 +48,7 @@ If Catch2 has been installed in system, both of these can be used after
doing `find_package(Catch2 REQUIRED)`. Otherwise you need to add them
to your CMake module path.
### `Catch.cmake` and `AddCatchTests.cmake`
### `Catch.cmake` and `CatchAddTests.cmake`
`Catch.cmake` provides function `catch_discover_tests` to get tests from
a target. This function works by running the resulting executable with

View File

@@ -27,7 +27,7 @@
[Override output colouring](#override-output-colouring)<br>
Catch works quite nicely without any command line options at all - but for those times when you want greater control the following options are available.
Click one of the followings links to take you straight to that option - or scroll on to browse the available options.
Click one of the following links to take you straight to that option - or scroll on to browse the available options.
<a href="#specifying-which-tests-to-run"> ` <test-spec> ...`</a><br />
<a href="#usage"> ` -h, -?, --help`</a><br />

View File

@@ -89,7 +89,7 @@ them yourself, their signatures are:
By default, when Catch's stringification machinery has to stringify
a type that does not specialize `StringMaker`, does not overload `operator<<`,
is not an enumeration and is not a range, it uses `"{?}"`. This can be
overriden by defining `CATCH_CONFIG_FALLBACK_STRINGIFIER` to name of a
overridden by defining `CATCH_CONFIG_FALLBACK_STRINGIFIER` to name of a
function that should perform the stringification instead.
All types that do not provide `StringMaker` specialization or `operator<<`

View File

@@ -75,8 +75,34 @@ before you do so, you need to check that the introduced changes are indeed
intentional.
## Code constructs to watch out for
*this document is still in-progress...*
This section is a (sadly incomplete) listing of various constructs that
are problematic and are not always caught by our CI infrastructure.
### Naked exceptions and exceptions-related function
If you are throwing an exception, it should be done via `CATCH_ERROR`
or `CATCH_RUNTIME_ERROR` in `catch_enforce.h`. These macros will handle
the differences between compilation with or without exceptions for you.
However, some platforms (IAR) also have problems with exceptions-related
functions, such as `std::current_exceptions`. We do not have IAR in our
CI, but luckily there should not be too many reasons to use these.
However, if you do, they should be kept behind a
`CATCH_CONFIG_DISABLE_EXCEPTIONS` macro.
### Unqualified usage of functions from C's stdlib
If you are using a function from C's stdlib, please include the header
as `<cfoo>` and call the function qualified. The common knowledge that
there is no difference is wrong, QNX and VxWorks won't compile if you
include the header as `<cfoo>` and call the function unqualified.
----
_This documentation will always be in-progress as new information comes
up, but we are trying to keep it as up to date as possible._
---

View File

@@ -29,13 +29,13 @@ struct MyListener : Catch::TestEventListenerBase {
using TestEventListenerBase::TestEventListenerBase; // inherit constructor
virtual void testCaseStarting( Catch::TestCaseInfo const& testInfo ) override {
void testCaseStarting( Catch::TestCaseInfo const& testInfo ) override {
// Perform some setup before a test case is run
}
virtual void testCaseEnded( Catch::TestCaseStats const& testCaseStats ) override {
void testCaseEnded( Catch::TestCaseStats const& testCaseStats ) override {
// Tear-down after a test case is run
}
}
};
CATCH_REGISTER_LISTENER( MyListener )
```

View File

@@ -57,11 +57,11 @@ type, making their usage much nicer. These are
* `filter(predicate, GeneratorWrapper<T>&&)` for `FilterGenerator<T, Predicate>`
* `take(count, GeneratorWrapper<T>&&)` for `TakeGenerator<T>`
* `repeat(repeats, GeneratorWrapper<T>&&)` for `RepeatGenerator<T>`
* `map(func, GeneratorWrapper<T>&&)` for `MapGenerator<T, T, Func>` (map `T` to `T`)
* `map(func, GeneratorWrapper<T>&&)` for `MapGenerator<T, U, Func>` (map `U` to `T`, deduced from `Func`)
* `map<T>(func, GeneratorWrapper<U>&&)` for `MapGenerator<T, U, Func>` (map `U` to `T`)
* `chunk(chunk-size, GeneratorWrapper<T>&&)` for `ChunkGenerator<T>`
* `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator`
* `range(start, end)` for `RangeGenerator<T>` with a step size of `1`
* `range(start, end)` for `RangeGenerator<T>` with a step size of `1`
* `range(start, end, step)` for `RangeGenerator<T>` with a custom step size
@@ -90,7 +90,11 @@ used with other generators as arguments, such as `auto i = GENERATE(0, 2,
take(100, random(300, 3000)));`. This is useful e.g. if you know that
specific inputs are problematic and want to test them separately/first.
**For safety reasons, you cannot use variables inside the `GENERATE` macro.**
**For safety reasons, you cannot use variables inside the `GENERATE` macro.
This is done because the generator expression _will_ outlive the outside
scope and thus capturing references is dangerous. If you need to use
variables inside the generator expression, make sure you thought through
the lifetime implications and use `GENERATE_COPY` or `GENERATE_REF`.**
You can also override the inferred type by using `as<type>` as the first
argument to the macro. This can be useful when dealing with string literals,
@@ -98,7 +102,7 @@ if you want them to come out as `std::string`:
```cpp
TEST_CASE("type conversion", "[generators]") {
auto str = GENERATE(as<std::string>{}, "a", "bb", "ccc");`
auto str = GENERATE(as<std::string>{}, "a", "bb", "ccc");
REQUIRE(str.size() > 0);
}
```

View File

@@ -17,6 +17,7 @@
- Generators: [Create your own generator](../examples/300-Gen-OwnGenerator.cpp)
- Generators: [Use map to convert types in GENERATE expression](../examples/301-Gen-MapTypeConversion.cpp)
- Generators: [Use variables in generator expressions](../examples/310-Gen-VariablesInGenerators.cpp)
- Generators: [Use custom variable capture in generator expressions](../examples/311-Gen-CustomCapture.cpp)
## Planned

View File

@@ -85,7 +85,7 @@ Second unscoped info
## Streaming macros
All these macros allow heterogenous sequences of values to be streaming using the insertion operator (```<<```) in the same way that std::ostream, std::cout, etc support it.
All these macros allow heterogeneous sequences of values to be streaming using the insertion operator (```<<```) in the same way that std::ostream, std::cout, etc support it.
E.g.:
```c++

View File

@@ -92,7 +92,7 @@ public:
IntRange( int begin, int end ) : m_begin( begin ), m_end( end ) {}
// Performs the test for this matcher
virtual bool match( int const& i ) const override {
bool match( int const& i ) const override {
return i >= m_begin && i <= m_end;
}
@@ -100,7 +100,7 @@ public:
// include any provided data (the begin/ end in this case) and
// be written as if it were stating a fact (in the output it will be
// preceded by the value under test).
virtual std::string describe() const {
virtual std::string describe() const override {
std::ostringstream ss;
ss << "is between " << m_begin << " and " << m_end;
return ss.str();

View File

@@ -17,6 +17,9 @@ Listing a project here does not imply endorsement and the plan is to keep these
## Libraries & Frameworks
### [ApprovalTests.cpp](https://github.com/approvals/ApprovalTests.cpp)
C++11 implementation of Approval Tests, for quick, convenient testing of legacy code.
### [Azmq](https://github.com/zeromq/azmq)
Boost Asio style bindings for ZeroMQ.
@@ -100,6 +103,9 @@ MAME originally stood for Multiple Arcade Machine Emulator.
### [Newsbeuter](https://github.com/akrennmair/newsbeuter)
Newsbeuter is an open-source RSS/Atom feed reader for text terminals.
### [raspigcd](https://github.com/pantadeusz/raspigcd)
Low level CLI app and library for execution of GCODE on Raspberry Pi without any additional microcontrolers (just RPi + Stepsticks).
### [SpECTRE](https://github.com/sxs-collaboration/spectre)
SpECTRE is a code for multi-scale, multi-physics problems in astrophysics and gravitational physics.

View File

@@ -30,7 +30,7 @@ CHECKED_IF( a == b ) {
`CHECK_NOFAIL( expr )` is a variant of `CHECK` that does not fail the test
case if _expr_ evaluates to `false`. This can be useful for checking some
assumption, that might be violated without the test neccessarily failing.
assumption, that might be violated without the test necessarily failing.
Example output:
```
@@ -120,7 +120,7 @@ constructor, or before Catch2's session is created in user's own main._
`ANON_TEST_CASE` is a `TEST_CASE` replacement that will autogenerate
unique name. The advantage of this is that you do not have to think
of a name for the test case,`the disadvantage is that the name doesn't
neccessarily remain stable across different links, and thus it might be
necessarily remain stable across different links, and thus it might be
hard to run directly.
Example:

View File

@@ -2,6 +2,8 @@
# Release notes
**Contents**<br>
[2.7.2](#272)<br>
[2.7.1](#271)<br>
[2.7.0](#270)<br>
[2.6.1](#261)<br>
[2.6.0](#260)<br>
@@ -21,6 +23,41 @@
[Older versions](#older-versions)<br>
[Even Older versions](#even-older-versions)<br>
## 2.7.2
### Improvements
* Added an approximate vector matcher (#1499)
### Fixes
* Filters will no longer be shown if there were none
* Fixed compilation error when using Homebrew GCC on OS X (#1588, #1589)
* Fixed the console reporter not showing messages that start with a newline (#1455, #1470)
* Modified JUnit reporter's output so that rng seed and filters are reported according to the JUnit schema (#1598)
* Fixed some obscure warnings and static analysis passes
### Miscellaneous
* Various improvements to `ParseAndAddCatchTests` (#1559, #1601)
* When a target is parsed, it receives `ParseAndAddCatchTests_TESTS` property which summarizes found tests
* Fixed problem with tests not being found if the `OptionalCatchTestLauncher` variables is used
* Including the script will no longer forcefully modify `CMAKE_MINIMUM_REQUIRED_VERSION`
* CMake object libraries are ignored when parsing to avoid needless warnings
* `CatchAddTests` now adds test's tags to their CTest labels (#1600)
* Added basic CPack support to our build
## 2.7.1
### Improvements
* Reporters now print out the filters applied to test cases (#1550, #1585)
* Added `GENERATE_COPY` and `GENERATE_VAR` macros that can use variables inside the generator expression
* Because of the significant danger of lifetime issues, the default `GENERATE` macro still does not allow variables
* The `map` generator helper now deduces the mapped return type (#1576)
### Fixes
* Fixed ObjC++ compilation (#1571)
* Fixed test tag parsing so that `[.foo]` is now parsed as `[.][foo]`.
* Suppressed warning caused by the Windows headers defining SE codes in different manners (#1575)
## 2.7.0
### Improvements
@@ -42,7 +79,7 @@
* Running tests will no longer open the specified output file twice (#1545)
* This would cause trouble when the file was not a file, but rather a named pipe
* Fixes the CLion/Resharper integration with Catch
* Fixed `-Wunreachable-code` occuring with (old) ccache+cmake+clang combination (#1540)
* Fixed `-Wunreachable-code` occurring with (old) ccache+cmake+clang combination (#1540)
* Fixed `-Wdefaulted-function-deleted` warning with Clang 8 (#1537)
* Catch2's type traits and helpers are now properly namespaced inside `Catch::` (#1548)
* Fixed std{out,err} redirection for failing test (#1514, #1525)
@@ -724,7 +761,7 @@ Cygwin issue with `gettimeofday` - `#define` was not early enough
* Usage of `gettimeofday` inside Catch should no longer cause compilation errors.
* Improved `-Wparentheses` suppression for gcc (#674)
* When compiled with gcc 4.8 or newer, the suppression is localized to assertions only
* Otherwise it is supressed for the whole TU
* Otherwise it is suppressed for the whole TU
* Fixed test spec parser issue (with escapes in multiple names)
##### Other
@@ -807,7 +844,7 @@ Other:
##### Other:
* Types with overloaded `&&` operator are no longer evaluated twice when used in an assertion macro.
* The use of `__COUNTER__` is supressed when Catch is parsed by CLion
* The use of `__COUNTER__` is suppressed when Catch is parsed by CLion
* This change is not active when compiling a binary
* Approval tests can now be run on Windows
* CMake will now warn if a file is present in the `include` folder but not is not enumerated as part of the project

View File

@@ -32,7 +32,7 @@ Once a release is ready, release notes need to be written. They should summarize
### 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.
After version number is incremented, single-include header is regenerated and release notes are updated, changes should be committed and pushed to GitHub.
### Release on GitHub

View File

@@ -23,7 +23,7 @@ The full source for Catch2, including test projects, documentation, and other th
## Where to put it?
Catch2 is header only. All you need to do is drop the file somewhere reachable from your project - either in some central location you can set your header search path to find, or directly into your project tree itself! This is a particularly good option for other Open-Source projects that want to use Catch for their test suite. See [this blog entry for more on that](http://www.levelofindirection.com/journal/2011/5/27/unit-testing-in-c-and-objective-c-just-got-ridiculously-easi.html).
Catch2 is header only. All you need to do is drop the file somewhere reachable from your project - either in some central location you can set your header search path to find, or directly into your project tree itself! This is a particularly good option for other Open-Source projects that want to use Catch for their test suite. See [this blog entry for more on that](https://levelofindirection.com/blog/unit-testing-in-cpp-and-objective-c-just-got-ridiculously-easier-still.html).
The rest of this tutorial will assume that the Catch2 single-include header (or the include folder) is available unqualified - but you may need to prefix it with a folder name if necessary.
@@ -103,7 +103,7 @@ Of course there are still more issues to deal with. For example we'll hit proble
### What did we do here?
Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take moment to consider those before we move on.
Although this was a simple test it's been enough to demonstrate a few things about how Catch is used. Let's take a moment to consider those before we move on.
1. All we did was ```#define``` one identifier and ```#include``` one header and we got everything - even an implementation of ```main()``` that will [respond to command line arguments](command-line.md#top). You can only use that ```#define``` in one implementation file, for (hopefully) obvious reasons. Once you have more than one file with unit tests in you'll just ```#include "catch.hpp"``` and go. Usually it's a good idea to have a dedicated implementation file that just has ```#define CATCH_CONFIG_MAIN``` and ```#include "catch.hpp"```. You can also provide your own implementation of main and drive Catch yourself (see [Supplying-your-own-main()](own-main.md#top)).
2. We introduce test cases with the ```TEST_CASE``` macro. This macro takes one or two arguments - a free form test name and, optionally, one or more tags (for more see <a href="#test-cases-and-sections">Test cases and Sections</a>, ). The test name must be unique. You can run sets of tests by specifying a wildcarded test name or a tag expression. See the [command line docs](command-line.md#top) for more information on running tests.
@@ -159,7 +159,7 @@ This works because the ```SECTION``` macro contains an if statement that calls b
So far so good - this is already an improvement on the setup/teardown approach because now we see our setup code inline and use the stack.
The power of sections really shows, however, when we need to execute a sequence of, checked, operations. Continuing the vector example, we might want to verify that attempting to reserve a capacity smaller than the current capacity of the vector changes nothing. We can do that, naturally, like so:
The power of sections really shows, however, when we need to execute a sequence of checked operations. Continuing the vector example, we might want to verify that attempting to reserve a capacity smaller than the current capacity of the vector changes nothing. We can do that, naturally, like so:
```c++
SECTION( "reserving bigger changes capacity but not size" ) {

View File

@@ -305,7 +305,7 @@ struct MyListener : Catch::TestEventListenerBase {
~MyListener();
// The whole test run starting
virtual void testRunStarting( Catch::TestRunInfo const& testRunInfo ) override {
void testRunStarting( Catch::TestRunInfo const& testRunInfo ) override {
std::cout
<< std::boolalpha
<< "\nEvent: testRunStarting:\n";
@@ -313,7 +313,7 @@ struct MyListener : Catch::TestEventListenerBase {
}
// The whole test run ending
virtual void testRunEnded( Catch::TestRunStats const& testRunStats ) override {
void testRunEnded( Catch::TestRunStats const& testRunStats ) override {
std::cout
<< dashed_line
<< "\nEvent: testRunEnded:\n";
@@ -321,7 +321,7 @@ struct MyListener : Catch::TestEventListenerBase {
}
// A test is being skipped (because it is "hidden")
virtual void skipTest( Catch::TestCaseInfo const& testInfo ) override {
void skipTest( Catch::TestCaseInfo const& testInfo ) override {
std::cout
<< dashed_line
<< "\nEvent: skipTest:\n";
@@ -329,7 +329,7 @@ struct MyListener : Catch::TestEventListenerBase {
}
// Test cases starting
virtual void testCaseStarting( Catch::TestCaseInfo const& testInfo ) override {
void testCaseStarting( Catch::TestCaseInfo const& testInfo ) override {
std::cout
<< dashed_line
<< "\nEvent: testCaseStarting:\n";
@@ -337,30 +337,30 @@ struct MyListener : Catch::TestEventListenerBase {
}
// Test cases ending
virtual void testCaseEnded( Catch::TestCaseStats const& testCaseStats ) override {
void testCaseEnded( Catch::TestCaseStats const& testCaseStats ) override {
std::cout << "\nEvent: testCaseEnded:\n";
print( std::cout, 1, "testCaseStats", testCaseStats );
}
// Sections starting
virtual void sectionStarting( Catch::SectionInfo const& sectionInfo ) override {
void sectionStarting( Catch::SectionInfo const& sectionInfo ) override {
std::cout << "\nEvent: sectionStarting:\n";
print( std::cout, 1, "- sectionInfo", sectionInfo );
}
// Sections ending
virtual void sectionEnded( Catch::SectionStats const& sectionStats ) override {
void sectionEnded( Catch::SectionStats const& sectionStats ) override {
std::cout << "\nEvent: sectionEnded:\n";
print( std::cout, 1, "- sectionStats", sectionStats );
}
// Assertions before/ after
virtual void assertionStarting( Catch::AssertionInfo const& assertionInfo ) override {
void assertionStarting( Catch::AssertionInfo const& assertionInfo ) override {
std::cout << "\nEvent: assertionStarting:\n";
print( std::cout, 1, "- assertionInfo", assertionInfo );
}
virtual bool assertionEnded( Catch::AssertionStats const& assertionStats ) override {
bool assertionEnded( Catch::AssertionStats const& assertionStats ) override {
std::cout << "\nEvent: assertionEnded:\n";
print( std::cout, 1, "- assertionStats", assertionStats );
return true;

View File

@@ -8,41 +8,6 @@
#include <catch2/catch.hpp>
#include <random>
// Lets start by implementing a parametrizable double generator
class RandomDoubleGenerator : public Catch::Generators::IGenerator<double> {
std::minstd_rand m_rand;
std::uniform_real_distribution<> m_dist;
double current_number;
public:
RandomDoubleGenerator(double low, double high):
m_rand(std::random_device{}()),
m_dist(low, high)
{
static_cast<void>(next());
}
double const& get() const override;
bool next() override {
current_number = m_dist(m_rand);
return true;
}
};
// Avoids -Wweak-vtables
double const& RandomDoubleGenerator::get() const {
return current_number;
}
// Also provide a nice shortcut for creating the generator
Catch::Generators::GeneratorWrapper<double> random(double low, double high) {
return Catch::Generators::GeneratorWrapper<double>(std::unique_ptr<Catch::Generators::IGenerator<double>>(new RandomDoubleGenerator(low, high)));
}
TEST_CASE("Generate random doubles across different ranges",
"[generator][example][advanced]") {
// Workaround for old libstdc++
@@ -55,16 +20,12 @@ TEST_CASE("Generate random doubles across different ranges",
}));
// This will not compile (intentionally), because it accesses a variable
// auto number = GENERATE(take(50, random(r.first, r.second)));
// We have to manually register the generators instead
// Notice that we are using value capture in the lambda, to avoid lifetime issues
auto number = Catch::Generators::generate( CATCH_INTERNAL_LINEINFO,
[=]{
using namespace Catch::Generators;
return makeGenerators(take(50, random(std::get<0>(r), std::get<1>(r))));
}
);
// auto number = GENERATE(take(50, random(std::get<0>(r), std::get<1>(r))));
// GENERATE_COPY copies all variables mentioned inside the expression
// thus this will work.
auto number = GENERATE_COPY(take(50, random(std::get<0>(r), std::get<1>(r))));
REQUIRE(std::abs(number) > 0);
}

View File

@@ -0,0 +1,41 @@
// 311-Gen-CustomCapture.cpp
// Shows how to provide custom capture list to the generator expression
// Note that using variables inside generators is dangerous and should
// be done only if you know what you are doing, because the generators
// _WILL_ outlive the variables. Also, even if you know what you are
// doing, you should probably use GENERATE_COPY or GENERATE_REF macros
// instead. However, if your use case requires having a
// per-variable custom capture list, this example shows how to achieve
// that.
#include <catch2/catch.hpp>
TEST_CASE("Generate random doubles across different ranges",
"[generator][example][advanced]") {
// Workaround for old libstdc++
using record = std::tuple<double, double>;
// Set up 3 ranges to generate numbers from
auto r1 = GENERATE(table<double, double>({
record{3, 4},
record{-4, -3},
record{10, 1000}
}));
auto r2(r1);
// This will take r1 by reference and r2 by value.
// Note that there are no advantages for doing so in this example,
// it is done only for expository purposes.
auto number = Catch::Generators::generate( CATCH_INTERNAL_LINEINFO,
[&r1, r2]{
using namespace Catch::Generators;
return makeGenerators(take(50, random(std::get<0>(r1), std::get<1>(r2))));
}
);
REQUIRE(std::abs(number) > 0);
}
// Compiling and running this file will result in 150 successful assertions

View File

@@ -47,6 +47,7 @@ set( SOURCES_IDIOMATIC_TESTS
300-Gen-OwnGenerator.cpp
301-Gen-MapTypeConversion.cpp
310-Gen-VariablesInGenerators.cpp
311-Gen-CustomCapture.cpp
)
# main-s for reporter-specific test sources:

View File

@@ -11,7 +11,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 7
#define CATCH_VERSION_PATCH 0
#define CATCH_VERSION_PATCH 2
#ifdef __clang__
# pragma clang system_header

View File

@@ -111,6 +111,9 @@ public:
m_suffix = false;
auto width = m_column.m_width - indent();
m_end = m_pos;
if (line()[m_pos] == '\n') {
++m_end;
}
while (m_end < line().size() && line()[m_end] != '\n')
++m_end;

View File

@@ -55,18 +55,18 @@ namespace Detail {
return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
}
void Approx::setMargin(double margin) {
CATCH_ENFORCE(margin >= 0,
"Invalid Approx::margin: " << margin << '.'
void Approx::setMargin(double newMargin) {
CATCH_ENFORCE(newMargin >= 0,
"Invalid Approx::margin: " << newMargin << '.'
<< " Approx::Margin has to be non-negative.");
m_margin = margin;
m_margin = newMargin;
}
void Approx::setEpsilon(double epsilon) {
CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0,
"Invalid Approx::epsilon: " << epsilon << '.'
void Approx::setEpsilon(double newEpsilon) {
CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0,
"Invalid Approx::epsilon: " << newEpsilon << '.'
<< " Approx::epsilon has to be in [0, 1]");
m_epsilon = epsilon;
m_epsilon = newEpsilon;
}
} // end namespace Detail

View File

@@ -16,10 +16,7 @@ namespace Catch {
m_stream( openStream() )
{
TestSpecParser parser(ITagAliasRegistry::get());
if (data.testsOrTags.empty()) {
parser.parse("~[.]"); // All not hidden tests
}
else {
if (!data.testsOrTags.empty()) {
m_hasTestFilters = true;
for( auto const& testOrTags : data.testsOrTags )
parser.parse( testOrTags );

View File

@@ -82,10 +82,10 @@ namespace Catch {
std::string getProcessName() const;
std::string const& getReporterName() const;
std::vector<std::string> const& getTestsOrTags() const;
std::vector<std::string> const& getTestsOrTags() const override;
std::vector<std::string> const& getSectionsToRun() const override;
virtual TestSpec const& testSpec() const override;
TestSpec const& testSpec() const override;
bool hasTestFilters() const override;
bool showHelp() const;

View File

@@ -69,7 +69,7 @@ namespace {
originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
}
virtual void use( Colour::Code _colourCode ) override {
void use( Colour::Code _colourCode ) override {
switch( _colourCode ) {
case Colour::None: return setTextAttribute( originalForegroundAttributes );
case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
@@ -132,7 +132,7 @@ namespace {
// https://github.com/philsquared/Catch/pull/131
class PosixColourImpl : public IColourImpl {
public:
virtual void use( Colour::Code _colourCode ) override {
void use( Colour::Code _colourCode ) override {
switch( _colourCode ) {
case Colour::None:
case Colour::White: return setColour( "[0m" );

View File

@@ -13,27 +13,27 @@ namespace Catch {
class Context : public IMutableContext, NonCopyable {
public: // IContext
virtual IResultCapture* getResultCapture() override {
IResultCapture* getResultCapture() override {
return m_resultCapture;
}
virtual IRunner* getRunner() override {
IRunner* getRunner() override {
return m_runner;
}
virtual IConfigPtr const& getConfig() const override {
IConfigPtr const& getConfig() const override {
return m_config;
}
virtual ~Context() override;
~Context() override;
public: // IMutableContext
virtual void setResultCapture( IResultCapture* resultCapture ) override {
void setResultCapture( IResultCapture* resultCapture ) override {
m_resultCapture = resultCapture;
}
virtual void setRunner( IRunner* runner ) override {
void setRunner( IRunner* runner ) override {
m_runner = runner;
}
virtual void setConfig( IConfigPtr const& config ) override {
void setConfig( IConfigPtr const& config ) override {
m_config = config;
}

View File

@@ -18,19 +18,23 @@
# include <stdbool.h>
# include <sys/types.h>
# include <unistd.h>
# include <sys/sysctl.h>
# include <cstddef>
# include <ostream>
namespace Catch {
#ifdef __apple_build_version__
// These headers will only compile with AppleClang (XCode)
// For other compilers (Clang, GCC, ... ) we need to exclude them
# include <sys/sysctl.h>
#endif
namespace Catch {
#ifdef __apple_build_version__
// The following function is taken directly from the following technical note:
// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
// https://developer.apple.com/library/archive/qa/qa1361/_index.html
// Returns true if the current process is being debugged (either
// running under the debugger or has a debugger attached post facto).
bool isDebuggerActive(){
int mib[4];
struct kinfo_proc info;
std::size_t size;
@@ -60,6 +64,12 @@ namespace Catch {
return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
}
#else
bool isDebuggerActive() {
// We need to find another way to determine this for non-appleclang compilers on macOS
return false;
}
#endif
} // namespace Catch
#elif defined(CATCH_PLATFORM_LINUX)

View File

@@ -19,7 +19,7 @@ namespace Catch {
public:
~ExceptionTranslatorRegistry();
virtual void registerTranslator( const IExceptionTranslator* translator );
virtual std::string translateActiveException() const override;
std::string translateActiveException() const override;
std::string tryTranslators() const;
private:

View File

@@ -37,10 +37,10 @@ namespace Catch {
// Windows can easily distinguish between SO and SigSegV,
// but SigInt, SigTerm, etc are handled differently.
static SignalDefs signalDefs[] = {
{ EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
{ EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
{ EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
{ EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
{ static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION), "SIGILL - Illegal instruction signal" },
{ static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow" },
{ static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal" },
{ static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },
};
LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {

View File

@@ -201,7 +201,10 @@ namespace Generators {
} // namespace Catch
#define GENERATE( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
#define GENERATE_COPY( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
#define GENERATE_REF( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
#endif // TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED

View File

@@ -169,16 +169,28 @@ namespace Generators {
}
};
template <typename T, typename U, typename Func>
#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
// std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
// replaced with std::invoke_result here. Also *_t format is preferred over
// typename *::type format.
template <typename Func, typename U>
using MapFunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U>>>;
#else
template <typename Func, typename U>
using MapFunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U)>::type>::type>::type;
#endif
template <typename Func, typename U, typename T = MapFunctionReturnType<Func, U>>
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
return GeneratorWrapper<T>(
pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
);
}
template <typename T, typename Func>
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<T>&& generator) {
template <typename T, typename U, typename Func>
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
return GeneratorWrapper<T>(
pf::make_unique<MapGenerator<T, T, Func>>(std::forward<Func>(function), std::move(generator))
pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
);
}

View File

@@ -69,6 +69,7 @@ namespace Catch {
virtual ShowDurations::OrNot showDurations() const = 0;
virtual TestSpec const& testSpec() const = 0;
virtual bool hasTestFilters() const = 0;
virtual std::vector<std::string> const& getTestsOrTags() const = 0;
virtual RunTests::InWhatOrder runOrder() const = 0;
virtual unsigned int rngSeed() const = 0;
virtual int benchmarkResolutionMultiple() const = 0;

View File

@@ -45,7 +45,7 @@ public:
// The following functions create the actual matcher objects.
// The user has to explicitly specify type to the function, because
// infering std::function<bool(T const&)> is hard (but possible) and
// inferring std::function<bool(T const&)> is hard (but possible) and
// requires a lot of TMP.
template<typename T>
Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {

View File

@@ -9,6 +9,7 @@
#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
#include "catch_matchers.h"
#include "catch_approx.h"
#include <algorithm>
@@ -16,28 +17,6 @@ namespace Catch {
namespace Matchers {
namespace Vector {
namespace Detail {
template <typename InputIterator, typename T>
size_t count(InputIterator first, InputIterator last, T const& item) {
size_t cnt = 0;
for (; first != last; ++first) {
if (*first == item) {
++cnt;
}
}
return cnt;
}
template <typename InputIterator, typename T>
bool contains(InputIterator first, InputIterator last, T const& item) {
for (; first != last; ++first) {
if (*first == item) {
return true;
}
}
return false;
}
}
template<typename T>
struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
@@ -112,6 +91,42 @@ namespace Matchers {
std::vector<T> const& m_comparator;
};
template<typename T>
struct ApproxMatcher : MatcherBase<std::vector<T>> {
ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const override {
if (m_comparator.size() != v.size())
return false;
for (std::size_t i = 0; i < v.size(); ++i)
if (m_comparator[i] != approx(v[i]))
return false;
return true;
}
std::string describe() const override {
return "is approx: " + ::Catch::Detail::stringify( m_comparator );
}
template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
ApproxMatcher& epsilon( T const& newEpsilon ) {
approx.epsilon(newEpsilon);
return *this;
}
template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
ApproxMatcher& margin( T const& newMargin ) {
approx.margin(newMargin);
return *this;
}
template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
ApproxMatcher& scale( T const& newScale ) {
approx.scale(newScale);
return *this;
}
std::vector<T> const& m_comparator;
mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();
};
template<typename T>
struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
@@ -121,28 +136,7 @@ namespace Matchers {
if (m_target.size() != vec.size()) {
return false;
}
auto lfirst = m_target.begin(), llast = m_target.end();
auto rfirst = vec.begin(), rlast = vec.end();
// Cut common prefix to optimize checking of permuted parts
while (lfirst != llast && *lfirst == *rfirst) {
++lfirst; ++rfirst;
}
if (lfirst == llast) {
return true;
}
for (auto mid = lfirst; mid != llast; ++mid) {
// Skip already counted items
if (Detail::contains(lfirst, mid, *mid)) {
continue;
}
size_t num_vec = Detail::count(rfirst, rlast, *mid);
if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) {
return false;
}
}
return true;
return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
}
std::string describe() const override {
@@ -172,6 +166,11 @@ namespace Matchers {
return Vector::EqualsMatcher<T>( comparator );
}
template<typename T>
Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) {
return Vector::ApproxMatcher<T>( comparator );
}
template<typename T>
Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
return Vector::UnorderedEqualsMatcher<T>(target);

View File

@@ -116,7 +116,7 @@ namespace Catch {
arcSafeRelease( m_substr );
}
bool match( NSString* arg ) const override {
bool match( NSString* const& str ) const override {
return false;
}
@@ -126,7 +126,7 @@ namespace Catch {
struct Equals : StringHolder {
Equals( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str isEqualToString:m_substr];
}
@@ -139,7 +139,7 @@ namespace Catch {
struct Contains : StringHolder {
Contains( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location != NSNotFound;
}
@@ -152,7 +152,7 @@ namespace Catch {
struct StartsWith : StringHolder {
StartsWith( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == 0;
}
@@ -164,7 +164,7 @@ namespace Catch {
struct EndsWith : StringHolder {
EndsWith( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == [str length] - [m_substr length];
}

View File

@@ -71,7 +71,7 @@ namespace Catch {
if (strerror_s(buffer, errno)) {
CATCH_RUNTIME_ERROR("Could not translate errno to a string");
}
CATCH_RUNTIME_ERROR("Coul dnot open the temp file: '" << m_buffer << "' because: " << buffer);
CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer);
}
}
#else

View File

@@ -18,11 +18,11 @@ namespace Catch {
class ReporterFactory : public IReporterFactory {
virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
IStreamingReporterPtr create( ReporterConfig const& config ) const override {
return std::unique_ptr<T>( new T( config ) );
}
virtual std::string getDescription() const override {
std::string getDescription() const override {
return T::getDescription();
}
};
@@ -39,10 +39,10 @@ namespace Catch {
class ListenerFactory : public IReporterFactory {
virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
IStreamingReporterPtr create( ReporterConfig const& config ) const override {
return std::unique_ptr<T>( new T( config ) );
}
virtual std::string getDescription() const override {
std::string getDescription() const override {
return std::string();
}
};

View File

@@ -72,7 +72,10 @@ namespace Catch {
auto const& allTestCases = getAllTestCasesSorted(*config);
for (auto const& testCase : allTestCases) {
if (!context.aborting() && matchTest(testCase, testSpec, *config))
bool matching = (!testSpec.hasFilters() && !testCase.isHidden()) ||
(testSpec.hasFilters() && matchTest(testCase, testSpec, *config));
if (!context.aborting() && matching)
totals += context.runTest(testCase);
else
context.reporter().skipTest(testCase);

View File

@@ -43,7 +43,7 @@ namespace Catch {
void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
CATCH_ENFORCE( !isReservedTag(tag),
"Tag name: [" << tag << "] is not allowed.\n"
<< "Tag names starting with non alpha-numeric characters are reserved\n"
<< "Tag names starting with non alphanumeric characters are reserved\n"
<< _lineInfo );
}
}
@@ -75,6 +75,12 @@ namespace Catch {
else if( prop == TestCaseInfo::None )
enforceNotReservedTag( tag, _lineInfo );
// Merged hide tags like `[.approvals]` should be added as
// `[.][approvals]`. The `[.]` is added at later point, so
// we only strip the prefix
if (startsWith(tag, '.') && tag.size() > 1) {
tag.erase(0, 1);
}
tags.push_back( tag );
tag.clear();
inTag = false;

View File

@@ -54,9 +54,12 @@ namespace Catch {
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
std::vector<TestCase> filtered;
filtered.reserve( testCases.size() );
for( auto const& testCase : testCases )
if( matchTest( testCase, testSpec, config ) )
filtered.push_back( testCase );
for (auto const& testCase : testCases) {
if ((!testSpec.hasFilters() && !testCase.isHidden()) ||
(testSpec.hasFilters() && matchTest(testCase, testSpec, config))) {
filtered.push_back(testCase);
}
}
return filtered;
}
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {

View File

@@ -32,11 +32,6 @@ namespace TestCaseTracking {
ITracker::~ITracker() = default;
TrackerContext& TrackerContext::instance() {
static TrackerContext s_instance;
return s_instance;
}
ITracker& TrackerContext::startRun() {
m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr );
m_currentTracker = nullptr;

View File

@@ -71,8 +71,6 @@ namespace TestCaseTracking {
public:
static TrackerContext& instance();
ITracker& startRun();
void endRun();

View File

@@ -33,7 +33,7 @@ namespace Catch {
public:
NamePattern( std::string const& name );
virtual ~NamePattern();
virtual bool matches( TestCaseInfo const& testCase ) const override;
bool matches( TestCaseInfo const& testCase ) const override;
private:
WildcardPattern m_wildcardPattern;
};
@@ -42,7 +42,7 @@ namespace Catch {
public:
TagPattern( std::string const& tag );
virtual ~TagPattern();
virtual bool matches( TestCaseInfo const& testCase ) const override;
bool matches( TestCaseInfo const& testCase ) const override;
private:
std::string m_tag;
};
@@ -51,7 +51,7 @@ namespace Catch {
public:
ExcludedPattern( PatternPtr const& underlyingPattern );
virtual ~ExcludedPattern();
virtual bool matches( TestCaseInfo const& testCase ) const override;
bool matches( TestCaseInfo const& testCase ) const override;
private:
PatternPtr m_underlyingPattern;
};

View File

@@ -37,7 +37,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 2, 7, 0, "", 0 );
static Version version( 2, 7, 2, "", 0 );
return version;
}

View File

@@ -41,6 +41,20 @@ namespace Catch {
return std::string(buffer);
}
std::string serializeFilters( std::vector<std::string> const& container ) {
ReusableStringStream oss;
bool first = true;
for (auto&& filter : container)
{
if (!first)
oss << ' ';
else
first = false;
oss << filter;
}
return oss.str();
}
TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)
:StreamingReporterBase(_config) {}

View File

@@ -25,6 +25,8 @@ namespace Catch {
// Returns double formatted as %.3f (format expected on output)
std::string getFormattedDuration( double duration );
std::string serializeFilters( std::vector<std::string> const& container );
template<typename DerivedT>
struct StreamingReporterBase : IStreamingReporter {
@@ -52,6 +54,7 @@ namespace Catch {
void testRunStarting(TestRunInfo const& _testRunInfo) override {
currentTestRunInfo = _testRunInfo;
}
void testGroupStarting(GroupInfo const& _groupInfo) override {
currentGroupInfo = _groupInfo;
}

View File

@@ -441,6 +441,10 @@ void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {
stream << std::endl;
StreamingReporterBase::testRunEnded(_testRunStats);
}
void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) {
StreamingReporterBase::testRunStarting(_testInfo);
printTestFilters();
}
void ConsoleReporter::lazyPrint() {
@@ -622,6 +626,11 @@ void ConsoleReporter::printSummaryDivider() {
stream << getLineOfChars<'-'>() << '\n';
}
void ConsoleReporter::printTestFilters() {
if (m_config->testSpec().hasFilters())
stream << Colour(Colour::BrightYellow) << "Filters: " << serializeFilters( m_config->getTestsOrTags() ) << '\n';
}
CATCH_REGISTER_REPORTER("console", ConsoleReporter)
} // end namespace Catch

View File

@@ -46,7 +46,7 @@ namespace Catch {
void testCaseEnded(TestCaseStats const& _testCaseStats) override;
void testGroupEnded(TestGroupStats const& _testGroupStats) override;
void testRunEnded(TestRunStats const& _testRunStats) override;
void testRunStarting(TestRunInfo const& _testRunInfo) override;
private:
void lazyPrint();
@@ -69,6 +69,7 @@ namespace Catch {
void printTotalsDivider(Totals const& totals);
void printSummaryDivider();
void printTestFilters();
private:
bool m_headerPrinted = false;

View File

@@ -76,13 +76,6 @@ namespace Catch {
void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) {
CumulativeReporterBase::testRunStarting( runInfo );
xml.startElement( "testsuites" );
if( m_config->rngSeed() != 0 ) {
xml.startElement( "properties" );
xml.scopedElement( "property" )
.writeAttribute( "name", "random-seed" )
.writeAttribute( "value", m_config->rngSeed() );
xml.endElement();
}
}
void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {
@@ -121,6 +114,7 @@ namespace Catch {
void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
TestGroupStats const& stats = groupNode.value;
xml.writeAttribute( "name", stats.groupInfo.name );
xml.writeAttribute( "errors", unexpectedExceptions );
@@ -133,6 +127,21 @@ namespace Catch {
xml.writeAttribute( "time", suiteTime );
xml.writeAttribute( "timestamp", getCurrentTimestamp() );
// Write properties if there are any
if (m_config->hasTestFilters() || m_config->rngSeed() != 0) {
auto properties = xml.scopedElement("properties");
if (m_config->hasTestFilters()) {
xml.scopedElement("property")
.writeAttribute("name", "filters")
.writeAttribute("value", serializeFilters(m_config->getTestsOrTags()));
}
if (m_config->rngSeed() != 0) {
xml.scopedElement("property")
.writeAttribute("name", "random-seed")
.writeAttribute("value", m_config->rngSeed());
}
}
// Write test cases
for( auto const& child : groupNode.children )
writeTestCase( *child );

View File

@@ -55,6 +55,8 @@ namespace Catch {
m_xml.startElement( "Catch" );
if( !m_config->name().empty() )
m_xml.writeAttribute( "name", m_config->name() );
if (m_config->testSpec().hasFilters())
m_xml.writeAttribute( "filters", serializeFilters( m_config->getTestsOrTags() ) );
if( m_config->rngSeed() != 0 )
m_xml.scopedElement( "Randomness" )
.writeAttribute( "seed", m_config->rngSeed() );

View File

@@ -19,7 +19,7 @@ set(TEST_SOURCES
${SELF_TEST_DIR}/IntrospectiveTests/CmdLine.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/GeneratorsImpl.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/PartTracker.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/TagAlias.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/Tag.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/String.tests.cpp
${SELF_TEST_DIR}/IntrospectiveTests/Xml.tests.cpp
${SELF_TEST_DIR}/UsageTests/Approx.tests.cpp
@@ -322,6 +322,9 @@ endif()
# configure unit tests via CTest
add_test(NAME RunTests COMMAND $<TARGET_FILE:SelfTest>)
set_tests_properties(RunTests PROPERTIES
FAIL_REGULAR_EXPRESSION "Filters:"
)
add_test(NAME ListTests COMMAND $<TARGET_FILE:SelfTest> --list-tests --verbosity high)
set_tests_properties(ListTests PROPERTIES

View File

@@ -14,6 +14,9 @@ Compilation.tests.cpp:<line number>: passed: std::memcmp(uarr, "123", sizeof(uar
Compilation.tests.cpp:<line number>: passed: std::memcmp(sarr, "456", sizeof(sarr)) == 0 for: 0 == 0 with 2 messages: 'uarr := "123"' and 'sarr := "456"'
Compilation.tests.cpp:<line number>: passed:
Compilation.tests.cpp:<line number>: passed: h1 == h2 for: [1403 helper] == [1403 helper]
Message.tests.cpp:<line number>: warning: '
This info message starts with a linebreak' with 1 message: '
This warning message starts with a linebreak'
This would not be caught previously
Nor would this
Tricky.tests.cpp:<line number>: failed: explicitly with 1 message: '1514'
@@ -323,9 +326,9 @@ Matchers.tests.cpp:<line number>: passed: testStringForMatching(), Equals("this
Matchers.tests.cpp:<line number>: passed: testStringForMatching(), Equals("this string contains 'ABC' as a substring", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" equals: "this string contains 'abc' as a substring" (case insensitive)
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Equals("this string contains 'ABC' as a substring") for: "this string contains 'abc' as a substring" equals: "this string contains 'ABC' as a substring"
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), Equals("something else", Catch::CaseSensitive::No) for: "this string contains 'abc' as a substring" equals: "something else" (case insensitive)
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method" for: "This exception has overriden what() method"
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(WhatException{}) == "This exception has overridden what() method" for: "This exception has overridden what() method"
==
"This exception has overriden what() method"
"This exception has overridden what() method"
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(OperatorException{}) == "OperatorException" for: "OperatorException" == "OperatorException"
ToStringGeneral.tests.cpp:<line number>: passed: ::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException" for: "StringMakerException"
==
@@ -416,6 +419,9 @@ Generators.tests.cpp:<line number>: passed: i % 2 == 0 for: 0 == 0
Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
Generators.tests.cpp:<line number>: passed: i.size() == 1 for: 1 == 1
Generators.tests.cpp:<line number>: passed: j > 0 for: 1 > 0
Generators.tests.cpp:<line number>: passed: j > 0 for: 2 > 0
Generators.tests.cpp:<line number>: passed: j > 0 for: 3 > 0
@@ -495,6 +501,12 @@ GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 4.0 for: 4.0 == 4.0
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 6.0 for: 6.0 == 6.0
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 2.0 for: 2.0 == 2.0
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 4.0 for: 4.0 == 4.0
GeneratorsImpl.tests.cpp:<line number>: passed: gen.next() for: true
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 6.0 for: 6.0 == 6.0
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 3 for: 3 == 3
GeneratorsImpl.tests.cpp:<line number>: passed: !(gen.next()) for: !false
GeneratorsImpl.tests.cpp:<line number>: passed: gen.get() == 1 for: 1 == 1
@@ -628,6 +640,22 @@ Matchers.tests.cpp:<line number>: passed: testStringForMatching(), !Contains("di
Matchers.tests.cpp:<line number>: failed: testStringForMatching(), !Contains("substring") for: "this string contains 'abc' as a substring" not contains: "substring"
Exception.tests.cpp:<line number>: passed: thisThrows(), "expected exception" for: "expected exception" equals: "expected exception"
Exception.tests.cpp:<line number>: failed: thisThrows(), "should fail" for: "expected exception" equals: "should fail"
Generators.tests.cpp:<line number>: passed: values > -6 for: 3 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 4 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 5 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 6 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: -5 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: -4 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 90 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 91 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 92 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 93 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 94 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 95 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 96 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 97 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 98 > -6
Generators.tests.cpp:<line number>: passed: values > -6 for: 99 > -6
Misc.tests.cpp:<line number>: warning: 'This one ran'
Exception.tests.cpp:<line number>: failed: unexpected exception with message: 'custom exception'
Tricky.tests.cpp:<line number>: passed: True for: {?}
@@ -995,22 +1023,22 @@ Misc.tests.cpp:<line number>: failed: s1 == s2 for: "if ($b == 10) {
$a = 20;
}
"
TagAlias.tests.cpp:<line number>: passed: what, Contains( "[@zzz]" ) for: "error: tag alias, '[@zzz]' already registered.
Tag.tests.cpp:<line number>: passed: what, Contains( "[@zzz]" ) for: "error: tag alias, '[@zzz]' already registered.
First seen at: file:2
Redefined at: file:10" contains: "[@zzz]"
TagAlias.tests.cpp:<line number>: passed: what, Contains( "file" ) for: "error: tag alias, '[@zzz]' already registered.
Tag.tests.cpp:<line number>: passed: what, Contains( "file" ) for: "error: tag alias, '[@zzz]' already registered.
First seen at: file:2
Redefined at: file:10" contains: "file"
TagAlias.tests.cpp:<line number>: passed: what, Contains( "2" ) for: "error: tag alias, '[@zzz]' already registered.
Tag.tests.cpp:<line number>: passed: what, Contains( "2" ) for: "error: tag alias, '[@zzz]' already registered.
First seen at: file:2
Redefined at: file:10" contains: "2"
TagAlias.tests.cpp:<line number>: passed: what, Contains( "10" ) for: "error: tag alias, '[@zzz]' already registered.
Tag.tests.cpp:<line number>: passed: what, Contains( "10" ) for: "error: tag alias, '[@zzz]' already registered.
First seen at: file:2
Redefined at: file:10" contains: "10"
TagAlias.tests.cpp:<line number>: passed: registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) )
TagAlias.tests.cpp:<line number>: passed: registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) )
TagAlias.tests.cpp:<line number>: passed: registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) )
TagAlias.tests.cpp:<line number>: passed: registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) )
Tag.tests.cpp:<line number>: passed: registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) )
Tag.tests.cpp:<line number>: passed: registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) )
Tag.tests.cpp:<line number>: passed: registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) )
Tag.tests.cpp:<line number>: passed: registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) )
Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed: v.size() == 10 for: 10 == 10
@@ -1161,6 +1189,15 @@ Approx.tests.cpp:<line number>: passed: approx( d ) == 1.22 for: Approx( 1.23 )
Approx.tests.cpp:<line number>: passed: approx( d ) == 1.24 for: Approx( 1.23 ) == 1.24
Approx.tests.cpp:<line number>: passed: approx( d ) != 1.25 for: Approx( 1.23 ) != 1.25
VariadicMacros.tests.cpp:<line number>: passed: with 1 message: 'no assertions'
Matchers.tests.cpp:<line number>: passed: empty, Approx(empty) for: { } is approx: { }
Matchers.tests.cpp:<line number>: passed: v1, Approx(v1) for: { 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
Matchers.tests.cpp:<line number>: passed: v1, !Approx(temp) for: { 1.0, 2.0, 3.0 } not is approx: { 1.0, 2.0, 3.0, 4.0 }
Matchers.tests.cpp:<line number>: passed: v1, !Approx(v2) for: { 1.0, 2.0, 3.0 } not is approx: { 1.5, 2.5, 3.5 }
Matchers.tests.cpp:<line number>: passed: v1, Approx(v2).margin(0.5) for: { 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
Matchers.tests.cpp:<line number>: passed: v1, Approx(v2).epsilon(0.5) for: { 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
Matchers.tests.cpp:<line number>: passed: v1, Approx(v2).epsilon(0.1).scale(500) for: { 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
Matchers.tests.cpp:<line number>: failed: empty, Approx(t1) for: { } is approx: { 1.0, 2.0 }
Matchers.tests.cpp:<line number>: failed: v1, Approx(v2) for: { 2.0, 4.0, 6.0 } is approx: { 1.0, 3.0, 5.0 }
Matchers.tests.cpp:<line number>: passed: v, VectorContains(1) for: { 1, 2, 3 } Contains: 1
Matchers.tests.cpp:<line number>: passed: v, VectorContains(2) for: { 1, 2, 3 } Contains: 2
Matchers.tests.cpp:<line number>: passed: v, Contains(v2) for: { 1, 2, 3 } Contains: { 1, 2 }
@@ -1353,6 +1390,7 @@ String.tests.cpp:<line number>: passed: Catch::replaceInPlace( s, "'", "|'" ) fo
String.tests.cpp:<line number>: passed: s == "didn|'t" for: "didn|'t" == "didn|'t"
Misc.tests.cpp:<line number>: failed: false with 1 message: '3'
Message.tests.cpp:<line number>: failed: false with 2 messages: 'hi' and 'i := 7'
Tag.tests.cpp:<line number>: passed: testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")) for: { ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
Message.tests.cpp:<line number>: failed: false with 4 messages: 'Count 1 to 3...' and '1' and '2' and '3'
Message.tests.cpp:<line number>: failed: false with 4 messages: 'Count 4 to 6...' and '4' and '5' and '6'
ToStringGeneral.tests.cpp:<line number>: passed: Catch::Detail::stringify( emptyMap ) == "{ }" for: "{ }" == "{ }"
@@ -1476,5 +1514,5 @@ Misc.tests.cpp:<line number>: passed: v.size() == 5 for: 5 == 5
Misc.tests.cpp:<line number>: passed: v.capacity() >= 5 for: 5 >= 5
Misc.tests.cpp:<line number>: passed:
Misc.tests.cpp:<line number>: passed:
Failed 77 test cases, failed 138 assertions.
Failed 79 test cases, failed 141 assertions.

View File

@@ -1,5 +1,4 @@
This would not be caught previously
Nor would this
Filters: ~[!nonportable]~[!benchmark]~[approvals]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<exe-name> is a <version> host application.
@@ -7,6 +6,18 @@ Run with -? for options
Randomness seeded to: 1
-------------------------------------------------------------------------------
#1455 - INFO and WARN can start with a linebreak
-------------------------------------------------------------------------------
Message.tests.cpp:<line number>
...............................................................................
Message.tests.cpp:<line number>: warning:
This warning message starts with a linebreak
This would not be caught previously
Nor would this
-------------------------------------------------------------------------------
#1514: stderr/stdout is not captured in tests aborted by an exception
-------------------------------------------------------------------------------
@@ -850,6 +861,30 @@ Exception.tests.cpp:<line number>: FAILED:
due to unexpected exception with message:
3.14
-------------------------------------------------------------------------------
Vector Approx matcher -- failing
Empty and non empty vectors are not approx equal
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: FAILED:
CHECK_THAT( empty, Approx(t1) )
with expansion:
{ } is approx: { 1.0, 2.0 }
-------------------------------------------------------------------------------
Vector Approx matcher -- failing
Just different vectors
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: FAILED:
CHECK_THAT( v1, Approx(v2) )
with expansion:
{ 2.0, 4.0, 6.0 } is approx: { 1.0, 3.0, 5.0 }
-------------------------------------------------------------------------------
Vector matchers that fail
Contains (element)
@@ -1264,6 +1299,6 @@ due to unexpected exception with message:
Why would you throw a std::string?
===============================================================================
test cases: 255 | 189 passed | 62 failed | 4 failed as expected
assertions: 1393 | 1250 passed | 122 failed | 21 failed as expected
test cases: 260 | 193 passed | 63 failed | 4 failed as expected
assertions: 1428 | 1283 passed | 124 failed | 21 failed as expected

View File

@@ -1,3 +1,4 @@
Filters: ~[!nonportable]~[!benchmark]~[approvals]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<exe-name> is a <version> host application.
@@ -133,6 +134,21 @@ Compilation.tests.cpp:<line number>: PASSED:
with expansion:
[1403 helper] == [1403 helper]
-------------------------------------------------------------------------------
#1455 - INFO and WARN can start with a linebreak
-------------------------------------------------------------------------------
Message.tests.cpp:<line number>
...............................................................................
Message.tests.cpp:<line number>: warning:
This info message starts with a linebreak
This warning message starts with a linebreak
No assertions in test case '#1455 - INFO and WARN can start with a linebreak'
This would not be caught previously
Nor would this
-------------------------------------------------------------------------------
@@ -2390,11 +2406,11 @@ ToStringGeneral.tests.cpp:<line number>
...............................................................................
ToStringGeneral.tests.cpp:<line number>: PASSED:
REQUIRE( ::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method" )
REQUIRE( ::Catch::Detail::stringify(WhatException{}) == "This exception has overridden what() method" )
with expansion:
"This exception has overriden what() method"
"This exception has overridden what() method"
==
"This exception has overriden what() method"
"This exception has overridden what() method"
ToStringGeneral.tests.cpp:<line number>: PASSED:
REQUIRE( ::Catch::Detail::stringify(OperatorException{}) == "OperatorException" )
@@ -3040,6 +3056,45 @@ Generators -- adapters
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i.size() == 1 )
with expansion:
1 == 1
-------------------------------------------------------------------------------
Generators -- adapters
Transforming elements
Different deduced type
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i.size() == 1 )
with expansion:
1 == 1
-------------------------------------------------------------------------------
Generators -- adapters
Transforming elements
Different deduced type
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i.size() == 1 )
with expansion:
1 == 1
-------------------------------------------------------------------------------
Generators -- adapters
Transforming elements
Different deduced type
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( i.size() == 1 )
with expansion:
@@ -3675,7 +3730,44 @@ with expansion:
-------------------------------------------------------------------------------
Generators internals
Map
Map with explicit return type
-------------------------------------------------------------------------------
GeneratorsImpl.tests.cpp:<line number>
...............................................................................
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 2.0 )
with expansion:
2.0 == 2.0
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.next() )
with expansion:
true
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 4.0 )
with expansion:
4.0 == 4.0
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.next() )
with expansion:
true
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE( gen.get() == 6.0 )
with expansion:
6.0 == 6.0
GeneratorsImpl.tests.cpp:<line number>: PASSED:
REQUIRE_FALSE( gen.next() )
with expansion:
!false
-------------------------------------------------------------------------------
Generators internals
Map with deduced return type
-------------------------------------------------------------------------------
GeneratorsImpl.tests.cpp:<line number>
...............................................................................
@@ -4621,6 +4713,182 @@ Exception.tests.cpp:<line number>: FAILED:
with expansion:
"expected exception" equals: "should fail"
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
3 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
4 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
5 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
6 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
-5 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
-4 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
90 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
91 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
92 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
93 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
94 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
95 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
96 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
97 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
98 > -6
-------------------------------------------------------------------------------
Nested generators and captured variables
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
...............................................................................
Generators.tests.cpp:<line number>: PASSED:
REQUIRE( values > -6 )
with expansion:
99 > -6
-------------------------------------------------------------------------------
Nice descriptive name
-------------------------------------------------------------------------------
@@ -7239,31 +7507,31 @@ with expansion:
Tag alias can be registered against tag patterns
The same tag alias can only be registered once
-------------------------------------------------------------------------------
TagAlias.tests.cpp:<line number>
Tag.tests.cpp:<line number>
...............................................................................
TagAlias.tests.cpp:<line number>: PASSED:
Tag.tests.cpp:<line number>: PASSED:
CHECK_THAT( what, Contains( "[@zzz]" ) )
with expansion:
"error: tag alias, '[@zzz]' already registered.
First seen at: file:2
Redefined at: file:10" contains: "[@zzz]"
TagAlias.tests.cpp:<line number>: PASSED:
Tag.tests.cpp:<line number>: PASSED:
CHECK_THAT( what, Contains( "file" ) )
with expansion:
"error: tag alias, '[@zzz]' already registered.
First seen at: file:2
Redefined at: file:10" contains: "file"
TagAlias.tests.cpp:<line number>: PASSED:
Tag.tests.cpp:<line number>: PASSED:
CHECK_THAT( what, Contains( "2" ) )
with expansion:
"error: tag alias, '[@zzz]' already registered.
First seen at: file:2
Redefined at: file:10" contains: "2"
TagAlias.tests.cpp:<line number>: PASSED:
Tag.tests.cpp:<line number>: PASSED:
CHECK_THAT( what, Contains( "10" ) )
with expansion:
"error: tag alias, '[@zzz]' already registered.
@@ -7274,19 +7542,19 @@ with expansion:
Tag alias can be registered against tag patterns
Tag aliases must be of the form [@name]
-------------------------------------------------------------------------------
TagAlias.tests.cpp:<line number>
Tag.tests.cpp:<line number>
...............................................................................
TagAlias.tests.cpp:<line number>: PASSED:
Tag.tests.cpp:<line number>: PASSED:
CHECK_THROWS( registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) ) )
TagAlias.tests.cpp:<line number>: PASSED:
Tag.tests.cpp:<line number>: PASSED:
CHECK_THROWS( registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) ) )
TagAlias.tests.cpp:<line number>: PASSED:
Tag.tests.cpp:<line number>: PASSED:
CHECK_THROWS( registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) ) )
TagAlias.tests.cpp:<line number>: PASSED:
Tag.tests.cpp:<line number>: PASSED:
CHECK_THROWS( registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) )
-------------------------------------------------------------------------------
@@ -8452,6 +8720,96 @@ VariadicMacros.tests.cpp:<line number>: PASSED:
with message:
no assertions
-------------------------------------------------------------------------------
Vector Approx matcher
Empty vector is roughly equal to an empty vector
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( empty, Approx(empty) )
with expansion:
{ } is approx: { }
-------------------------------------------------------------------------------
Vector Approx matcher
Vectors with elements
A vector is approx equal to itself
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( v1, Approx(v1) )
with expansion:
{ 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
-------------------------------------------------------------------------------
Vector Approx matcher
Vectors with elements
Different length
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( v1, !Approx(temp) )
with expansion:
{ 1.0, 2.0, 3.0 } not is approx: { 1.0, 2.0, 3.0, 4.0 }
-------------------------------------------------------------------------------
Vector Approx matcher
Vectors with elements
Same length, different elements
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( v1, !Approx(v2) )
with expansion:
{ 1.0, 2.0, 3.0 } not is approx: { 1.5, 2.5, 3.5 }
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( v1, Approx(v2).margin(0.5) )
with expansion:
{ 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( v1, Approx(v2).epsilon(0.5) )
with expansion:
{ 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
Matchers.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( v1, Approx(v2).epsilon(0.1).scale(500) )
with expansion:
{ 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
-------------------------------------------------------------------------------
Vector Approx matcher -- failing
Empty and non empty vectors are not approx equal
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: FAILED:
CHECK_THAT( empty, Approx(t1) )
with expansion:
{ } is approx: { 1.0, 2.0 }
-------------------------------------------------------------------------------
Vector Approx matcher -- failing
Just different vectors
-------------------------------------------------------------------------------
Matchers.tests.cpp:<line number>
...............................................................................
Matchers.tests.cpp:<line number>: FAILED:
CHECK_THAT( v1, Approx(v2) )
with expansion:
{ 2.0, 4.0, 6.0 } is approx: { 1.0, 3.0, 5.0 }
-------------------------------------------------------------------------------
Vector matchers
Contains (element)
@@ -10008,6 +10366,17 @@ with messages:
hi
i := 7
-------------------------------------------------------------------------------
shortened hide tags are split apart
-------------------------------------------------------------------------------
Tag.tests.cpp:<line number>
...............................................................................
Tag.tests.cpp:<line number>: PASSED:
REQUIRE_THAT( testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")) )
with expansion:
{ ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
-------------------------------------------------------------------------------
stacks unscoped info in loops
-------------------------------------------------------------------------------
@@ -10849,6 +11218,6 @@ Misc.tests.cpp:<line number>
Misc.tests.cpp:<line number>: PASSED:
===============================================================================
test cases: 255 | 174 passed | 77 failed | 4 failed as expected
assertions: 1409 | 1250 passed | 138 failed | 21 failed as expected
test cases: 260 | 177 passed | 79 failed | 4 failed as expected
assertions: 1445 | 1283 passed | 141 failed | 21 failed as expected

View File

@@ -1,3 +1,4 @@
Filters: ~[!nonportable]~[!benchmark]~[approvals]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<exe-name> is a <version> host application.
@@ -133,6 +134,21 @@ Compilation.tests.cpp:<line number>: PASSED:
with expansion:
[1403 helper] == [1403 helper]
-------------------------------------------------------------------------------
#1455 - INFO and WARN can start with a linebreak
-------------------------------------------------------------------------------
Message.tests.cpp:<line number>
...............................................................................
Message.tests.cpp:<line number>: warning:
This info message starts with a linebreak
This warning message starts with a linebreak
No assertions in test case '#1455 - INFO and WARN can start with a linebreak'
This would not be caught previously
Nor would this
-------------------------------------------------------------------------------
@@ -335,12 +351,7 @@ Condition.tests.cpp:<line number>: FAILED:
Condition.tests.cpp:<line number>: FAILED:
CHECK( true != true )
Condition.tests.cpp:<line number>: FAILED:
CHECK( !true )
with expansion:
false
===============================================================================
test cases: 17 | 13 passed | 2 failed | 2 failed as expected
test cases: 18 | 13 passed | 3 failed | 2 failed as expected
assertions: 40 | 33 passed | 4 failed | 3 failed as expected

View File

@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<testsuites>
<properties>
<property name="random-seed" value="1"/>
</properties>
loose text artifact
<testsuite name="<exe-name>" errors="17" failures="122" tests="1410" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<testsuitesloose text artifact
>
<testsuite name="<exe-name>" errors="17" failures="125" tests="1446" hostname="tbd" time="{duration}" timestamp="{iso8601-timestamp}">
<properties>
<property name="filters" value="~[!nonportable]~[!benchmark]~[approvals]"/>
<property name="random-seed" value="1"/>
</properties>
<testcase classname="<exe-name>.global" name="# A test name that starts with a #" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1005: Comparing pointer to int and long (NULL can be either on various systems)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1027" time="{duration}"/>
@@ -13,6 +14,7 @@ loose text artifact
<testcase classname="<exe-name>.global" name="#1238" time="{duration}"/>
<testcase classname="<exe-name>.(Fixture_1245&lt;int, int>)" name="#1245" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1403" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1455 - INFO and WARN can start with a linebreak" time="{duration}"/>
<testcase classname="<exe-name>.global" name="#1514: stderr/stdout is not captured in tests aborted by an exception" time="{duration}">
<failure type="FAIL">
1514
@@ -360,6 +362,7 @@ Message.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Generators -- adapters/Shortening a range" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- adapters/Transforming elements/Same type" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- adapters/Transforming elements/Different type" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- adapters/Transforming elements/Different deduced type" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- adapters/Repeating a generator" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- adapters/Chunking a generator into sized pieces/Number of elements in source is divisible by chunk size" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators -- adapters/Chunking a generator into sized pieces/Number of elements in source is not divisible by chunk size" time="{duration}"/>
@@ -373,7 +376,8 @@ Message.tests.cpp:<line number>
<testcase classname="<exe-name>.global" name="Generators internals/Filter generator" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Take generator/Take less" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Take generator/Take more" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Map" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Map with explicit return type" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Map with deduced return type" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Repeat/Singular repeat" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Repeat/Actual repeat" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Generators internals/Range/Positive auto step/Integer" time="{duration}"/>
@@ -452,6 +456,7 @@ Matchers.tests.cpp:<line number>
Exception.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.global" name="Nested generators and captured variables" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Nice descriptive name" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Non-std exceptions can be translated" time="{duration}">
<error type="TEST_CASE">
@@ -736,6 +741,20 @@ Exception.tests.cpp:<line number>
</testcase>
<testcase classname="<exe-name>.global" name="Use a custom approx" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Variadic macros/Section with one argument" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Vector Approx matcher/Empty vector is roughly equal to an empty vector" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Vector Approx matcher/Vectors with elements/A vector is approx equal to itself" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Vector Approx matcher/Vectors with elements/Different length" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Vector Approx matcher/Vectors with elements/Same length, different elements" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Vector Approx matcher -- failing/Empty and non empty vectors are not approx equal" time="{duration}">
<failure message="{ } is approx: { 1.0, 2.0 }" type="CHECK_THAT">
Matchers.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.global" name="Vector Approx matcher -- failing/Just different vectors" time="{duration}">
<failure message="{ 2.0, 4.0, 6.0 } is approx: { 1.0, 3.0, 5.0 }" type="CHECK_THAT">
Matchers.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.global" name="Vector matchers/Contains (element)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Vector matchers/Contains (vector)" time="{duration}"/>
<testcase classname="<exe-name>.global" name="Vector matchers/Contains (element), composed" time="{duration}"/>
@@ -978,6 +997,7 @@ i := 7
Message.tests.cpp:<line number>
</failure>
</testcase>
<testcase classname="<exe-name>.global" name="shortened hide tags are split apart" time="{duration}"/>
<testcase classname="<exe-name>.global" name="stacks unscoped info in loops" time="{duration}">
<failure message="false" type="CHECK">
Count 1 to 3...

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<Catch name="<exe-name>">
<Catch name="<exe-name>" filters="~[!nonportable]~[!benchmark]~[approvals]">
<Randomness seed="1"/>
<Group name="<exe-name>">
<TestCase name="# A test name that starts with a #" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
@@ -142,6 +142,17 @@
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="#1455 - INFO and WARN can start with a linebreak" tags="[.][messages]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
<Info>
This info message starts with a linebreak
</Info>
<Warning>
This warning message starts with a linebreak
</Warning>
<OverallResult success="false"/>
</TestCase>
<TestCase name="#1514: stderr/stdout is not captured in tests aborted by an exception" tags="[.][output-capture][regression]" filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
<Failure filename="projects/<exe-name>/UsageTests/Tricky.tests.cpp" >
1514
@@ -2888,12 +2899,12 @@ Nor would this
<TestCase name="Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified" tags="[exception][toString]" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
<Original>
::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method"
::Catch::Detail::stringify(WhatException{}) == "This exception has overridden what() method"
</Original>
<Expanded>
"This exception has overriden what() method"
"This exception has overridden what() method"
==
"This exception has overriden what() method"
"This exception has overridden what() method"
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/ToStringGeneral.tests.cpp" >
@@ -2916,7 +2927,7 @@ Nor would this
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Exception matchers that fail" tags="[!throws][.][.failing][exceptions][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<TestCase name="Exception matchers that fail" tags="[!throws][.][exceptions][failing][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Section name="No exception" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="false" type="CHECK_THROWS_MATCHES" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
@@ -3736,6 +3747,48 @@ Nor would this
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Section name="Different deduced type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i.size() == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Section name="Different deduced type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i.size() == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Transforming elements" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Section name="Different deduced type" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
i.size() == 1
</Original>
<Expanded>
1 == 1
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Repeating a generator" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
@@ -4461,7 +4514,58 @@ Nor would this
</Section>
<OverallResults successes="2" failures="0" expectedFailures="0"/>
</Section>
<Section name="Map" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Section name="Map with explicit return type" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 2.0
</Original>
<Expanded>
2.0 == 2.0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.next()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 4.0
</Original>
<Expanded>
4.0 == 4.0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.next()
</Original>
<Expanded>
true
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 6.0
</Original>
<Expanded>
6.0 == 6.0
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_FALSE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
!(gen.next())
</Original>
<Expanded>
!false
</Expanded>
</Expression>
<OverallResults successes="6" failures="0" expectedFailures="0"/>
</Section>
<Section name="Map with deduced return type" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/IntrospectiveTests/GeneratorsImpl.tests.cpp" >
<Original>
gen.get() == 2.0
@@ -5768,7 +5872,7 @@ Nor would this
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Matchers can be composed with both &amp;&amp; and || - failing" tags="[.][.failing][matchers][operator&amp;&amp;][operators][operator||]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<TestCase name="Matchers can be composed with both &amp;&amp; and || - failing" tags="[.][failing][matchers][operator&amp;&amp;][operators][operator||]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
testStringForMatching(), (Contains("string") || Contains("different")) &amp;&amp; Contains("random")
@@ -5790,7 +5894,7 @@ Nor would this
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Matchers can be negated (Not) with the ! operator - failing" tags="[.][.failing][matchers][not][operators]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<TestCase name="Matchers can be negated (Not) with the ! operator - failing" tags="[.][failing][matchers][not][operators]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
testStringForMatching(), !Contains("substring")
@@ -5820,6 +5924,137 @@ Nor would this
</Expression>
<OverallResult success="false"/>
</TestCase>
<TestCase name="Nested generators and captured variables" tags="[generators]" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
3 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
4 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
5 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
6 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
-5 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
-4 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
90 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
91 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
92 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
93 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
94 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
95 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
96 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
97 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
98 > -6
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE" filename="projects/<exe-name>/UsageTests/Generators.tests.cpp" >
<Original>
values > -6
</Original>
<Expanded>
99 > -6
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Nice descriptive name" tags="[.][tag1][tag2][tag3]" filename="projects/<exe-name>/UsageTests/Misc.tests.cpp" >
<Warning>
This one ran
@@ -8112,7 +8347,7 @@ Nor would this
</Expression>
<OverallResult success="false"/>
</TestCase>
<TestCase name="Regex string matcher" tags="[.][.failing][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<TestCase name="Regex string matcher" tags="[.][failing][matchers]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
testStringForMatching(), Matches("this STRING contains 'abc' as a substring")
@@ -9093,9 +9328,9 @@ Message from section two
</Expression>
<OverallResult success="false"/>
</TestCase>
<TestCase name="Tag alias can be registered against tag patterns" filename="projects/<exe-name>/IntrospectiveTests/TagAlias.tests.cpp" >
<Section name="The same tag alias can only be registered once" filename="projects/<exe-name>/IntrospectiveTests/TagAlias.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/IntrospectiveTests/TagAlias.tests.cpp" >
<TestCase name="Tag alias can be registered against tag patterns" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Section name="The same tag alias can only be registered once" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Original>
what, Contains( "[@zzz]" )
</Original>
@@ -9105,7 +9340,7 @@ Message from section two
Redefined at: file:10" contains: "[@zzz]"
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/IntrospectiveTests/TagAlias.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Original>
what, Contains( "file" )
</Original>
@@ -9115,7 +9350,7 @@ Message from section two
Redefined at: file:10" contains: "file"
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/IntrospectiveTests/TagAlias.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Original>
what, Contains( "2" )
</Original>
@@ -9125,7 +9360,7 @@ Message from section two
Redefined at: file:10" contains: "2"
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/IntrospectiveTests/TagAlias.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Original>
what, Contains( "10" )
</Original>
@@ -9137,8 +9372,8 @@ Message from section two
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<Section name="Tag aliases must be of the form [@name]" filename="projects/<exe-name>/IntrospectiveTests/TagAlias.tests.cpp" >
<Expression success="true" type="CHECK_THROWS" filename="projects/<exe-name>/IntrospectiveTests/TagAlias.tests.cpp" >
<Section name="Tag aliases must be of the form [@name]" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Expression success="true" type="CHECK_THROWS" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Original>
registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) )
</Original>
@@ -9146,7 +9381,7 @@ Message from section two
registry.add( "[no ampersat]", "", Catch::SourceLineInfo( "file", 3 ) )
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THROWS" filename="projects/<exe-name>/IntrospectiveTests/TagAlias.tests.cpp" >
<Expression success="true" type="CHECK_THROWS" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Original>
registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) )
</Original>
@@ -9154,7 +9389,7 @@ Message from section two
registry.add( "[the @ is not at the start]", "", Catch::SourceLineInfo( "file", 3 ) )
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THROWS" filename="projects/<exe-name>/IntrospectiveTests/TagAlias.tests.cpp" >
<Expression success="true" type="CHECK_THROWS" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Original>
registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) )
</Original>
@@ -9162,7 +9397,7 @@ Message from section two
registry.add( "@no square bracket at start]", "", Catch::SourceLineInfo( "file", 3 ) )
</Expanded>
</Expression>
<Expression success="true" type="CHECK_THROWS" filename="projects/<exe-name>/IntrospectiveTests/TagAlias.tests.cpp" >
<Expression success="true" type="CHECK_THROWS" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Original>
registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) )
</Original>
@@ -10478,6 +10713,111 @@ Message from section two
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Vector Approx matcher" tags="[approx][matchers][vector]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Section name="Empty vector is roughly equal to an empty vector" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
empty, Approx(empty)
</Original>
<Expanded>
{ } is approx: { }
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Vectors with elements" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Section name="A vector is approx equal to itself" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v1, Approx(v1)
</Original>
<Expanded>
{ 1.0, 2.0, 3.0 } is approx: { 1.0, 2.0, 3.0 }
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Vectors with elements" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Section name="Different length" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v1, !Approx(temp)
</Original>
<Expanded>
{ 1.0, 2.0, 3.0 } not is approx: { 1.0, 2.0, 3.0, 4.0 }
</Expanded>
</Expression>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="1" failures="0" expectedFailures="0"/>
</Section>
<Section name="Vectors with elements" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Section name="Same length, different elements" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v1, !Approx(v2)
</Original>
<Expanded>
{ 1.0, 2.0, 3.0 } not is approx: { 1.5, 2.5, 3.5 }
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v1, Approx(v2).margin(0.5)
</Original>
<Expanded>
{ 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v1, Approx(v2).epsilon(0.5)
</Original>
<Expanded>
{ 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
</Expanded>
</Expression>
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v1, Approx(v2).epsilon(0.1).scale(500)
</Original>
<Expanded>
{ 1.0, 2.0, 3.0 } is approx: { 1.5, 2.5, 3.5 }
</Expanded>
</Expression>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<OverallResults successes="4" failures="0" expectedFailures="0"/>
</Section>
<OverallResult success="true"/>
</TestCase>
<TestCase name="Vector Approx matcher -- failing" tags="[.][approx][failing][matchers][vector]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Section name="Empty and non empty vectors are not approx equal" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
empty, Approx(t1)
</Original>
<Expanded>
{ } is approx: { 1.0, 2.0 }
</Expanded>
</Expression>
<OverallResults successes="0" failures="1" expectedFailures="0"/>
</Section>
<Section name="Just different vectors" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="false" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Original>
v1, Approx(v2)
</Original>
<Expanded>
{ 2.0, 4.0, 6.0 } is approx: { 1.0, 3.0, 5.0 }
</Expanded>
</Expression>
<OverallResults successes="0" failures="1" expectedFailures="0"/>
</Section>
<OverallResult success="false"/>
</TestCase>
<TestCase name="Vector matchers" tags="[matchers][vector]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Section name="Contains (element)" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
<Expression success="true" type="CHECK_THAT" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" >
@@ -12259,6 +12599,17 @@ loose text artifact
</Expression>
<OverallResult success="false"/>
</TestCase>
<TestCase name="shortened hide tags are split apart" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Expression success="true" type="REQUIRE_THAT" filename="projects/<exe-name>/IntrospectiveTests/Tag.tests.cpp" >
<Original>
testcase.tags, Catch::VectorContains(std::string("magic-tag")) &amp;&amp; Catch::VectorContains(std::string("."))
</Original>
<Expanded>
{ ".", "magic-tag" } ( Contains: "magic-tag" and Contains: "." )
</Expanded>
</Expression>
<OverallResult success="true"/>
</TestCase>
<TestCase name="stacks unscoped info in loops" tags="[.][failing][info][unscoped]" filename="projects/<exe-name>/UsageTests/Message.tests.cpp" >
<Info>
Count 1 to 3...
@@ -13153,7 +13504,7 @@ loose text artifact
</Section>
<OverallResult success="true"/>
</TestCase>
<OverallResults successes="1250" failures="139" expectedFailures="21"/>
<OverallResults successes="1283" failures="142" expectedFailures="21"/>
</Group>
<OverallResults successes="1250" failures="138" expectedFailures="21"/>
<OverallResults successes="1283" failures="141" expectedFailures="21"/>
</Catch>

View File

@@ -68,7 +68,7 @@ TEST_CASE("Generators internals", "[generators][internals]") {
REQUIRE_FALSE(gen.next());
}
}
SECTION("Map") {
SECTION("Map with explicit return type") {
auto gen = map<double>([] (int i) {return 2.0 * i; }, values({ 1, 2, 3 }));
REQUIRE(gen.get() == 2.0);
REQUIRE(gen.next());
@@ -77,6 +77,15 @@ TEST_CASE("Generators internals", "[generators][internals]") {
REQUIRE(gen.get() == 6.0);
REQUIRE_FALSE(gen.next());
}
SECTION("Map with deduced return type") {
auto gen = map([] (int i) {return 2.0 * i; }, values({ 1, 2, 3 }));
REQUIRE(gen.get() == 2.0);
REQUIRE(gen.next());
REQUIRE(gen.get() == 4.0);
REQUIRE(gen.next());
REQUIRE(gen.get() == 6.0);
REQUIRE_FALSE(gen.next());
}
SECTION("Repeat") {
SECTION("Singular repeat") {
auto gen = repeat(1, value(3));
@@ -207,3 +216,45 @@ TEST_CASE("Generators internals", "[generators][internals]") {
}
}
// todo: uncopyable type used in a generator
// idea: uncopyable tag type for a stupid generator
namespace {
struct non_copyable {
non_copyable() = default;
non_copyable(non_copyable const&) = delete;
non_copyable& operator=(non_copyable const&) = delete;
int value = -1;
};
// This class shows how to implement a simple generator for Catch tests
class TestGen : public Catch::Generators::IGenerator<int> {
int current_number;
public:
TestGen(non_copyable const& nc):
current_number(nc.value) {}
int const& get() const override;
bool next() override {
return false;
}
};
// Avoids -Wweak-vtables
int const& TestGen::get() const {
return current_number;
}
}
TEST_CASE("GENERATE capture macros", "[generators][internals][.approvals]") {
auto value = GENERATE(take(10, random(0, 10)));
non_copyable nc; nc.value = value;
// neither `GENERATE_COPY` nor plain `GENERATE` would compile here
auto value2 = GENERATE_REF(Catch::Generators::GeneratorWrapper<int>(std::unique_ptr<Catch::Generators::IGenerator<int>>(new TestGen(nc))));
REQUIRE(value == value2);
}

View File

@@ -8,21 +8,6 @@
#include "internal/catch_suppress_warnings.h"
#include "internal/catch_test_case_tracker.h"
namespace Catch
{
class LocalContext {
public:
TrackerContext& operator()() const {
return TrackerContext::instance();
}
};
} // namespace Catch
// -------------------
#include "catch.hpp"
using namespace Catch;

View File

@@ -40,3 +40,8 @@ TEST_CASE( "Tag alias can be registered against tag patterns" ) {
CHECK_THROWS( registry.add( "[@no square bracket at end", "", Catch::SourceLineInfo( "file", 3 ) ) );
}
}
TEST_CASE("shortened hide tags are split apart") {
auto testcase = Catch::makeTestCase(nullptr, "", {"fake test name", "[.magic-tag]"}, CATCH_INTERNAL_LINEINFO);
REQUIRE_THAT(testcase.tags, Catch::VectorContains(std::string("magic-tag")) && Catch::VectorContains(std::string(".")));
}

View File

@@ -144,6 +144,11 @@ TEST_CASE("Generators -- adapters", "[generators][generic]") {
auto i = GENERATE(map<std::string>([] (int val) { return std::to_string(val); }, values({ 1, 2, 3 })));
REQUIRE(i.size() == 1);
}
SECTION("Different deduced type") {
// This takes a generator that returns ints and maps them into strings
auto i = GENERATE(map([] (int val) { return std::to_string(val); }, values({ 1, 2, 3 })));
REQUIRE(i.size() == 1);
}
}
SECTION("Repeating a generator") {
// This will return values [1, 2, 3, 1, 2, 3]
@@ -183,3 +188,21 @@ TEST_CASE("Random generator", "[generators][.][approvals]") {
static_cast<void>(val); // Silence VS 2015 unused variable warning
}
}
TEST_CASE("Nested generators and captured variables", "[generators]") {
// Workaround for old libstdc++
using record = std::tuple<int, int>;
// Set up 3 ranges to generate numbers from
auto extent = GENERATE(table<int, int>({
record{3, 7},
record{-5, -3},
record{90, 100}
}));
auto from = std::get<0>(extent);
auto to = std::get<1>(extent);
auto values = GENERATE_COPY(range(from, to));
REQUIRE(values > -6);
}

View File

@@ -213,6 +213,16 @@ namespace { namespace MatchersTests {
v2.push_back(1);
v2.push_back(2);
std::vector<double> v3;
v3.push_back(1);
v3.push_back(2);
v3.push_back(3);
std::vector<double> v4;
v4.push_back(1 + 1e-8);
v4.push_back(2 + 1e-8);
v4.push_back(3 + 1e-8);
std::vector<int> empty;
SECTION("Contains (element)") {
@@ -265,6 +275,16 @@ namespace { namespace MatchersTests {
v2.push_back(1);
v2.push_back(2);
std::vector<double> v3;
v3.push_back(1);
v3.push_back(2);
v3.push_back(3);
std::vector<double> v4;
v4.push_back(1.1);
v4.push_back(2.1);
v4.push_back(3.1);
std::vector<int> empty;
SECTION("Contains (element)") {
@@ -436,6 +456,44 @@ namespace { namespace MatchersTests {
REQUIRE_THAT("foo", Predicate<const char*>([] (const char* const&) { return true; }));
}
TEST_CASE("Vector Approx matcher", "[matchers][approx][vector]") {
using Catch::Matchers::Approx;
SECTION("Empty vector is roughly equal to an empty vector") {
std::vector<double> empty;
REQUIRE_THAT(empty, Approx(empty));
}
SECTION("Vectors with elements") {
std::vector<double> v1({1., 2., 3.});
SECTION("A vector is approx equal to itself") {
REQUIRE_THAT(v1, Approx(v1));
}
std::vector<double> v2({1.5, 2.5, 3.5});
SECTION("Different length") {
auto temp(v1);
temp.push_back(4);
REQUIRE_THAT(v1, !Approx(temp));
}
SECTION("Same length, different elements") {
REQUIRE_THAT(v1, !Approx(v2));
REQUIRE_THAT(v1, Approx(v2).margin(0.5));
REQUIRE_THAT(v1, Approx(v2).epsilon(0.5));
REQUIRE_THAT(v1, Approx(v2).epsilon(0.1).scale(500));
}
}
}
TEST_CASE("Vector Approx matcher -- failing", "[matchers][approx][vector][.failing]") {
using Catch::Matchers::Approx;
SECTION("Empty and non empty vectors are not approx equal") {
std::vector<double> empty, t1({1, 2});
CHECK_THAT(empty, Approx(t1));
}
SECTION("Just different vectors") {
std::vector<double> v1({2., 4., 6.}), v2({1., 3., 5.});
CHECK_THAT(v1, Approx(v2));
}
}
} } // namespace MatchersTests
#endif // CATCH_CONFIG_DISABLE_MATCHERS

View File

@@ -14,6 +14,13 @@ TEST_CASE( "INFO and WARN do not abort tests", "[messages][.]" ) {
WARN( "this is a " << "warning" ); // This should always output the message but then continue
}
TEST_CASE( "#1455 - INFO and WARN can start with a linebreak", "[messages][.]" ) {
// Previously these would be hidden from the console reporter output,
// because it would fail at properly reflowing the text
INFO( "\nThis info message starts with a linebreak" );
WARN( "\nThis warning message starts with a linebreak" );
}
TEST_CASE( "SUCCEED counts as a test pass", "[messages]" ) {
SUCCEED( "this is a " << "success" );
}
@@ -220,9 +227,9 @@ TEST_CASE( "CAPTURE can deal with complex expressions", "[messages][capture]" )
template <typename T1, typename T2>
struct helper_1436 {
helper_1436(T1 t1, T2 t2):
t1{ t1 },
t2{ t2 }
helper_1436(T1 t1_, T2 t2_):
t1{ t1_ },
t2{ t2_ }
{}
T1 t1;
T2 t2;

View File

@@ -132,7 +132,7 @@ namespace {
struct WhatException : std::exception {
char const* what() const noexcept override {
return "This exception has overriden what() method";
return "This exception has overridden what() method";
}
~WhatException() override;
};
@@ -170,7 +170,7 @@ StringMakerException::~StringMakerException() = default;
TEST_CASE("Exception as a value (e.g. in REQUIRE_THROWS_MATCHES) can be stringified", "[toString][exception]") {
REQUIRE(::Catch::Detail::stringify(WhatException{}) == "This exception has overriden what() method");
REQUIRE(::Catch::Detail::stringify(WhatException{}) == "This exception has overridden what() method");
REQUIRE(::Catch::Detail::stringify(OperatorException{}) == "OperatorException");
REQUIRE(::Catch::Detail::stringify(StringMakerException{}) == "StringMakerException");
}

View File

@@ -70,7 +70,7 @@ OC_TEST_CASE( "Matches work with OC types (NSString so far)", "[!shouldfail]" )
{
using namespace Catch::Matchers;
REQUIRE_THAT( @"This is a string", Equals( @"This isnt a string" ) );
REQUIRE_THAT( @"This is a string", Equals( @"This isn't a string" ) );
REQUIRE_THAT( @"This is a string", Contains( @"is a" ) );
REQUIRE_THAT( @"This is a string", StartsWith( @"This" ) );
REQUIRE_THAT( @"This is a string", EndsWith( @"string" ) );

View File

@@ -1,6 +1,6 @@
/*
* Catch v2.7.0
* Generated: 2019-03-07 21:34:30.252164
* Catch v2.7.2
* Generated: 2019-04-22 23:13:14.687465
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2019 Two Blue Cubes Ltd. All rights reserved.
@@ -15,7 +15,7 @@
#define CATCH_VERSION_MAJOR 2
#define CATCH_VERSION_MINOR 7
#define CATCH_VERSION_PATCH 0
#define CATCH_VERSION_PATCH 2
#ifdef __clang__
# pragma clang system_header
@@ -3113,7 +3113,7 @@ public:
// The following functions create the actual matcher objects.
// The user has to explicitly specify type to the function, because
// infering std::function<bool(T const&)> is hard (but possible) and
// inferring std::function<bool(T const&)> is hard (but possible) and
// requires a lot of TMP.
template<typename T>
Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {
@@ -3201,28 +3201,6 @@ namespace Catch {
namespace Matchers {
namespace Vector {
namespace Detail {
template <typename InputIterator, typename T>
size_t count(InputIterator first, InputIterator last, T const& item) {
size_t cnt = 0;
for (; first != last; ++first) {
if (*first == item) {
++cnt;
}
}
return cnt;
}
template <typename InputIterator, typename T>
bool contains(InputIterator first, InputIterator last, T const& item) {
for (; first != last; ++first) {
if (*first == item) {
return true;
}
}
return false;
}
}
template<typename T>
struct ContainsElementMatcher : MatcherBase<std::vector<T>> {
@@ -3297,6 +3275,42 @@ namespace Matchers {
std::vector<T> const& m_comparator;
};
template<typename T>
struct ApproxMatcher : MatcherBase<std::vector<T>> {
ApproxMatcher(std::vector<T> const& comparator) : m_comparator( comparator ) {}
bool match(std::vector<T> const &v) const override {
if (m_comparator.size() != v.size())
return false;
for (std::size_t i = 0; i < v.size(); ++i)
if (m_comparator[i] != approx(v[i]))
return false;
return true;
}
std::string describe() const override {
return "is approx: " + ::Catch::Detail::stringify( m_comparator );
}
template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
ApproxMatcher& epsilon( T const& newEpsilon ) {
approx.epsilon(newEpsilon);
return *this;
}
template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
ApproxMatcher& margin( T const& newMargin ) {
approx.margin(newMargin);
return *this;
}
template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
ApproxMatcher& scale( T const& newScale ) {
approx.scale(newScale);
return *this;
}
std::vector<T> const& m_comparator;
mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();
};
template<typename T>
struct UnorderedEqualsMatcher : MatcherBase<std::vector<T>> {
UnorderedEqualsMatcher(std::vector<T> const& target) : m_target(target) {}
@@ -3306,28 +3320,7 @@ namespace Matchers {
if (m_target.size() != vec.size()) {
return false;
}
auto lfirst = m_target.begin(), llast = m_target.end();
auto rfirst = vec.begin(), rlast = vec.end();
// Cut common prefix to optimize checking of permuted parts
while (lfirst != llast && *lfirst == *rfirst) {
++lfirst; ++rfirst;
}
if (lfirst == llast) {
return true;
}
for (auto mid = lfirst; mid != llast; ++mid) {
// Skip already counted items
if (Detail::contains(lfirst, mid, *mid)) {
continue;
}
size_t num_vec = Detail::count(rfirst, rlast, *mid);
if (num_vec == 0 || Detail::count(lfirst, llast, *mid) != num_vec) {
return false;
}
}
return true;
return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());
}
std::string describe() const override {
@@ -3357,6 +3350,11 @@ namespace Matchers {
return Vector::EqualsMatcher<T>( comparator );
}
template<typename T>
Vector::ApproxMatcher<T> Approx( std::vector<T> const& comparator ) {
return Vector::ApproxMatcher<T>( comparator );
}
template<typename T>
Vector::UnorderedEqualsMatcher<T> UnorderedEquals(std::vector<T> const& target) {
return Vector::UnorderedEqualsMatcher<T>(target);
@@ -3686,7 +3684,11 @@ namespace Generators {
} // namespace Catch
#define GENERATE( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, []{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
#define GENERATE_COPY( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
#define GENERATE_REF( ... ) \
Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
// end catch_generators.hpp
// start catch_generators_generic.hpp
@@ -3849,16 +3851,28 @@ namespace Generators {
}
};
template <typename T, typename U, typename Func>
#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
// std::result_of is deprecated in C++17 and removed in C++20. Hence, it is
// replaced with std::invoke_result here. Also *_t format is preferred over
// typename *::type format.
template <typename Func, typename U>
using MapFunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U>>>;
#else
template <typename Func, typename U>
using MapFunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U)>::type>::type>::type;
#endif
template <typename Func, typename U, typename T = MapFunctionReturnType<Func, U>>
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
return GeneratorWrapper<T>(
pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
);
}
template <typename T, typename Func>
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<T>&& generator) {
template <typename T, typename U, typename Func>
GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
return GeneratorWrapper<T>(
pf::make_unique<MapGenerator<T, T, Func>>(std::forward<Func>(function), std::move(generator))
pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))
);
}
@@ -4022,6 +4036,7 @@ namespace Catch {
virtual ShowDurations::OrNot showDurations() const = 0;
virtual TestSpec const& testSpec() const = 0;
virtual bool hasTestFilters() const = 0;
virtual std::vector<std::string> const& getTestsOrTags() const = 0;
virtual RunTests::InWhatOrder runOrder() const = 0;
virtual unsigned int rngSeed() const = 0;
virtual int benchmarkResolutionMultiple() const = 0;
@@ -4352,7 +4367,7 @@ namespace Catch {
arcSafeRelease( m_substr );
}
bool match( NSString* arg ) const override {
bool match( NSString* const& str ) const override {
return false;
}
@@ -4362,7 +4377,7 @@ namespace Catch {
struct Equals : StringHolder {
Equals( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str isEqualToString:m_substr];
}
@@ -4375,7 +4390,7 @@ namespace Catch {
struct Contains : StringHolder {
Contains( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location != NSNotFound;
}
@@ -4388,7 +4403,7 @@ namespace Catch {
struct StartsWith : StringHolder {
StartsWith( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == 0;
}
@@ -4400,7 +4415,7 @@ namespace Catch {
struct EndsWith : StringHolder {
EndsWith( NSString* substr ) : StringHolder( substr ){}
bool match( NSString* str ) const override {
bool match( NSString* const& str ) const override {
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == [str length] - [m_substr length];
}
@@ -4518,7 +4533,7 @@ namespace Catch {
public:
NamePattern( std::string const& name );
virtual ~NamePattern();
virtual bool matches( TestCaseInfo const& testCase ) const override;
bool matches( TestCaseInfo const& testCase ) const override;
private:
WildcardPattern m_wildcardPattern;
};
@@ -4527,7 +4542,7 @@ namespace Catch {
public:
TagPattern( std::string const& tag );
virtual ~TagPattern();
virtual bool matches( TestCaseInfo const& testCase ) const override;
bool matches( TestCaseInfo const& testCase ) const override;
private:
std::string m_tag;
};
@@ -4536,7 +4551,7 @@ namespace Catch {
public:
ExcludedPattern( PatternPtr const& underlyingPattern );
virtual ~ExcludedPattern();
virtual bool matches( TestCaseInfo const& testCase ) const override;
bool matches( TestCaseInfo const& testCase ) const override;
private:
PatternPtr m_underlyingPattern;
};
@@ -4708,10 +4723,10 @@ namespace Catch {
std::string getProcessName() const;
std::string const& getReporterName() const;
std::vector<std::string> const& getTestsOrTags() const;
std::vector<std::string> const& getTestsOrTags() const override;
std::vector<std::string> const& getSectionsToRun() const override;
virtual TestSpec const& testSpec() const override;
TestSpec const& testSpec() const override;
bool hasTestFilters() const override;
bool showHelp() const;
@@ -5082,6 +5097,8 @@ namespace Catch {
// Returns double formatted as %.3f (format expected on output)
std::string getFormattedDuration( double duration );
std::string serializeFilters( std::vector<std::string> const& container );
template<typename DerivedT>
struct StreamingReporterBase : IStreamingReporter {
@@ -5109,6 +5126,7 @@ namespace Catch {
void testRunStarting(TestRunInfo const& _testRunInfo) override {
currentTestRunInfo = _testRunInfo;
}
void testGroupStarting(GroupInfo const& _groupInfo) override {
currentGroupInfo = _groupInfo;
}
@@ -5399,11 +5417,11 @@ namespace Catch {
class ReporterFactory : public IReporterFactory {
virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
IStreamingReporterPtr create( ReporterConfig const& config ) const override {
return std::unique_ptr<T>( new T( config ) );
}
virtual std::string getDescription() const override {
std::string getDescription() const override {
return T::getDescription();
}
};
@@ -5420,10 +5438,10 @@ namespace Catch {
class ListenerFactory : public IReporterFactory {
virtual IStreamingReporterPtr create( ReporterConfig const& config ) const override {
IStreamingReporterPtr create( ReporterConfig const& config ) const override {
return std::unique_ptr<T>( new T( config ) );
}
virtual std::string getDescription() const override {
std::string getDescription() const override {
return std::string();
}
};
@@ -5521,7 +5539,7 @@ namespace Catch {
void testCaseEnded(TestCaseStats const& _testCaseStats) override;
void testGroupEnded(TestGroupStats const& _testGroupStats) override;
void testRunEnded(TestRunStats const& _testRunStats) override;
void testRunStarting(TestRunInfo const& _testRunInfo) override;
private:
void lazyPrint();
@@ -5543,6 +5561,7 @@ namespace Catch {
void printTotalsDivider(Totals const& totals);
void printSummaryDivider();
void printTestFilters();
private:
bool m_headerPrinted = false;
@@ -5823,8 +5842,6 @@ namespace TestCaseTracking {
public:
static TrackerContext& instance();
ITracker& startRun();
void endRun();
@@ -5970,18 +5987,18 @@ namespace Detail {
return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(m_value)));
}
void Approx::setMargin(double margin) {
CATCH_ENFORCE(margin >= 0,
"Invalid Approx::margin: " << margin << '.'
void Approx::setMargin(double newMargin) {
CATCH_ENFORCE(newMargin >= 0,
"Invalid Approx::margin: " << newMargin << '.'
<< " Approx::Margin has to be non-negative.");
m_margin = margin;
m_margin = newMargin;
}
void Approx::setEpsilon(double epsilon) {
CATCH_ENFORCE(epsilon >= 0 && epsilon <= 1.0,
"Invalid Approx::epsilon: " << epsilon << '.'
void Approx::setEpsilon(double newEpsilon) {
CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0,
"Invalid Approx::epsilon: " << newEpsilon << '.'
<< " Approx::epsilon has to be in [0, 1]");
m_epsilon = epsilon;
m_epsilon = newEpsilon;
}
} // end namespace Detail
@@ -6617,6 +6634,9 @@ public:
m_suffix = false;
auto width = m_column.m_width - indent();
m_end = m_pos;
if (line()[m_pos] == '\n') {
++m_end;
}
while (m_end < line().size() && line()[m_end] != '\n')
++m_end;
@@ -8021,10 +8041,7 @@ namespace Catch {
m_stream( openStream() )
{
TestSpecParser parser(ITagAliasRegistry::get());
if (data.testsOrTags.empty()) {
parser.parse("~[.]"); // All not hidden tests
}
else {
if (!data.testsOrTags.empty()) {
m_hasTestFilters = true;
for( auto const& testOrTags : data.testsOrTags )
parser.parse( testOrTags );
@@ -8142,7 +8159,7 @@ namespace {
originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
}
virtual void use( Colour::Code _colourCode ) override {
void use( Colour::Code _colourCode ) override {
switch( _colourCode ) {
case Colour::None: return setTextAttribute( originalForegroundAttributes );
case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
@@ -8205,7 +8222,7 @@ namespace {
// https://github.com/philsquared/Catch/pull/131
class PosixColourImpl : public IColourImpl {
public:
virtual void use( Colour::Code _colourCode ) override {
void use( Colour::Code _colourCode ) override {
switch( _colourCode ) {
case Colour::None:
case Colour::White: return setColour( "[0m" );
@@ -8316,27 +8333,27 @@ namespace Catch {
class Context : public IMutableContext, NonCopyable {
public: // IContext
virtual IResultCapture* getResultCapture() override {
IResultCapture* getResultCapture() override {
return m_resultCapture;
}
virtual IRunner* getRunner() override {
IRunner* getRunner() override {
return m_runner;
}
virtual IConfigPtr const& getConfig() const override {
IConfigPtr const& getConfig() const override {
return m_config;
}
virtual ~Context() override;
~Context() override;
public: // IMutableContext
virtual void setResultCapture( IResultCapture* resultCapture ) override {
void setResultCapture( IResultCapture* resultCapture ) override {
m_resultCapture = resultCapture;
}
virtual void setRunner( IRunner* runner ) override {
void setRunner( IRunner* runner ) override {
m_runner = runner;
}
virtual void setConfig( IConfigPtr const& config ) override {
void setConfig( IConfigPtr const& config ) override {
m_config = config;
}
@@ -8402,19 +8419,23 @@ namespace Catch {
# include <stdbool.h>
# include <sys/types.h>
# include <unistd.h>
# include <sys/sysctl.h>
# include <cstddef>
# include <ostream>
namespace Catch {
#ifdef __apple_build_version__
// These headers will only compile with AppleClang (XCode)
// For other compilers (Clang, GCC, ... ) we need to exclude them
# include <sys/sysctl.h>
#endif
namespace Catch {
#ifdef __apple_build_version__
// The following function is taken directly from the following technical note:
// http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
// https://developer.apple.com/library/archive/qa/qa1361/_index.html
// Returns true if the current process is being debugged (either
// running under the debugger or has a debugger attached post facto).
bool isDebuggerActive(){
int mib[4];
struct kinfo_proc info;
std::size_t size;
@@ -8444,6 +8465,12 @@ namespace Catch {
return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
}
#else
bool isDebuggerActive() {
// We need to find another way to determine this for non-appleclang compilers on macOS
return false;
}
#endif
} // namespace Catch
#elif defined(CATCH_PLATFORM_LINUX)
@@ -8548,7 +8575,7 @@ namespace Catch {
public:
~ExceptionTranslatorRegistry();
virtual void registerTranslator( const IExceptionTranslator* translator );
virtual std::string translateActiveException() const override;
std::string translateActiveException() const override;
std::string tryTranslators() const;
private:
@@ -8660,10 +8687,10 @@ namespace Catch {
// Windows can easily distinguish between SO and SigSegV,
// but SigInt, SigTerm, etc are handled differently.
static SignalDefs signalDefs[] = {
{ EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
{ EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
{ EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
{ EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
{ static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION), "SIGILL - Illegal instruction signal" },
{ static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow" },
{ static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal" },
{ static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },
};
LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
@@ -9821,7 +9848,7 @@ namespace Catch {
if (strerror_s(buffer, errno)) {
CATCH_RUNTIME_ERROR("Could not translate errno to a string");
}
CATCH_RUNTIME_ERROR("Coul dnot open the temp file: '" << m_buffer << "' because: " << buffer);
CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer);
}
}
#else
@@ -10899,7 +10926,10 @@ namespace Catch {
auto const& allTestCases = getAllTestCasesSorted(*config);
for (auto const& testCase : allTestCases) {
if (!context.aborting() && matchTest(testCase, testSpec, *config))
bool matching = (!testSpec.hasFilters() && !testCase.isHidden()) ||
(testSpec.hasFilters() && matchTest(testCase, testSpec, *config));
if (!context.aborting() && matching)
totals += context.runTest(testCase);
else
context.reporter().skipTest(testCase);
@@ -11625,7 +11655,7 @@ namespace Catch {
void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
CATCH_ENFORCE( !isReservedTag(tag),
"Tag name: [" << tag << "] is not allowed.\n"
<< "Tag names starting with non alpha-numeric characters are reserved\n"
<< "Tag names starting with non alphanumeric characters are reserved\n"
<< _lineInfo );
}
}
@@ -11657,6 +11687,12 @@ namespace Catch {
else if( prop == TestCaseInfo::None )
enforceNotReservedTag( tag, _lineInfo );
// Merged hide tags like `[.approvals]` should be added as
// `[.][approvals]`. The `[.]` is added at later point, so
// we only strip the prefix
if (startsWith(tag, '.') && tag.size() > 1) {
tag.erase(0, 1);
}
tags.push_back( tag );
tag.clear();
inTag = false;
@@ -11801,9 +11837,12 @@ namespace Catch {
std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
std::vector<TestCase> filtered;
filtered.reserve( testCases.size() );
for( auto const& testCase : testCases )
if( matchTest( testCase, testSpec, config ) )
filtered.push_back( testCase );
for (auto const& testCase : testCases) {
if ((!testSpec.hasFilters() && !testCase.isHidden()) ||
(testSpec.hasFilters() && matchTest(testCase, testSpec, config))) {
filtered.push_back(testCase);
}
}
return filtered;
}
std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
@@ -11879,11 +11918,6 @@ namespace TestCaseTracking {
ITracker::~ITracker() = default;
TrackerContext& TrackerContext::instance() {
static TrackerContext s_instance;
return s_instance;
}
ITracker& TrackerContext::startRun() {
m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr );
m_currentTracker = nullptr;
@@ -12665,7 +12699,7 @@ namespace Catch {
}
Version const& libraryVersion() {
static Version version( 2, 7, 0, "", 0 );
static Version version( 2, 7, 2, "", 0 );
return version;
}
@@ -13022,6 +13056,21 @@ namespace Catch {
return std::string(buffer);
}
std::string serializeFilters( std::vector<std::string> const& container ) {
ReusableStringStream oss;
bool first = true;
for (auto&& filter : container)
{
if (!first)
oss << ' ';
else
first = false;
oss << filter;
}
return oss.str();
}
TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)
:StreamingReporterBase(_config) {}
@@ -13746,6 +13795,10 @@ void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {
stream << std::endl;
StreamingReporterBase::testRunEnded(_testRunStats);
}
void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) {
StreamingReporterBase::testRunStarting(_testInfo);
printTestFilters();
}
void ConsoleReporter::lazyPrint() {
@@ -13927,6 +13980,11 @@ void ConsoleReporter::printSummaryDivider() {
stream << getLineOfChars<'-'>() << '\n';
}
void ConsoleReporter::printTestFilters() {
if (m_config->testSpec().hasFilters())
stream << Colour(Colour::BrightYellow) << "Filters: " << serializeFilters( m_config->getTestsOrTags() ) << '\n';
}
CATCH_REGISTER_REPORTER("console", ConsoleReporter)
} // end namespace Catch
@@ -14000,13 +14058,6 @@ namespace Catch {
void JunitReporter::testRunStarting( TestRunInfo const& runInfo ) {
CumulativeReporterBase::testRunStarting( runInfo );
xml.startElement( "testsuites" );
if( m_config->rngSeed() != 0 ) {
xml.startElement( "properties" );
xml.scopedElement( "property" )
.writeAttribute( "name", "random-seed" )
.writeAttribute( "value", m_config->rngSeed() );
xml.endElement();
}
}
void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {
@@ -14045,6 +14096,7 @@ namespace Catch {
void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
TestGroupStats const& stats = groupNode.value;
xml.writeAttribute( "name", stats.groupInfo.name );
xml.writeAttribute( "errors", unexpectedExceptions );
@@ -14057,6 +14109,21 @@ namespace Catch {
xml.writeAttribute( "time", suiteTime );
xml.writeAttribute( "timestamp", getCurrentTimestamp() );
// Write properties if there are any
if (m_config->hasTestFilters() || m_config->rngSeed() != 0) {
auto properties = xml.scopedElement("properties");
if (m_config->hasTestFilters()) {
xml.scopedElement("property")
.writeAttribute("name", "filters")
.writeAttribute("value", serializeFilters(m_config->getTestsOrTags()));
}
if (m_config->rngSeed() != 0) {
xml.scopedElement("property")
.writeAttribute("name", "random-seed")
.writeAttribute("value", m_config->rngSeed());
}
}
// Write test cases
for( auto const& child : groupNode.children )
writeTestCase( *child );
@@ -14357,6 +14424,8 @@ namespace Catch {
m_xml.startElement( "Catch" );
if( !m_config->name().empty() )
m_xml.writeAttribute( "name", m_config->name() );
if (m_config->testSpec().hasFilters())
m_xml.writeAttribute( "filters", serializeFilters( m_config->getTestsOrTags() ) );
if( m_config->rngSeed() != 0 )
m_xml.scopedElement( "Randomness" )
.writeAttribute( "seed", m_config->rngSeed() );

View File

@@ -110,6 +110,9 @@ namespace clara { namespace TextFlow {
m_suffix = false;
auto width = m_column.m_width-indent();
m_end = m_pos;
if (line()[m_pos] == '\n') {
++m_end;
}
while( m_end < line().size() && line()[m_end] != '\n' )
++m_end;