summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaibo Huang <hhb@google.com>2019-05-23 09:26:57 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-05-23 09:26:57 -0700
commitdba03cace0e298b6a690c00ccd99848193c2e0f9 (patch)
tree26e11d8d52fd0b8fb25aab5b23a1e45d0b646430
parentbcfbb791d09e390fb545c03ca002e570f764d960 (diff)
parenta8f1a3dea29dbd45c1b7f3422c0aa29d5f06dbda (diff)
downloadcatch2-android11-mainline-cellbroadcast-release.tar.gz
Merge "android: Upgrade catch2 to v2.7.2" am: 6461e4174a am: 47286e0e8e am: b9a38f6db9r_aml_301500702android-mainline-12.0.0_r55android-mainline-11.0.0_r9android-mainline-11.0.0_r8android-mainline-11.0.0_r7android-mainline-11.0.0_r6android-mainline-11.0.0_r5android-mainline-11.0.0_r45android-mainline-11.0.0_r44android-mainline-11.0.0_r43android-mainline-11.0.0_r42android-mainline-11.0.0_r41android-mainline-11.0.0_r40android-mainline-11.0.0_r4android-mainline-11.0.0_r39android-mainline-11.0.0_r38android-mainline-11.0.0_r37android-mainline-11.0.0_r36android-mainline-11.0.0_r35android-mainline-11.0.0_r34android-mainline-11.0.0_r33android-mainline-11.0.0_r32android-mainline-11.0.0_r31android-mainline-11.0.0_r30android-mainline-11.0.0_r3android-mainline-11.0.0_r29android-mainline-11.0.0_r28android-mainline-11.0.0_r27android-mainline-11.0.0_r26android-mainline-11.0.0_r25android-mainline-11.0.0_r24android-mainline-11.0.0_r23android-mainline-11.0.0_r22android-mainline-11.0.0_r21android-mainline-11.0.0_r20android-mainline-11.0.0_r2android-mainline-11.0.0_r19android-mainline-11.0.0_r18android-mainline-11.0.0_r17android-mainline-11.0.0_r16android-mainline-11.0.0_r15android-mainline-11.0.0_r14android-mainline-11.0.0_r13android-mainline-11.0.0_r12android-mainline-11.0.0_r10android-mainline-11.0.0_r1android-11.0.0_r9android-11.0.0_r8android-11.0.0_r7android-11.0.0_r48android-11.0.0_r47android-11.0.0_r46android-11.0.0_r45android-11.0.0_r44android-11.0.0_r43android-11.0.0_r42android-11.0.0_r41android-11.0.0_r40android-11.0.0_r39android-11.0.0_r38android-11.0.0_r37android-11.0.0_r36android-11.0.0_r35android-11.0.0_r34android-11.0.0_r33android-11.0.0_r32android-11.0.0_r31android-11.0.0_r30android-11.0.0_r29android-11.0.0_r28android-11.0.0_r27android-11.0.0_r26android-11.0.0_r24android-11.0.0_r23android-11.0.0_r22android-11.0.0_r21android-11.0.0_r20android-11.0.0_r19android-11.0.0_r18android-11.0.0_r16android-11.0.0_r15android-11.0.0_r14android-11.0.0_r13android-11.0.0_r12android-11.0.0_r11android-11.0.0_r10android11-qpr3-s1-releaseandroid11-qpr3-releaseandroid11-qpr2-releaseandroid11-qpr1-s2-releaseandroid11-qpr1-s1-releaseandroid11-qpr1-releaseandroid11-qpr1-d-s1-releaseandroid11-qpr1-d-releaseandroid11-qpr1-c-releaseandroid11-mainline-tethering-releaseandroid11-mainline-sparse-2021-jan-releaseandroid11-mainline-sparse-2020-dec-releaseandroid11-mainline-releaseandroid11-mainline-permission-releaseandroid11-mainline-os-statsd-releaseandroid11-mainline-networkstack-releaseandroid11-mainline-media-swcodec-releaseandroid11-mainline-media-releaseandroid11-mainline-extservices-releaseandroid11-mainline-documentsui-releaseandroid11-mainline-conscrypt-releaseandroid11-mainline-cellbroadcast-releaseandroid11-mainline-captiveportallogin-releaseandroid11-devandroid11-d2-releaseandroid11-d1-s7-releaseandroid11-d1-s6-releaseandroid11-d1-s5-releaseandroid11-d1-s1-releaseandroid11-d1-releaseandroid11-d1-b-release
am: a8f1a3dea2 Change-Id: I98ea4b3c203abd31996ed12d667da3921dfb6771
-rw-r--r--.conan/build.py2
-rw-r--r--.github/pull_request_template.md2
-rw-r--r--CMake/FindGcov.cmake2
-rw-r--r--CMake/Findcodecov.cmake2
-rw-r--r--CMakeLists.txt13
-rw-r--r--METADATA14
-rw-r--r--README.md6
-rw-r--r--contrib/CatchAddTests.cmake66
-rw-r--r--contrib/ParseAndAddCatchTests.cmake56
-rw-r--r--docs/assertions.md4
-rw-r--r--docs/cmake-integration.md2
-rw-r--r--docs/command-line.md2
-rw-r--r--docs/configuration.md2
-rw-r--r--docs/contributing.md28
-rw-r--r--docs/event-listeners.md6
-rw-r--r--docs/generators.md12
-rw-r--r--docs/list-of-examples.md1
-rw-r--r--docs/logging.md2
-rw-r--r--docs/matchers.md4
-rw-r--r--docs/opensource-users.md6
-rw-r--r--docs/other-macros.md4
-rw-r--r--docs/release-notes.md43
-rw-r--r--docs/release-process.md2
-rw-r--r--docs/tutorial.md6
-rw-r--r--examples/210-Evt-EventListeners.cpp18
-rw-r--r--examples/310-Gen-VariablesInGenerators.cpp51
-rw-r--r--examples/311-Gen-CustomCapture.cpp41
-rw-r--r--examples/CMakeLists.txt1
-rw-r--r--include/catch.hpp2
-rw-r--r--include/external/clara.hpp3
-rw-r--r--include/internal/catch_approx.cpp16
-rw-r--r--include/internal/catch_config.cpp5
-rw-r--r--include/internal/catch_config.hpp4
-rw-r--r--include/internal/catch_console_colour.cpp4
-rw-r--r--include/internal/catch_context.cpp14
-rw-r--r--include/internal/catch_debugger.cpp18
-rw-r--r--include/internal/catch_exception_translator_registry.h2
-rw-r--r--include/internal/catch_fatal_condition.cpp8
-rw-r--r--include/internal/catch_generators.hpp7
-rw-r--r--include/internal/catch_generators_generic.hpp20
-rw-r--r--include/internal/catch_interfaces_config.h1
-rw-r--r--include/internal/catch_matchers_generic.hpp2
-rw-r--r--include/internal/catch_matchers_vector.h87
-rw-r--r--include/internal/catch_objc.hpp10
-rw-r--r--include/internal/catch_output_redirect.cpp2
-rw-r--r--include/internal/catch_reporter_registrars.hpp8
-rw-r--r--include/internal/catch_session.cpp5
-rw-r--r--include/internal/catch_test_case_info.cpp8
-rw-r--r--include/internal/catch_test_case_registry_impl.cpp9
-rw-r--r--include/internal/catch_test_case_tracker.cpp5
-rw-r--r--include/internal/catch_test_case_tracker.h2
-rw-r--r--include/internal/catch_test_spec.h6
-rw-r--r--include/internal/catch_version.cpp2
-rw-r--r--include/reporters/catch_reporter_bases.cpp14
-rw-r--r--include/reporters/catch_reporter_bases.hpp3
-rw-r--r--include/reporters/catch_reporter_console.cpp9
-rw-r--r--include/reporters/catch_reporter_console.h3
-rw-r--r--include/reporters/catch_reporter_junit.cpp23
-rw-r--r--include/reporters/catch_reporter_xml.cpp2
-rw-r--r--projects/CMakeLists.txt5
-rw-r--r--projects/SelfTest/Baselines/compact.sw.approved.txt60
-rw-r--r--projects/SelfTest/Baselines/console.std.approved.txt43
-rw-r--r--projects/SelfTest/Baselines/console.sw.approved.txt401
-rw-r--r--projects/SelfTest/Baselines/console.swa4.approved.txt23
-rw-r--r--projects/SelfTest/Baselines/junit.sw.approved.txt34
-rw-r--r--projects/SelfTest/Baselines/xml.sw.approved.txt395
-rw-r--r--projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp53
-rw-r--r--projects/SelfTest/IntrospectiveTests/PartTracker.tests.cpp15
-rw-r--r--projects/SelfTest/IntrospectiveTests/Tag.tests.cpp (renamed from projects/SelfTest/IntrospectiveTests/TagAlias.tests.cpp)5
-rw-r--r--projects/SelfTest/UsageTests/Generators.tests.cpp23
-rw-r--r--projects/SelfTest/UsageTests/Matchers.tests.cpp58
-rw-r--r--projects/SelfTest/UsageTests/Message.tests.cpp13
-rw-r--r--projects/SelfTest/UsageTests/ToStringGeneral.tests.cpp4
-rw-r--r--projects/XCode/OCTest/OCTest/CatchOCTestCase.mm2
-rw-r--r--single_include/catch2/catch.hpp307
-rw-r--r--third_party/clara.hpp3
76 files changed, 1690 insertions, 456 deletions
diff --git a/.conan/build.py b/.conan/build.py
index dfba2642..27298651 100644
--- a/.conan/build.py
+++ b/.conan/build.py
@@ -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))
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 368f41fb..ea2b7bb5 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -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.
-->
diff --git a/CMake/FindGcov.cmake b/CMake/FindGcov.cmake
index 6ffd6eac..41417113 100644
--- a/CMake/FindGcov.cmake
+++ b/CMake/FindGcov.cmake
@@ -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)
diff --git a/CMake/Findcodecov.cmake b/CMake/Findcodecov.cmake
index fa135fa8..2c0f2fee 100644
--- a/CMake/Findcodecov.cmake
+++ b/CMake/Findcodecov.cmake
@@ -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})
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ea35d24e..e2329c69 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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)
diff --git a/METADATA b/METADATA
index cf98e4a9..50e9afad 100644
--- a/METADATA
+++ b/METADATA
@@ -1,9 +1,5 @@
name: "catch"
-description:
- "A modern, C++-native, header-only, test framework for unit-tests, TDD and "
- "BDD - using C++11, C++14, C++17 and later (or C++03 on the Catch1.x "
- "branch)"
-
+description: "A modern, C++-native, header-only, test framework for unit-tests, TDD and BDD - using C++11, C++14, C++17 and later (or C++03 on the Catch1.x branch)"
third_party {
url {
type: HOMEPAGE
@@ -13,7 +9,11 @@ third_party {
type: GIT
value: "https://github.com/catchorg/Catch2.git"
}
- version: "v2.7.0"
- last_upgrade_date { year: 2019 month: 3 day: 7 }
+ version: "v2.7.2"
license_type: NOTICE
+ last_upgrade_date {
+ year: 2019
+ month: 5
+ day: 2
+ }
}
diff --git a/README.md b/README.md
index 08095f1c..535ac6ec 100644
--- a/README.md
+++ b/README.md
@@ -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?
diff --git a/contrib/CatchAddTests.cmake b/contrib/CatchAddTests.cmake
index 2220ce3a..ca5ebc17 100644
--- a/contrib/CatchAddTests.cmake
+++ b/contrib/CatchAddTests.cmake
@@ -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
diff --git a/contrib/ParseAndAddCatchTests.cmake b/contrib/ParseAndAddCatchTests.cmake
index ff4fc667..925d9328 100644
--- a/contrib/ParseAndAddCatchTests.cmake
+++ b/contrib/ParseAndAddCatchTests.cmake
@@ -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()
diff --git a/docs/assertions.md b/docs/assertions.md
index 900fd52c..07d2484e 100644
--- a/docs/assertions.md
+++ b/docs/assertions.md
@@ -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;
diff --git a/docs/cmake-integration.md b/docs/cmake-integration.md
index 246e7f0e..57073c40 100644
--- a/docs/cmake-integration.md
+++ b/docs/cmake-integration.md
@@ -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
diff --git a/docs/command-line.md b/docs/command-line.md
index fc63fe87..f68c84ca 100644
--- a/docs/command-line.md
+++ b/docs/command-line.md
@@ -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 />
diff --git a/docs/configuration.md b/docs/configuration.md
index 1c94481a..c01d7f5e 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -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<<`
diff --git a/docs/contributing.md b/docs/contributing.md
index 21bbad14..b95edf86 100644
--- a/docs/contributing.md
+++ b/docs/contributing.md
@@ -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._
---
diff --git a/docs/event-listeners.md b/docs/event-listeners.md
index c6625a2e..62311006 100644
--- a/docs/event-listeners.md
+++ b/docs/event-listeners.md
@@ -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 )
```
diff --git a/docs/generators.md b/docs/generators.md
index 8ad47e39..57fdf44b 100644
--- a/docs/generators.md
+++ b/docs/generators.md
@@ -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);
}
```
diff --git a/docs/list-of-examples.md b/docs/list-of-examples.md
index 677dec1e..95e7bda0 100644
--- a/docs/list-of-examples.md
+++ b/docs/list-of-examples.md
@@ -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
diff --git a/docs/logging.md b/docs/logging.md
index e896a570..7b5c6c4b 100644
--- a/docs/logging.md
+++ b/docs/logging.md
@@ -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++
diff --git a/docs/matchers.md b/docs/matchers.md
index adbd4ce7..13c7d0c8 100644
--- a/docs/matchers.md
+++ b/docs/matchers.md
@@ -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();
diff --git a/docs/opensource-users.md b/docs/opensource-users.md
index d71b425a..489bbdcc 100644
--- a/docs/opensource-users.md
+++ b/docs/opensource-users.md
@@ -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.
diff --git a/docs/other-macros.md b/docs/other-macros.md
index 6f5fac7b..345234d5 100644
--- a/docs/other-macros.md
+++ b/docs/other-macros.md
@@ -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:
diff --git a/docs/release-notes.md b/docs/release-notes.md
index 34278c38..c5f92d2b 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -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
diff --git a/docs/release-process.md b/docs/release-process.md
index 412cf2d3..7fa5f7e1 100644
--- a/docs/release-process.md
+++ b/docs/release-process.md
@@ -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
diff --git a/docs/tutorial.md b/docs/tutorial.md
index 7c0f8145..e45f967e 100644
--- a/docs/tutorial.md
+++ b/docs/tutorial.md
@@ -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" ) {
diff --git a/examples/210-Evt-EventListeners.cpp b/examples/210-Evt-EventListeners.cpp
index fde51c7e..2d5fdb28 100644
--- a/examples/210-Evt-EventListeners.cpp
+++ b/examples/210-Evt-EventListeners.cpp
@@ -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;
diff --git a/examples/310-Gen-VariablesInGenerators.cpp b/examples/310-Gen-VariablesInGenerators.cpp
index 96840bbb..422815d2 100644
--- a/examples/310-Gen-VariablesInGenerators.cpp
+++ b/examples/310-Gen-VariablesInGenerators.cpp
@@ -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);
}
diff --git a/examples/311-Gen-CustomCapture.cpp b/examples/311-Gen-CustomCapture.cpp
new file mode 100644
index 00000000..da6d686f
--- /dev/null
+++ b/examples/311-Gen-CustomCapture.cpp
@@ -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
+
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index dff5c742..65dc5f54 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -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:
diff --git a/include/catch.hpp b/include/catch.hpp
index e15588f0..5667def9 100644
--- a/include/catch.hpp
+++ b/include/catch.hpp
@@ -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
diff --git a/include/external/clara.hpp b/include/external/clara.hpp
index 20c6da70..c7348bf9 100644
--- a/include/external/clara.hpp
+++ b/include/external/clara.hpp
@@ -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;
diff --git a/include/internal/catch_approx.cpp b/include/internal/catch_approx.cpp
index a7d7111c..da7e4020 100644
--- a/include/internal/catch_approx.cpp
+++ b/include/internal/catch_approx.cpp
@@ -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
diff --git a/include/internal/catch_config.cpp b/include/internal/catch_config.cpp
index e8ad2a81..d9ee9182 100644
--- a/include/internal/catch_config.cpp
+++ b/include/internal/catch_config.cpp
@@ -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 );
diff --git a/include/internal/catch_config.hpp b/include/internal/catch_config.hpp
index 7bafc9c3..a9850233 100644
--- a/include/internal/catch_config.hpp
+++ b/include/internal/catch_config.hpp
@@ -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;
diff --git a/include/internal/catch_console_colour.cpp b/include/internal/catch_console_colour.cpp
index 07072db6..0a13a1bb 100644
--- a/include/internal/catch_console_colour.cpp
+++ b/include/internal/catch_console_colour.cpp
@@ -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" );
diff --git a/include/internal/catch_context.cpp b/include/internal/catch_context.cpp
index e116f28f..52fca302 100644
--- a/include/internal/catch_context.cpp
+++ b/include/internal/catch_context.cpp
@@ -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;
}
diff --git a/include/internal/catch_debugger.cpp b/include/internal/catch_debugger.cpp
index 71dc6506..f04900a4 100644
--- a/include/internal/catch_debugger.cpp
+++ b/include/internal/catch_debugger.cpp
@@ -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)
diff --git a/include/internal/catch_exception_translator_registry.h b/include/internal/catch_exception_translator_registry.h
index da2f4f12..bb07c131 100644
--- a/include/internal/catch_exception_translator_registry.h
+++ b/include/internal/catch_exception_translator_registry.h
@@ -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:
diff --git a/include/internal/catch_fatal_condition.cpp b/include/internal/catch_fatal_condition.cpp
index 24e16d3c..cea271f3 100644
--- a/include/internal/catch_fatal_condition.cpp
+++ b/include/internal/catch_fatal_condition.cpp
@@ -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) {
diff --git a/include/internal/catch_generators.hpp b/include/internal/catch_generators.hpp
index 40e434e7..8f06b8c6 100644
--- a/include/internal/catch_generators.hpp
+++ b/include/internal/catch_generators.hpp
@@ -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
diff --git a/include/internal/catch_generators_generic.hpp b/include/internal/catch_generators_generic.hpp
index 2226dbc5..2903ba69 100644
--- a/include/internal/catch_generators_generic.hpp
+++ b/include/internal/catch_generators_generic.hpp
@@ -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))
);
}
diff --git a/include/internal/catch_interfaces_config.h b/include/internal/catch_interfaces_config.h
index f509c7ed..341bb742 100644
--- a/include/internal/catch_interfaces_config.h
+++ b/include/internal/catch_interfaces_config.h
@@ -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;
diff --git a/include/internal/catch_matchers_generic.hpp b/include/internal/catch_matchers_generic.hpp
index 7c4f9f1d..7d57c9d4 100644
--- a/include/internal/catch_matchers_generic.hpp
+++ b/include/internal/catch_matchers_generic.hpp
@@ -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 = "") {
diff --git a/include/internal/catch_matchers_vector.h b/include/internal/catch_matchers_vector.h
index 1e29cc94..2dc8a715 100644
--- a/include/internal/catch_matchers_vector.h
+++ b/include/internal/catch_matchers_vector.h
@@ -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>> {
@@ -113,6 +92,42 @@ namespace Matchers {
};
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) {}
bool match(std::vector<T> const& vec) const override {
@@ -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 {
@@ -173,6 +167,11 @@ namespace Matchers {
}
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);
}
diff --git a/include/internal/catch_objc.hpp b/include/internal/catch_objc.hpp
index 39cbb1fa..f927e0d3 100644
--- a/include/internal/catch_objc.hpp
+++ b/include/internal/catch_objc.hpp
@@ -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];
}
diff --git a/include/internal/catch_output_redirect.cpp b/include/internal/catch_output_redirect.cpp
index a0a9aff9..1308bfe3 100644
--- a/include/internal/catch_output_redirect.cpp
+++ b/include/internal/catch_output_redirect.cpp
@@ -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
diff --git a/include/internal/catch_reporter_registrars.hpp b/include/internal/catch_reporter_registrars.hpp
index 943fba65..660f554a 100644
--- a/include/internal/catch_reporter_registrars.hpp
+++ b/include/internal/catch_reporter_registrars.hpp
@@ -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();
}
};
diff --git a/include/internal/catch_session.cpp b/include/internal/catch_session.cpp
index a5907e97..38b74ef7 100644
--- a/include/internal/catch_session.cpp
+++ b/include/internal/catch_session.cpp
@@ -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);
diff --git a/include/internal/catch_test_case_info.cpp b/include/internal/catch_test_case_info.cpp
index 536462d1..4baa9d4b 100644
--- a/include/internal/catch_test_case_info.cpp
+++ b/include/internal/catch_test_case_info.cpp
@@ -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;
diff --git a/include/internal/catch_test_case_registry_impl.cpp b/include/internal/catch_test_case_registry_impl.cpp
index a6b7f570..a85d0edf 100644
--- a/include/internal/catch_test_case_registry_impl.cpp
+++ b/include/internal/catch_test_case_registry_impl.cpp
@@ -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 ) {
diff --git a/include/internal/catch_test_case_tracker.cpp b/include/internal/catch_test_case_tracker.cpp
index 210f2730..1ef830d1 100644
--- a/include/internal/catch_test_case_tracker.cpp
+++ b/include/internal/catch_test_case_tracker.cpp
@@ -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;
diff --git a/include/internal/catch_test_case_tracker.h b/include/internal/catch_test_case_tracker.h
index 17276001..97b63b8b 100644
--- a/include/internal/catch_test_case_tracker.h
+++ b/include/internal/catch_test_case_tracker.h
@@ -71,8 +71,6 @@ namespace TestCaseTracking {
public:
- static TrackerContext& instance();
-
ITracker& startRun();
void endRun();
diff --git a/include/internal/catch_test_spec.h b/include/internal/catch_test_spec.h
index baf8b019..d2565187 100644
--- a/include/internal/catch_test_spec.h
+++ b/include/internal/catch_test_spec.h
@@ -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;
};
diff --git a/include/internal/catch_version.cpp b/include/internal/catch_version.cpp
index a1d08b2c..5f4917c1 100644
--- a/include/internal/catch_version.cpp
+++ b/include/internal/catch_version.cpp
@@ -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;
}
diff --git a/include/reporters/catch_reporter_bases.cpp b/include/reporters/catch_reporter_bases.cpp
index ce3553ed..fcbafef5 100644
--- a/include/reporters/catch_reporter_bases.cpp
+++ b/include/reporters/catch_reporter_bases.cpp
@@ -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) {}
diff --git a/include/reporters/catch_reporter_bases.hpp b/include/reporters/catch_reporter_bases.hpp
index 4a27db68..a9b0640c 100644
--- a/include/reporters/catch_reporter_bases.hpp
+++ b/include/reporters/catch_reporter_bases.hpp
@@ -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;
}
diff --git a/include/reporters/catch_reporter_console.cpp b/include/reporters/catch_reporter_console.cpp
index 76dc9ecd..53b977eb 100644
--- a/include/reporters/catch_reporter_console.cpp
+++ b/include/reporters/catch_reporter_console.cpp
@@ -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
diff --git a/include/reporters/catch_reporter_console.h b/include/reporters/catch_reporter_console.h
index 10cea49a..effa58d3 100644
--- a/include/reporters/catch_reporter_console.h
+++ b/include/reporters/catch_reporter_console.h
@@ -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;
diff --git a/include/reporters/catch_reporter_junit.cpp b/include/reporters/catch_reporter_junit.cpp
index 7e97ee31..e8375862 100644
--- a/include/reporters/catch_reporter_junit.cpp
+++ b/include/reporters/catch_reporter_junit.cpp
@@ -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 );
diff --git a/include/reporters/catch_reporter_xml.cpp b/include/reporters/catch_reporter_xml.cpp
index 902014cf..c7572d1e 100644
--- a/include/reporters/catch_reporter_xml.cpp
+++ b/include/reporters/catch_reporter_xml.cpp
@@ -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() );
diff --git a/projects/CMakeLists.txt b/projects/CMakeLists.txt
index b3caa82f..3fbd9b42 100644
--- a/projects/CMakeLists.txt
+++ b/projects/CMakeLists.txt
@@ -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
diff --git a/projects/SelfTest/Baselines/compact.sw.approved.txt b/projects/SelfTest/Baselines/compact.sw.approved.txt
index 2fcdd866..6fedbb92 100644
--- a/projects/SelfTest/Baselines/compact.sw.approved.txt
+++ b/projects/SelfTest/Baselines/compact.sw.approved.txt
@@ -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.
diff --git a/projects/SelfTest/Baselines/console.std.approved.txt b/projects/SelfTest/Baselines/console.std.approved.txt
index 3c504378..e5a1d5da 100644
--- a/projects/SelfTest/Baselines/console.std.approved.txt
+++ b/projects/SelfTest/Baselines/console.std.approved.txt
@@ -1,5 +1,4 @@
-This would not be caught previously
-Nor would this
+Filters: ~[!nonportable]~[!benchmark]~[approvals]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<exe-name> is a <version> host application.
@@ -8,6 +7,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
-------------------------------------------------------------------------------
Tricky.tests.cpp:<line number>
@@ -851,6 +862,30 @@ 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
diff --git a/projects/SelfTest/Baselines/console.sw.approved.txt b/projects/SelfTest/Baselines/console.sw.approved.txt
index 5b54ace9..9def37d9 100644
--- a/projects/SelfTest/Baselines/console.sw.approved.txt
+++ b/projects/SelfTest/Baselines/console.sw.approved.txt
@@ -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" )
@@ -3047,6 +3063,45 @@ with expansion:
-------------------------------------------------------------------------------
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:
+ 1 == 1
+
+-------------------------------------------------------------------------------
+Generators -- adapters
Repeating a generator
-------------------------------------------------------------------------------
Generators.tests.cpp:<line number>
@@ -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>
...............................................................................
@@ -4622,6 +4714,182 @@ 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
-------------------------------------------------------------------------------
Misc.tests.cpp:<line number>
@@ -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 ) ) )
-------------------------------------------------------------------------------
@@ -8453,6 +8721,96 @@ 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)
-------------------------------------------------------------------------------
@@ -10009,6 +10367,17 @@ with messages:
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
-------------------------------------------------------------------------------
Message.tests.cpp:<line number>
@@ -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
diff --git a/projects/SelfTest/Baselines/console.swa4.approved.txt b/projects/SelfTest/Baselines/console.swa4.approved.txt
index 2efd7617..bfa66750 100644
--- a/projects/SelfTest/Baselines/console.swa4.approved.txt
+++ b/projects/SelfTest/Baselines/console.swa4.approved.txt
@@ -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
diff --git a/projects/SelfTest/Baselines/junit.sw.approved.txt b/projects/SelfTest/Baselines/junit.sw.approved.txt
index 25c48235..af4ebe07 100644
--- a/projects/SelfTest/Baselines/junit.sw.approved.txt
+++ b/projects/SelfTest/Baselines/junit.sw.approved.txt
@@ -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...
diff --git a/projects/SelfTest/Baselines/xml.sw.approved.txt b/projects/SelfTest/Baselines/xml.sw.approved.txt
index 637689a4..d053b408 100644
--- a/projects/SelfTest/Baselines/xml.sw.approved.txt
+++ b/projects/SelfTest/Baselines/xml.sw.approved.txt
@@ -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>
diff --git a/projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp b/projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp
index de8b0ffc..dbc1d957 100644
--- a/projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp
+++ b/projects/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp
@@ -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);
+}
diff --git a/projects/SelfTest/IntrospectiveTests/PartTracker.tests.cpp b/projects/SelfTest/IntrospectiveTests/PartTracker.tests.cpp
index 9372b1c3..97423265 100644
--- a/projects/SelfTest/IntrospectiveTests/PartTracker.tests.cpp
+++ b/projects/SelfTest/IntrospectiveTests/PartTracker.tests.cpp
@@ -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;
diff --git a/projects/SelfTest/IntrospectiveTests/TagAlias.tests.cpp b/projects/SelfTest/IntrospectiveTests/Tag.tests.cpp
index 54285894..f3890b14 100644
--- a/projects/SelfTest/IntrospectiveTests/TagAlias.tests.cpp
+++ b/projects/SelfTest/IntrospectiveTests/Tag.tests.cpp
@@ -43,3 +43,8 @@ TEST_CASE( "Tag alias can be registered against tag patterns" ) {
#endif
}
+
+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(".")));
+}
diff --git a/projects/SelfTest/UsageTests/Generators.tests.cpp b/projects/SelfTest/UsageTests/Generators.tests.cpp
index 0cf1ce6e..f5e3f6a5 100644
--- a/projects/SelfTest/UsageTests/Generators.tests.cpp
+++ b/projects/SelfTest/UsageTests/Generators.tests.cpp
@@ -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);
+}
diff --git a/projects/SelfTest/UsageTests/Matchers.tests.cpp b/projects/SelfTest/UsageTests/Matchers.tests.cpp
index dc4b701d..b0b5d58e 100644
--- a/projects/SelfTest/UsageTests/Matchers.tests.cpp
+++ b/projects/SelfTest/UsageTests/Matchers.tests.cpp
@@ -215,6 +215,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)") {
@@ -267,6 +277,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)") {
@@ -440,6 +460,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
diff --git a/projects/SelfTest/UsageTests/Message.tests.cpp b/projects/SelfTest/UsageTests/Message.tests.cpp
index c955822f..ccb7ac2f 100644
--- a/projects/SelfTest/UsageTests/Message.tests.cpp
+++ b/projects/SelfTest/UsageTests/Message.tests.cpp
@@ -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;
diff --git a/projects/SelfTest/UsageTests/ToStringGeneral.tests.cpp b/projects/SelfTest/UsageTests/ToStringGeneral.tests.cpp
index acddf223..09ac3045 100644
--- a/projects/SelfTest/UsageTests/ToStringGeneral.tests.cpp
+++ b/projects/SelfTest/UsageTests/ToStringGeneral.tests.cpp
@@ -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");
}
diff --git a/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm b/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm
index 9bd1fa09..e285138b 100644
--- a/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm
+++ b/projects/XCode/OCTest/OCTest/CatchOCTestCase.mm
@@ -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" ) );
diff --git a/single_include/catch2/catch.hpp b/single_include/catch2/catch.hpp
index 1850fff1..df14c357 100644
--- a/single_include/catch2/catch.hpp
+++ b/single_include/catch2/catch.hpp
@@ -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>> {
@@ -3298,6 +3276,42 @@ namespace Matchers {
};
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) {}
bool match(std::vector<T> const& vec) const override {
@@ -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 {
@@ -3358,6 +3351,11 @@ namespace Matchers {
}
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() );
diff --git a/third_party/clara.hpp b/third_party/clara.hpp
index 6be5a98b..9f4f1b2c 100644
--- a/third_party/clara.hpp
+++ b/third_party/clara.hpp
@@ -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;