diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2019-05-24 03:05:24 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2019-05-24 03:05:24 +0000 |
commit | 2df9c0644ee3ab3689ca56a2e723de5bb70b9480 (patch) | |
tree | 26e11d8d52fd0b8fb25aab5b23a1e45d0b646430 | |
parent | bcfbb791d09e390fb545c03ca002e570f764d960 (diff) | |
parent | dba03cace0e298b6a690c00ccd99848193c2e0f9 (diff) | |
download | catch2-android11-release.tar.gz |
Snap for 5600116 from dba03cace0e298b6a690c00ccd99848193c2e0f9 to rvc-releaseandroid-vts-11.0_r9android-vts-11.0_r8android-vts-11.0_r7android-vts-11.0_r6android-vts-11.0_r5android-vts-11.0_r4android-vts-11.0_r3android-vts-11.0_r2android-vts-11.0_r16android-vts-11.0_r15android-vts-11.0_r14android-vts-11.0_r13android-vts-11.0_r12android-vts-11.0_r11android-vts-11.0_r10android-vts-11.0_r1android-security-11.0.0_r76android-security-11.0.0_r75android-security-11.0.0_r74android-security-11.0.0_r73android-security-11.0.0_r72android-security-11.0.0_r71android-security-11.0.0_r70android-security-11.0.0_r69android-security-11.0.0_r68android-security-11.0.0_r67android-security-11.0.0_r66android-security-11.0.0_r65android-security-11.0.0_r64android-security-11.0.0_r63android-security-11.0.0_r62android-security-11.0.0_r61android-security-11.0.0_r60android-security-11.0.0_r59android-security-11.0.0_r58android-security-11.0.0_r57android-security-11.0.0_r56android-security-11.0.0_r55android-security-11.0.0_r54android-security-11.0.0_r53android-security-11.0.0_r52android-security-11.0.0_r51android-security-11.0.0_r50android-security-11.0.0_r49android-security-11.0.0_r1android-platform-11.0.0_r9android-platform-11.0.0_r8android-platform-11.0.0_r7android-platform-11.0.0_r6android-platform-11.0.0_r5android-platform-11.0.0_r40android-platform-11.0.0_r4android-platform-11.0.0_r39android-platform-11.0.0_r38android-platform-11.0.0_r37android-platform-11.0.0_r36android-platform-11.0.0_r35android-platform-11.0.0_r34android-platform-11.0.0_r33android-platform-11.0.0_r32android-platform-11.0.0_r31android-platform-11.0.0_r30android-platform-11.0.0_r3android-platform-11.0.0_r29android-platform-11.0.0_r28android-platform-11.0.0_r27android-platform-11.0.0_r26android-platform-11.0.0_r25android-platform-11.0.0_r24android-platform-11.0.0_r23android-platform-11.0.0_r22android-platform-11.0.0_r21android-platform-11.0.0_r20android-platform-11.0.0_r2android-platform-11.0.0_r19android-platform-11.0.0_r18android-platform-11.0.0_r17android-platform-11.0.0_r16android-platform-11.0.0_r15android-platform-11.0.0_r14android-platform-11.0.0_r13android-platform-11.0.0_r12android-platform-11.0.0_r11android-platform-11.0.0_r10android-platform-11.0.0_r1android-cts-11.0_r9android-cts-11.0_r8android-cts-11.0_r7android-cts-11.0_r6android-cts-11.0_r5android-cts-11.0_r4android-cts-11.0_r3android-cts-11.0_r2android-cts-11.0_r16android-cts-11.0_r15android-cts-11.0_r14android-cts-11.0_r13android-cts-11.0_r12android-cts-11.0_r11android-cts-11.0_r10android-cts-11.0_r1android-11.0.0_r6android-11.0.0_r5android-11.0.0_r4android-11.0.0_r3android-11.0.0_r25android-11.0.0_r2android-11.0.0_r17android-11.0.0_r1android11-tests-releaseandroid11-security-releaseandroid11-s1-releaseandroid11-releaseandroid11-platform-releaseandroid11-gsi
Change-Id: I61078d68107d57d0e4c466cc1177f5167a4490da
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) @@ -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 + } } @@ -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<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 && and || - failing" tags="[.][.failing][matchers][operator&&][operators][operator||]" filename="projects/<exe-name>/UsageTests/Matchers.tests.cpp" > + <TestCase name="Matchers can be composed with both && and || - failing" tags="[.][failing][matchers][operator&&][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")) && 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")) && 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; |