From 4e8399d83532cc8f990caa3937319c3f8f92e8b8 Mon Sep 17 00:00:00 2001 From: Holger Kaelberer Date: Tue, 11 Apr 2023 09:43:44 +0200 Subject: [PATCH 01/26] CatchAddTests.cmake: Refactor into callable method Move test discovery logic into new catch_discover_tests_impl method and make CatchAddTests aware of whether it is being launched in CMake's script mode. When launched in script mode, catch_discover_tests_impl is called passing arguments obtained from the definitions passed into the call to cmake. This preserves the existing behavior assumed by Catch.cmake. Looking ahead, it also allows CatchAddTests to be included in generated files and call catch_discover_tests_impl to perform test discovery at test runtime with the new PRE_TEST discovery mode introduced later. --- extras/CatchAddTests.cmake | 275 +++++++++++++++++++++---------------- 1 file changed, 153 insertions(+), 122 deletions(-) diff --git a/extras/CatchAddTests.cmake b/extras/CatchAddTests.cmake index 2df663dc..91f79f3c 100644 --- a/extras/CatchAddTests.cmake +++ b/extras/CatchAddTests.cmake @@ -1,28 +1,6 @@ # Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. -set(prefix "${TEST_PREFIX}") -set(suffix "${TEST_SUFFIX}") -set(spec ${TEST_SPEC}) -set(extra_args ${TEST_EXTRA_ARGS}) -set(properties ${TEST_PROPERTIES}) -set(reporter ${TEST_REPORTER}) -set(output_dir ${TEST_OUTPUT_DIR}) -set(output_prefix ${TEST_OUTPUT_PREFIX}) -set(output_suffix ${TEST_OUTPUT_SUFFIX}) -set(dl_paths ${TEST_DL_PATHS}) -set(script) -set(suite) -set(tests) - -if(WIN32) - set(dl_paths_variable_name PATH) -elseif(APPLE) - set(dl_paths_variable_name DYLD_LIBRARY_PATH) -else() - set(dl_paths_variable_name LD_LIBRARY_PATH) -endif() - function(add_command NAME) set(_args "") # use ARGV* instead of ARGN, because ARGN splits arrays into multiple arguments @@ -38,119 +16,172 @@ function(add_command NAME) set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE) endfunction() -# Run test executable to get list of available tests -if(NOT EXISTS "${TEST_EXECUTABLE}") - message(FATAL_ERROR - "Specified test executable '${TEST_EXECUTABLE}' does not exist" +function(catch_discover_tests_impl) + + cmake_parse_arguments( + "" + "" + "TEST_EXECUTABLE;TEST_WORKING_DIR;TEST_DL_PATHS;TEST_OUTPUT_DIR;TEST_OUTPUT_PREFIX;TEST_OUTPUT_SUFFIX;TEST_PREFIX;TEST_REPORTER;TEST_SPEC;TEST_SUFFIX;TEST_LIST;CTEST_FILE" + "TEST_EXTRA_ARGS;TEST_PROPERTIES;TEST_EXECUTOR" + ${ARGN} ) -endif() -if(dl_paths) - cmake_path(CONVERT "${dl_paths}" TO_NATIVE_PATH_LIST paths) - set(ENV{${dl_paths_variable_name}} "${paths}") -endif() + set(prefix "${_TEST_PREFIX}") + set(suffix "${_TEST_SUFFIX}") + set(spec ${_TEST_SPEC}) + set(extra_args ${_TEST_EXTRA_ARGS}) + set(properties ${_TEST_PROPERTIES}) + set(reporter ${_TEST_REPORTER}) + set(output_dir ${_TEST_OUTPUT_DIR}) + set(output_prefix ${_TEST_OUTPUT_PREFIX}) + set(output_suffix ${_TEST_OUTPUT_SUFFIX}) + set(dl_paths ${_TEST_DL_PATHS}) + set(script) + set(suite) + set(tests) -execute_process( - COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-tests --verbosity quiet - OUTPUT_VARIABLE output - RESULT_VARIABLE result - WORKING_DIRECTORY "${TEST_WORKING_DIR}" -) -if(NOT ${result} EQUAL 0) - message(FATAL_ERROR - "Error running test executable '${TEST_EXECUTABLE}':\n" - " Result: ${result}\n" - " Output: ${output}\n" - ) -endif() + if(WIN32) + set(dl_paths_variable_name PATH) + elseif(APPLE) + set(dl_paths_variable_name DYLD_LIBRARY_PATH) + else() + set(dl_paths_variable_name LD_LIBRARY_PATH) + endif() -string(REPLACE "\n" ";" output "${output}") + # Run test executable to get list of available tests + if(NOT EXISTS "${_TEST_EXECUTABLE}") + message(FATAL_ERROR + "Specified test executable '${_TEST_EXECUTABLE}' does not exist" + ) + endif() -# Prepare reporter -if(reporter) - set(reporter_arg "--reporter ${reporter}") + if(dl_paths) + cmake_path(CONVERT "${dl_paths}" TO_NATIVE_PATH_LIST paths) + set(ENV{${dl_paths_variable_name}} "${paths}") + endif() - # Run test executable to check whether reporter is available - # note that the use of --list-reporters is not the important part, - # we only want to check whether the execution succeeds with ${reporter_arg} execute_process( - COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} ${reporter_arg} --list-reporters - OUTPUT_VARIABLE reporter_check_output - RESULT_VARIABLE reporter_check_result - WORKING_DIRECTORY "${TEST_WORKING_DIR}" + COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" ${spec} --list-tests --verbosity quiet + OUTPUT_VARIABLE output + RESULT_VARIABLE result + WORKING_DIRECTORY "${_TEST_WORKING_DIR}" ) - if(${reporter_check_result} EQUAL 255) + if(NOT ${result} EQUAL 0) message(FATAL_ERROR - "\"${reporter}\" is not a valid reporter!\n" - ) - elseif(NOT ${reporter_check_result} EQUAL 0) - message(FATAL_ERROR - "Error running test executable '${TEST_EXECUTABLE}':\n" - " Result: ${reporter_check_result}\n" - " Output: ${reporter_check_output}\n" + "Error running test executable '${_TEST_EXECUTABLE}':\n" + " Result: ${result}\n" + " Output: ${output}\n" ) endif() -endif() -# Prepare output dir -if(output_dir AND NOT IS_ABSOLUTE ${output_dir}) - set(output_dir "${TEST_WORKING_DIR}/${output_dir}") - if(NOT EXISTS ${output_dir}) - file(MAKE_DIRECTORY ${output_dir}) + string(REPLACE "\n" ";" output "${output}") + + # Prepare reporter + if(reporter) + set(reporter_arg "--reporter ${reporter}") + + # Run test executable to check whether reporter is available + # note that the use of --list-reporters is not the important part, + # we only want to check whether the execution succeeds with ${reporter_arg} + execute_process( + COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} ${reporter_arg} --list-reporters + OUTPUT_VARIABLE reporter_check_output + RESULT_VARIABLE reporter_check_result + WORKING_DIRECTORY "${TEST_WORKING_DIR}" + ) + if(${reporter_check_result} EQUAL 255) + message(FATAL_ERROR + "\"${reporter}\" is not a valid reporter!\n" + ) + elseif(NOT ${reporter_check_result} EQUAL 0) + message(FATAL_ERROR + "Error running test executable '${TEST_EXECUTABLE}':\n" + " Result: ${reporter_check_result}\n" + " Output: ${reporter_check_output}\n" + ) + endif() endif() -endif() -if(dl_paths) - foreach(path ${dl_paths}) - cmake_path(NATIVE_PATH path native_path) - list(APPEND environment_modifications "${dl_paths_variable_name}=path_list_prepend:${native_path}") + # Prepare output dir + if(output_dir AND NOT IS_ABSOLUTE ${output_dir}) + set(output_dir "${_TEST_WORKING_DIR}/${output_dir}") + if(NOT EXISTS ${output_dir}) + file(MAKE_DIRECTORY ${output_dir}) + endif() + endif() + + if(dl_paths) + foreach(path ${dl_paths}) + cmake_path(NATIVE_PATH path native_path) + list(APPEND environment_modifications "${dl_paths_variable_name}=path_list_prepend:${native_path}") + endforeach() + endif() + + # Parse output + foreach(line ${output}) + set(test ${line}) + # Escape characters in test case names that would be parsed by Catch2 + set(test_name ${test}) + foreach(char , [ ]) + string(REPLACE ${char} "\\${char}" test_name ${test_name}) + endforeach(char) + # ...add output dir + if(output_dir) + string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean ${test_name}) + set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}") + endif() + + # ...and add to script + add_command(add_test + "${prefix}${test}${suffix}" + ${_TEST_EXECUTOR} + "${_TEST_EXECUTABLE}" + "${test_name}" + ${extra_args} + "${reporter_arg}" + "${output_dir_arg}" + ) + add_command(set_tests_properties + "${prefix}${test}${suffix}" + PROPERTIES + WORKING_DIRECTORY "${_TEST_WORKING_DIR}" + ${properties} + ) + + if(environment_modifications) + add_command(set_tests_properties + "${prefix}${test}${suffix}" + PROPERTIES + ENVIRONMENT_MODIFICATION "${environment_modifications}") + endif() + + list(APPEND tests "${prefix}${test}${suffix}") endforeach() + + # Create a list of all discovered tests, which users may use to e.g. set + # properties on the tests + add_command(set ${_TEST_LIST} ${tests}) + + # Write CTest script + file(WRITE "${_CTEST_FILE}" "${script}") +endfunction() + +if(CMAKE_SCRIPT_MODE_FILE) + catch_discover_tests_impl( + TEST_EXECUTABLE ${TEST_EXECUTABLE} + TEST_EXECUTOR ${TEST_EXECUTOR} + TEST_WORKING_DIR ${TEST_WORKING_DIR} + TEST_SPEC ${TEST_SPEC} + TEST_EXTRA_ARGS ${TEST_EXTRA_ARGS} + TEST_PROPERTIES ${TEST_PROPERTIES} + TEST_PREFIX ${TEST_PREFIX} + TEST_SUFFIX ${TEST_SUFFIX} + TEST_LIST ${TEST_LIST} + TEST_REPORTER ${TEST_REPORTER} + TEST_OUTPUT_DIR ${TEST_OUTPUT_DIR} + TEST_OUTPUT_PREFIX ${TEST_OUTPUT_PREFIX} + TEST_OUTPUT_SUFFIX ${TEST_OUTPUT_SUFFIX} + TEST_DL_PATHS ${TEST_DL_PATHS} + CTEST_FILE ${CTEST_FILE} + ) endif() - -# Parse output -foreach(line ${output}) - set(test ${line}) - # Escape characters in test case names that would be parsed by Catch2 - set(test_name ${test}) - foreach(char , [ ]) - string(REPLACE ${char} "\\${char}" test_name ${test_name}) - endforeach(char) - # ...add output dir - if(output_dir) - string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean ${test_name}) - set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}") - endif() - - # ...and add to script - add_command(add_test - "${prefix}${test}${suffix}" - ${TEST_EXECUTOR} - "${TEST_EXECUTABLE}" - "${test_name}" - ${extra_args} - "${reporter_arg}" - "${output_dir_arg}" - ) - add_command(set_tests_properties - "${prefix}${test}${suffix}" - PROPERTIES - WORKING_DIRECTORY "${TEST_WORKING_DIR}" - ${properties} - ) - - if(environment_modifications) - add_command(set_tests_properties - "${prefix}${test}${suffix}" - PROPERTIES - ENVIRONMENT_MODIFICATION "${environment_modifications}") - endif() - - list(APPEND tests "${prefix}${test}${suffix}") -endforeach() - -# Create a list of all discovered tests, which users may use to e.g. set -# properties on the tests -add_command(set ${TEST_LIST} ${tests}) - -# Write CTest script -file(WRITE "${CTEST_FILE}" "${script}") From aad926baf87bb0121afc07b100e61f2b344ce156 Mon Sep 17 00:00:00 2001 From: Holger Kaelberer Date: Tue, 11 Apr 2023 09:50:16 +0200 Subject: [PATCH 02/26] Catch.cmake: Add new DISCOVERY_MODE option to catch_discover_tests Introducing a new DISCOVERY_MODE mode option, which provides greater control over when catch_discover_tests perforsm test discovery. It has two supported modes: * POST_BUILD: The default behavior, which adds a POST_BUILD command to perform test discovery after the test has been built as was always done so far. * PRE_TEST: New mode, which delays test discovery until test execution. The generated include file generates the appropriate CTest files at runtime and regenerates the CTest files when the executable is updated. This mode can be used in build-environments that don't allow for executing the linked binaries at build-time (like in a cross-compilation environment). DISCOVERY_MODE can be controlled in two ways: 1. Setting the DISCOVERY_MODE when calling catch_discover_tests. 2. Setting the global CMAKE_CATCH_DISCOVER_TESTS_DISCOVERY_MODE prior to calling gtest_discover_tests. Closes #2493 --- docs/cmake-integration.md | 11 ++++ extras/Catch.cmake | 131 +++++++++++++++++++++++++++----------- 2 files changed, 106 insertions(+), 36 deletions(-) diff --git a/docs/cmake-integration.md b/docs/cmake-integration.md index 0720a95b..e38d5c2f 100644 --- a/docs/cmake-integration.md +++ b/docs/cmake-integration.md @@ -126,6 +126,7 @@ catch_discover_tests(target [OUTPUT_DIR dir] [OUTPUT_PREFIX prefix] [OUTPUT_SUFFIX suffix] + [DISCOVERY_MODE ] ) ``` @@ -198,6 +199,16 @@ If specified, `suffix` is added to each output file name, like so `--out dir/suffix`. This can be used to add a file extension to the output file name e.g. ".xml". +* `DISCOVERY_MODE mode` + +If specified allows control over when test discovery is performed. +For a value of `POST_BUILD` (default) test discovery is performed at build time. +For a a value of `PRE_TEST` test discovery is delayed until just prior to test +execution (useful e.g. in cross-compilation environments). +``DISCOVERY_MODE`` defaults to the value of the +``CMAKE_CATCH_DISCOVER_TESTS_DISCOVERY_MODE`` variable if it is not passed when +calling ``catch_discover_tests``. This provides a mechanism for globally +selecting a preferred test discovery behavior. ### `ParseAndAddCatchTests.cmake` diff --git a/extras/Catch.cmake b/extras/Catch.cmake index 8e712b77..b37b0bf6 100644 --- a/extras/Catch.cmake +++ b/extras/Catch.cmake @@ -37,6 +37,7 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. [OUTPUT_DIR dir] [OUTPUT_PREFIX prefix] [OUTPUT_SUFFIX suffix] + [DISCOVERY_MODE ] ) ``catch_discover_tests`` sets up a post-build command on the test executable @@ -123,14 +124,28 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. test executable and when the tests are executed themselves. This requires cmake/ctest >= 3.22. + `DISCOVERY_MODE mode`` + Provides control over when ``catch_discover_tests`` performs test discovery. + By default, ``POST_BUILD`` sets up a post-build command to perform test discovery + at build time. In certain scenarios, like cross-compiling, this ``POST_BUILD`` + behavior is not desirable. By contrast, ``PRE_TEST`` delays test discovery until + just prior to test execution. This way test discovery occurs in the target environment + where the test has a better chance at finding appropriate runtime dependencies. + + ``DISCOVERY_MODE`` defaults to the value of the + ``CMAKE_CATCH_DISCOVER_TESTS_DISCOVERY_MODE`` variable if it is not passed when + calling ``catch_discover_tests``. This provides a mechanism for globally selecting + a preferred test discovery behavior without having to modify each call site. + #]=======================================================================] #------------------------------------------------------------------------------ function(catch_discover_tests TARGET) + cmake_parse_arguments( "" "" - "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;REPORTER;OUTPUT_DIR;OUTPUT_PREFIX;OUTPUT_SUFFIX" + "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;REPORTER;OUTPUT_DIR;OUTPUT_PREFIX;OUTPUT_SUFFIX;DISCOVERY_MODE" "TEST_SPEC;EXTRA_ARGS;PROPERTIES;DL_PATHS" ${ARGN} ) @@ -141,12 +156,20 @@ function(catch_discover_tests TARGET) if(NOT _TEST_LIST) set(_TEST_LIST ${TARGET}_TESTS) endif() - if (_DL_PATHS) if(${CMAKE_VERSION} VERSION_LESS "3.22.0") message(FATAL_ERROR "The DL_PATHS option requires at least cmake 3.22") endif() endif() + if(NOT _DISCOVERY_MODE) + if(NOT CMAKE_CATCH_DISCOVER_TESTS_DISCOVERY_MODE) + set(CMAKE_CATCH_DISCOVER_TESTS_DISCOVERY_MODE "POST_BUILD") + endif() + set(_DISCOVERY_MODE ${CMAKE_CATCH_DISCOVER_TESTS_DISCOVERY_MODE}) + endif() + if (NOT _DISCOVERY_MODE MATCHES "^(POST_BUILD|PRE_TEST)$") + message(FATAL_ERROR "Unknown DISCOVERY_MODE: ${_DISCOVERY_MODE}") + endif() ## Generate a unique name based on the extra arguments string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS} ${_REPORTER} ${_OUTPUT_DIR} ${_OUTPUT_PREFIX} ${_OUTPUT_SUFFIX}") @@ -159,39 +182,77 @@ function(catch_discover_tests TARGET) TARGET ${TARGET} PROPERTY CROSSCOMPILING_EMULATOR ) - add_custom_command( - TARGET ${TARGET} POST_BUILD - BYPRODUCTS "${ctest_tests_file}" - COMMAND "${CMAKE_COMMAND}" - -D "TEST_TARGET=${TARGET}" - -D "TEST_EXECUTABLE=$" - -D "TEST_EXECUTOR=${crosscompiling_emulator}" - -D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}" - -D "TEST_SPEC=${_TEST_SPEC}" - -D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}" - -D "TEST_PROPERTIES=${_PROPERTIES}" - -D "TEST_PREFIX=${_TEST_PREFIX}" - -D "TEST_SUFFIX=${_TEST_SUFFIX}" - -D "TEST_LIST=${_TEST_LIST}" - -D "TEST_REPORTER=${_REPORTER}" - -D "TEST_OUTPUT_DIR=${_OUTPUT_DIR}" - -D "TEST_OUTPUT_PREFIX=${_OUTPUT_PREFIX}" - -D "TEST_OUTPUT_SUFFIX=${_OUTPUT_SUFFIX}" - -D "TEST_DL_PATHS=${_DL_PATHS}" - -D "CTEST_FILE=${ctest_tests_file}" - -P "${_CATCH_DISCOVER_TESTS_SCRIPT}" - VERBATIM - ) - file(WRITE "${ctest_include_file}" - "if(EXISTS \"${ctest_tests_file}\")\n" - " include(\"${ctest_tests_file}\")\n" - "else()\n" - " add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n" - "endif()\n" - ) + if(_DISCOVERY_MODE STREQUAL "POST_BUILD") + add_custom_command( + TARGET ${TARGET} POST_BUILD + BYPRODUCTS "${ctest_tests_file}" + COMMAND "${CMAKE_COMMAND}" + -D "TEST_TARGET=${TARGET}" + -D "TEST_EXECUTABLE=$" + -D "TEST_EXECUTOR=${crosscompiling_emulator}" + -D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}" + -D "TEST_SPEC=${_TEST_SPEC}" + -D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}" + -D "TEST_PROPERTIES=${_PROPERTIES}" + -D "TEST_PREFIX=${_TEST_PREFIX}" + -D "TEST_SUFFIX=${_TEST_SUFFIX}" + -D "TEST_LIST=${_TEST_LIST}" + -D "TEST_REPORTER=${_REPORTER}" + -D "TEST_OUTPUT_DIR=${_OUTPUT_DIR}" + -D "TEST_OUTPUT_PREFIX=${_OUTPUT_PREFIX}" + -D "TEST_OUTPUT_SUFFIX=${_OUTPUT_SUFFIX}" + -D "TEST_DL_PATHS=${_DL_PATHS}" + -D "CTEST_FILE=${ctest_tests_file}" + -P "${_CATCH_DISCOVER_TESTS_SCRIPT}" + VERBATIM + ) - if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0") + file(WRITE "${ctest_include_file}" + "if(EXISTS \"${ctest_tests_file}\")\n" + " include(\"${ctest_tests_file}\")\n" + "else()\n" + " add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n" + "endif()\n" + ) + + elseif(_DISCOVERY_MODE STREQUAL "PRE_TEST") + + string(CONCAT ctest_include_content + "if(EXISTS \"$\")" "\n" + " if(NOT EXISTS \"${ctest_tests_file}\" OR" "\n" + " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"$\" OR\n" + " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"\${CMAKE_CURRENT_LIST_FILE}\")\n" + " include(\"${_CATCH_DISCOVER_TESTS_SCRIPT}\")" "\n" + " catch_discover_tests_impl(" "\n" + " TEST_EXECUTABLE" " [==[" "$" "]==]" "\n" + " TEST_EXECUTOR" " [==[" "${crosscompiling_emulator}" "]==]" "\n" + " TEST_WORKING_DIR" " [==[" "${_WORKING_DIRECTORY}" "]==]" "\n" + " TEST_SPEC" " [==[" "${_TEST_SPEC}" "]==]" "\n" + " TEST_EXTRA_ARGS" " [==[" "${_EXTRA_ARGS}" "]==]" "\n" + " TEST_PROPERTIES" " [==[" "${_PROPERTIES}" "]==]" "\n" + " TEST_PREFIX" " [==[" "${_TEST_PREFIX}" "]==]" "\n" + " TEST_SUFFIX" " [==[" "${_TEST_SUFFIX}" "]==]" "\n" + " TEST_LIST" " [==[" "${_TEST_LIST}" "]==]" "\n" + " TEST_REPORTER" " [==[" "${_REPORTER}" "]==]" "\n" + " TEST_OUTPUT_DIR" " [==[" "${_OUTPUT_DIR}" "]==]" "\n" + " TEST_OUTPUT_PREFIX" " [==[" "${_OUTPUT_PREFIX}" "]==]" "\n" + " TEST_OUTPUT_SUFFIX" " [==[" "${_OUTPUT_SUFFIX}" "]==]" "\n" + " CTEST_FILE" " [==[" "${ctest_tests_file}" "]==]" "\n" + " TEST_DL_PATHS" " [==[" "${_DL_PATHS}" "]==]" "\n" + " CTEST_FILE" " [==[" "${CTEST_FILE}" "]==]" "\n" + " )" "\n" + " endif()" "\n" + " include(\"${ctest_tests_file}\")" "\n" + "else()" "\n" + " add_test(${TARGET}_NOT_BUILT ${TARGET}_NOT_BUILT)" "\n" + "endif()" "\n" + ) + + file(GENERATE OUTPUT "${ctest_include_file}" CONTENT "${ctest_include_content}") + endif() + + if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0") # Add discovered tests to directory TEST_INCLUDE_FILES set_property(DIRECTORY APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}" @@ -204,9 +265,7 @@ function(catch_discover_tests TARGET) PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}" ) else() - message(FATAL_ERROR - "Cannot set more than one TEST_INCLUDE_FILE" - ) + message(FATAL_ERROR "Cannot set more than one TEST_INCLUDE_FILE") endif() endif() From 897fe2a01b7e1983b076ef41f4ce11c5b3e498c6 Mon Sep 17 00:00:00 2001 From: Holger Kaelberer Date: Wed, 19 Apr 2023 10:12:44 +0200 Subject: [PATCH 03/26] cmake: Improve unreachable-code warnings Enable CI to report -Wunreachable-code-aggressive warnings in clang builds which covers all, -Wunreachable-code, -code-break, -code-return. --- CMake/CatchMiscFunctions.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMake/CatchMiscFunctions.cmake b/CMake/CatchMiscFunctions.cmake index 3758d956..735c7868 100644 --- a/CMake/CatchMiscFunctions.cmake +++ b/CMake/CatchMiscFunctions.cmake @@ -83,7 +83,7 @@ function(add_warnings_to_targets targets) "-Wundef" "-Wuninitialized" "-Wunneeded-internal-declaration" - "-Wunreachable-code" + "-Wunreachable-code-aggressive" "-Wunused" "-Wunused-function" "-Wunused-parameter" From 10596b22781f03df3d35f34187213f6f8709e453 Mon Sep 17 00:00:00 2001 From: Holger Kaelberer Date: Wed, 19 Apr 2023 10:28:45 +0200 Subject: [PATCH 04/26] Fix unreachable-code-return warnings --- src/catch2/internal/catch_reporter_registry.cpp | 2 -- tests/SelfTest/UsageTests/Exception.tests.cpp | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/catch2/internal/catch_reporter_registry.cpp b/src/catch2/internal/catch_reporter_registry.cpp index 8f13ae56..b2b0cd07 100644 --- a/src/catch2/internal/catch_reporter_registry.cpp +++ b/src/catch2/internal/catch_reporter_registry.cpp @@ -57,8 +57,6 @@ namespace Catch { auto it = m_impl->factories.find( name ); if ( it == m_impl->factories.end() ) return nullptr; return it->second->create( CATCH_MOVE( config ) ); - - return IEventListenerPtr(); } void ReporterRegistry::registerReporter( std::string const& name, diff --git a/tests/SelfTest/UsageTests/Exception.tests.cpp b/tests/SelfTest/UsageTests/Exception.tests.cpp index f917932f..4f91a30c 100644 --- a/tests/SelfTest/UsageTests/Exception.tests.cpp +++ b/tests/SelfTest/UsageTests/Exception.tests.cpp @@ -20,7 +20,7 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wweak-vtables" #pragma clang diagnostic ignored "-Wmissing-noreturn" -#pragma clang diagnostic ignored "-Wunreachable-code" +#pragma clang diagnostic ignored "-Wunreachable-code-return" #endif namespace { From 46539b6d9b1d429fcc2261d3e687482c878a9ddb Mon Sep 17 00:00:00 2001 From: Vertexwahn Date: Tue, 25 Apr 2023 20:14:27 +0200 Subject: [PATCH 05/26] Fix spelling --- docs/faq.md | 2 +- docs/generators.md | 2 +- docs/opensource-users.md | 2 +- docs/release-notes.md | 8 ++++---- examples/302-Gen-Table.cpp | 4 ++-- src/catch2/catch_config.cpp | 2 +- src/catch2/catch_user_config.hpp.in | 2 +- src/catch2/interfaces/catch_interfaces_reporter.hpp | 2 +- src/catch2/internal/catch_test_case_tracker.hpp | 2 +- src/catch2/internal/catch_textflow.hpp | 2 +- src/catch2/matchers/catch_matchers_range_equals.hpp | 2 +- .../reporters/catch_reporter_cumulative_base.hpp | 2 +- tests/SelfTest/Baselines/console.sw.approved.txt | 12 ++++++------ .../SelfTest/Baselines/console.sw.multi.approved.txt | 12 ++++++------ tests/SelfTest/Baselines/junit.sw.approved.txt | 12 ++++++------ tests/SelfTest/Baselines/junit.sw.multi.approved.txt | 12 ++++++------ tests/SelfTest/Baselines/sonarqube.sw.approved.txt | 12 ++++++------ .../Baselines/sonarqube.sw.multi.approved.txt | 12 ++++++------ tests/SelfTest/Baselines/xml.sw.approved.txt | 12 ++++++------ tests/SelfTest/Baselines/xml.sw.multi.approved.txt | 12 ++++++------ tests/SelfTest/UsageTests/MatchersRanges.tests.cpp | 12 ++++++------ tools/scripts/updateDocumentToC.py | 2 +- 22 files changed, 71 insertions(+), 71 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 0f303ee5..a7d0455a 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -28,7 +28,7 @@ depending on how often the cleanup needs to happen. ## Why cannot I derive from the built-in reporters? They are not made to be overridden, in that we do not attempt to maintain -a consistent internal state if a member function is overriden, and by +a consistent internal state if a member function is overridden, and by forbidding users from using them as a base class, we can refactor them as needed later. diff --git a/docs/generators.md b/docs/generators.md index 69d1a02d..37d7424a 100644 --- a/docs/generators.md +++ b/docs/generators.md @@ -134,7 +134,7 @@ type, making their usage much nicer. These are * `map(func, GeneratorWrapper&&)` for `MapGenerator` (map `U` to `T`) * `chunk(chunk-size, GeneratorWrapper&&)` for `ChunkGenerator` * `random(IntegerOrFloat a, IntegerOrFloat b)` for `RandomIntegerGenerator` or `RandomFloatGenerator` -* `range(Arithemtic start, Arithmetic end)` for `RangeGenerator` with a step size of `1` +* `range(Arithmetic start, Arithmetic end)` for `RangeGenerator` with a step size of `1` * `range(Arithmetic start, Arithmetic end, Arithmetic step)` for `RangeGenerator` with a custom step size * `from_range(InputIterator from, InputIterator to)` for `IteratorGenerator` * `from_range(Container const&)` for `IteratorGenerator` diff --git a/docs/opensource-users.md b/docs/opensource-users.md index 9dcd38df..df015f08 100644 --- a/docs/opensource-users.md +++ b/docs/opensource-users.md @@ -143,7 +143,7 @@ Newsbeuter is an open-source RSS/Atom feed reader for text terminals. A 2D, Zombie, RPG game which is being made on our own engine. ### [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). +Low level CLI app and library for execution of GCODE on Raspberry Pi without any additional microcontrollers (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/release-notes.md b/docs/release-notes.md index 1fa37da4..8b413b15 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -149,7 +149,7 @@ ### Fixes * Cleaned out some warnings and static analysis issues - * Suppressed `-Wcomma` warning rarely occuring in templated test cases (#2543) + * Suppressed `-Wcomma` warning rarely occurring in templated test cases (#2543) * Constified implementation details in `INFO` (#2564) * Made `MatcherGenericBase` copy constructor const (#2566) * Fixed serialization of test filters so the output roundtrips @@ -517,7 +517,7 @@ v3 releases. * The `SECTION`(s) before the `GENERATE` will not be run multiple times, the following ones will. * Added `-D`/`--min-duration` command line flag (#1910) * If a test takes longer to finish than the provided value, its name and duration will be printed. - * This flag is overriden by setting `-d`/`--duration`. + * This flag is overridden by setting `-d`/`--duration`. ### Fixes * `TAPReporter` no longer skips successful assertions (#1983) @@ -585,7 +585,7 @@ v3 releases. ### Fixes * Fixed computation of benchmarking column widths in ConsoleReporter (#1885, #1886) * Suppressed clang-tidy's `cppcoreguidelines-pro-type-vararg` in assertions (#1901) - * It was a false positive trigered by the new warning support workaround + * It was a false positive triggered by the new warning support workaround * Fixed bug in test specification parser handling of OR'd patterns using escaping (#1905) ### Miscellaneous @@ -922,7 +922,7 @@ v3 releases. ### Contrib * `ParseAndAddCatchTests` has learned how to use `DISABLED` CTest property (#1452) -* `ParseAndAddCatchTests` now works when there is a whitspace before the test name (#1493) +* `ParseAndAddCatchTests` now works when there is a whitespace before the test name (#1493) ### Miscellaneous diff --git a/examples/302-Gen-Table.cpp b/examples/302-Gen-Table.cpp index 74319518..97809889 100644 --- a/examples/302-Gen-Table.cpp +++ b/examples/302-Gen-Table.cpp @@ -44,11 +44,11 @@ TEST_CASE("Table allows pre-computed test inputs and outputs", "[example][genera /* Possible simplifications where less legacy toolchain support is needed: * - * - With libstdc++6 or newer, the make_tuple() calls can be ommitted + * - With libstdc++6 or newer, the make_tuple() calls can be omitted * (technically C++17 but does not require -std in GCC/Clang). See * https://stackoverflow.com/questions/12436586/tuple-vector-and-initializer-list * - * - In C++17 mode std::tie() and the preceding variable delcarations can be + * - In C++17 mode std::tie() and the preceding variable declarations can be * replaced by structured bindings: auto [test_input, expected] = GENERATE( * table({ ... */ diff --git a/src/catch2/catch_config.cpp b/src/catch2/catch_config.cpp index eb4f5ad3..34f50f17 100644 --- a/src/catch2/catch_config.cpp +++ b/src/catch2/catch_config.cpp @@ -105,7 +105,7 @@ namespace Catch { elem = trim(elem); } - // Insert the default reporter if user hasn't asked for a specfic one + // Insert the default reporter if user hasn't asked for a specific one if ( m_data.reporterSpecifications.empty() ) { m_data.reporterSpecifications.push_back( { #if defined( CATCH_CONFIG_DEFAULT_REPORTER ) diff --git a/src/catch2/catch_user_config.hpp.in b/src/catch2/catch_user_config.hpp.in index 3f6b10e8..f7973af1 100644 --- a/src/catch2/catch_user_config.hpp.in +++ b/src/catch2/catch_user_config.hpp.in @@ -171,7 +171,7 @@ // ------ // Simple toggle defines -// their value is never used and they cannot be overriden +// their value is never used and they cannot be overridden // ------ diff --git a/src/catch2/interfaces/catch_interfaces_reporter.hpp b/src/catch2/interfaces/catch_interfaces_reporter.hpp index 0ce62e86..b40fce31 100644 --- a/src/catch2/interfaces/catch_interfaces_reporter.hpp +++ b/src/catch2/interfaces/catch_interfaces_reporter.hpp @@ -205,7 +205,7 @@ namespace Catch { */ virtual void skipTest( TestCaseInfo const& testInfo ) = 0; - //! Called if a fatal error (signal/structured exception) occured + //! Called if a fatal error (signal/structured exception) occurred virtual void fatalErrorEncountered( StringRef error ) = 0; //! Writes out information about provided reporters using reporter-specific format diff --git a/src/catch2/internal/catch_test_case_tracker.hpp b/src/catch2/internal/catch_test_case_tracker.hpp index beff8d6d..50278c91 100644 --- a/src/catch2/internal/catch_test_case_tracker.hpp +++ b/src/catch2/internal/catch_test_case_tracker.hpp @@ -113,7 +113,7 @@ namespace TestCaseTracking { //! Returns true if tracker run to completion (successfully or not) virtual bool isComplete() const = 0; - //! Returns true if tracker run to completion succesfully + //! Returns true if tracker run to completion successfully bool isSuccessfullyCompleted() const { return m_runState == CompletedSuccessfully; } diff --git a/src/catch2/internal/catch_textflow.hpp b/src/catch2/internal/catch_textflow.hpp index ceac675d..0776ab92 100644 --- a/src/catch2/internal/catch_textflow.hpp +++ b/src/catch2/internal/catch_textflow.hpp @@ -59,7 +59,7 @@ namespace Catch { // Calculates the length of the current line void calcLength(); - // Returns current indention width + // Returns current indentation width size_t indentSize() const; // Creates an indented and (optionally) suffixed string from diff --git a/src/catch2/matchers/catch_matchers_range_equals.hpp b/src/catch2/matchers/catch_matchers_range_equals.hpp index ce66bed9..95b781a4 100644 --- a/src/catch2/matchers/catch_matchers_range_equals.hpp +++ b/src/catch2/matchers/catch_matchers_range_equals.hpp @@ -129,7 +129,7 @@ namespace Catch { /** * Creates a matcher that checks if all elements in a range are equal - * to all elements in another range, in some permuation. + * to all elements in another range, in some permutation. * * Uses to provided predicate `predicate` to do the comparisons */ diff --git a/src/catch2/reporters/catch_reporter_cumulative_base.hpp b/src/catch2/reporters/catch_reporter_cumulative_base.hpp index 691e1f95..267b39fd 100644 --- a/src/catch2/reporters/catch_reporter_cumulative_base.hpp +++ b/src/catch2/reporters/catch_reporter_cumulative_base.hpp @@ -124,7 +124,7 @@ namespace Catch { void skipTest(TestCaseInfo const&) override {} protected: - //! Should the cumulative base store the assertion expansion for succesful assertions? + //! Should the cumulative base store the assertion expansion for successful assertions? bool m_shouldStoreSuccesfulAssertions = true; //! Should the cumulative base store the assertion expansion for failed assertions? bool m_shouldStoreFailedAssertions = true; diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index 26d5e8f3..db724867 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -13460,7 +13460,7 @@ with expansion: ------------------------------------------------------------------------------- Usage of AllTrue range matcher Basic usage - One false evalutes to false + One false evaluates to false ------------------------------------------------------------------------------- MatchersRanges.tests.cpp: ............................................................................... @@ -13499,7 +13499,7 @@ with expansion: ------------------------------------------------------------------------------- Usage of AllTrue range matcher Contained type is convertible to bool - One false evalutes to false + One false evaluates to false ------------------------------------------------------------------------------- MatchersRanges.tests.cpp: ............................................................................... @@ -13735,7 +13735,7 @@ with expansion: ------------------------------------------------------------------------------- Usage of AnyTrue range matcher Basic usage - One true evalutes to true + One true evaluates to true ------------------------------------------------------------------------------- MatchersRanges.tests.cpp: ............................................................................... @@ -13774,7 +13774,7 @@ with expansion: ------------------------------------------------------------------------------- Usage of AnyTrue range matcher Contained type is convertible to bool - One true evalutes to true + One true evaluates to true ------------------------------------------------------------------------------- MatchersRanges.tests.cpp: ............................................................................... @@ -14010,7 +14010,7 @@ with expansion: ------------------------------------------------------------------------------- Usage of NoneTrue range matcher Basic usage - One true evalutes to false + One true evaluates to false ------------------------------------------------------------------------------- MatchersRanges.tests.cpp: ............................................................................... @@ -14049,7 +14049,7 @@ with expansion: ------------------------------------------------------------------------------- Usage of NoneTrue range matcher Contained type is convertible to bool - One true evalutes to false + One true evaluates to false ------------------------------------------------------------------------------- MatchersRanges.tests.cpp: ............................................................................... diff --git a/tests/SelfTest/Baselines/console.sw.multi.approved.txt b/tests/SelfTest/Baselines/console.sw.multi.approved.txt index 80b63ab8..67b2dcb8 100644 --- a/tests/SelfTest/Baselines/console.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.multi.approved.txt @@ -13453,7 +13453,7 @@ with expansion: ------------------------------------------------------------------------------- Usage of AllTrue range matcher Basic usage - One false evalutes to false + One false evaluates to false ------------------------------------------------------------------------------- MatchersRanges.tests.cpp: ............................................................................... @@ -13492,7 +13492,7 @@ with expansion: ------------------------------------------------------------------------------- Usage of AllTrue range matcher Contained type is convertible to bool - One false evalutes to false + One false evaluates to false ------------------------------------------------------------------------------- MatchersRanges.tests.cpp: ............................................................................... @@ -13728,7 +13728,7 @@ with expansion: ------------------------------------------------------------------------------- Usage of AnyTrue range matcher Basic usage - One true evalutes to true + One true evaluates to true ------------------------------------------------------------------------------- MatchersRanges.tests.cpp: ............................................................................... @@ -13767,7 +13767,7 @@ with expansion: ------------------------------------------------------------------------------- Usage of AnyTrue range matcher Contained type is convertible to bool - One true evalutes to true + One true evaluates to true ------------------------------------------------------------------------------- MatchersRanges.tests.cpp: ............................................................................... @@ -14003,7 +14003,7 @@ with expansion: ------------------------------------------------------------------------------- Usage of NoneTrue range matcher Basic usage - One true evalutes to false + One true evaluates to false ------------------------------------------------------------------------------- MatchersRanges.tests.cpp: ............................................................................... @@ -14042,7 +14042,7 @@ with expansion: ------------------------------------------------------------------------------- Usage of NoneTrue range matcher Contained type is convertible to bool - One true evalutes to false + One true evaluates to false ------------------------------------------------------------------------------- MatchersRanges.tests.cpp: ............................................................................... diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index 25129349..cf0c9170 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1401,10 +1401,10 @@ at Exception.tests.cpp: - + - + @@ -1414,10 +1414,10 @@ at Exception.tests.cpp: - + - + @@ -1427,10 +1427,10 @@ at Exception.tests.cpp: - + - + diff --git a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt index 6220d8e2..f900bc99 100644 --- a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt @@ -1400,10 +1400,10 @@ at Exception.tests.cpp: - + - + @@ -1413,10 +1413,10 @@ at Exception.tests.cpp: - + - + @@ -1426,10 +1426,10 @@ at Exception.tests.cpp: - + - + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index a4e08bd2..5e78a714 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -1389,10 +1389,10 @@ at Matchers.tests.cpp: - + - + @@ -1402,10 +1402,10 @@ at Matchers.tests.cpp: - + - + @@ -1415,10 +1415,10 @@ at Matchers.tests.cpp: - + - + diff --git a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt index c00defae..b8f7d646 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt @@ -1388,10 +1388,10 @@ at Matchers.tests.cpp: - + - + @@ -1401,10 +1401,10 @@ at Matchers.tests.cpp: - + - + @@ -1414,10 +1414,10 @@ at Matchers.tests.cpp: - + - + diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index d4d4858b..aaf28b61 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -15670,7 +15670,7 @@ There is no extra whitespace here
-
+
data, !AllTrue() @@ -15712,7 +15712,7 @@ There is no extra whitespace here
-
+
data, !AllTrue() @@ -16020,7 +16020,7 @@ There is no extra whitespace here
-
+
data, AnyTrue() @@ -16062,7 +16062,7 @@ There is no extra whitespace here
-
+
data, AnyTrue() @@ -16370,7 +16370,7 @@ There is no extra whitespace here
-
+
data, !NoneTrue() @@ -16412,7 +16412,7 @@ There is no extra whitespace here
-
+
data, !NoneTrue() diff --git a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt index 12229a99..706c4ac9 100644 --- a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt @@ -15670,7 +15670,7 @@ There is no extra whitespace here
-
+
data, !AllTrue() @@ -15712,7 +15712,7 @@ There is no extra whitespace here
-
+
data, !AllTrue() @@ -16020,7 +16020,7 @@ There is no extra whitespace here
-
+
data, AnyTrue() @@ -16062,7 +16062,7 @@ There is no extra whitespace here
-
+
data, AnyTrue() @@ -16370,7 +16370,7 @@ There is no extra whitespace here
-
+
data, !NoneTrue() @@ -16412,7 +16412,7 @@ There is no extra whitespace here
-
+
data, !NoneTrue() diff --git a/tests/SelfTest/UsageTests/MatchersRanges.tests.cpp b/tests/SelfTest/UsageTests/MatchersRanges.tests.cpp index 05e11b0c..cc8c54f8 100644 --- a/tests/SelfTest/UsageTests/MatchersRanges.tests.cpp +++ b/tests/SelfTest/UsageTests/MatchersRanges.tests.cpp @@ -381,7 +381,7 @@ TEST_CASE("Usage of AllTrue range matcher", "[matchers][templated][quantifiers]" std::array const data{}; REQUIRE_THAT( data, AllTrue() ); } - SECTION( "One false evalutes to false" ) { + SECTION( "One false evaluates to false" ) { std::array const data{ { true, true, false, true, true } }; REQUIRE_THAT( data, !AllTrue() ); } @@ -398,7 +398,7 @@ TEST_CASE("Usage of AllTrue range matcher", "[matchers][templated][quantifiers]" { { true }, { true }, { true }, { true }, { true } } }; REQUIRE_THAT( data, AllTrue() ); } - SECTION( "One false evalutes to false" ) { + SECTION( "One false evaluates to false" ) { std::array const data{ { { true }, { true }, { false }, { true }, { true } } }; REQUIRE_THAT( data, !AllTrue() ); @@ -446,7 +446,7 @@ TEST_CASE( "Usage of NoneTrue range matcher", "[matchers][templated][quantifiers std::array const data{}; REQUIRE_THAT( data, NoneTrue() ); } - SECTION( "One true evalutes to false" ) { + SECTION( "One true evaluates to false" ) { std::array const data{ { false, false, true, false, false } }; REQUIRE_THAT( data, !NoneTrue() ); @@ -464,7 +464,7 @@ TEST_CASE( "Usage of NoneTrue range matcher", "[matchers][templated][quantifiers { { true }, { true }, { true }, { true }, { true } } }; REQUIRE_THAT( data, !NoneTrue() ); } - SECTION( "One true evalutes to false" ) { + SECTION( "One true evaluates to false" ) { std::array const data{ { { false }, { false }, { true }, { false }, { false } } }; REQUIRE_THAT( data, !NoneTrue() ); @@ -512,7 +512,7 @@ TEST_CASE( "Usage of AnyTrue range matcher", "[matchers][templated][quantifiers] std::array const data{}; REQUIRE_THAT( data, !AnyTrue() ); } - SECTION( "One true evalutes to true" ) { + SECTION( "One true evaluates to true" ) { std::array const data{ { false, false, true, false, false } }; REQUIRE_THAT( data, AnyTrue() ); @@ -530,7 +530,7 @@ TEST_CASE( "Usage of AnyTrue range matcher", "[matchers][templated][quantifiers] { { true }, { true }, { true }, { true }, { true } } }; REQUIRE_THAT( data, AnyTrue() ); } - SECTION( "One true evalutes to true" ) { + SECTION( "One true evaluates to true" ) { std::array const data{ { { false }, { false }, { true }, { false }, { false } } }; REQUIRE_THAT( data, AnyTrue() ); diff --git a/tools/scripts/updateDocumentToC.py b/tools/scripts/updateDocumentToC.py index 7b56cfc7..1840cecc 100755 --- a/tools/scripts/updateDocumentToC.py +++ b/tools/scripts/updateDocumentToC.py @@ -287,7 +287,7 @@ def markdownToclify( Path to the markdown output file. min_toc_len: int (default: 2) - Miniumum number of entries to create a table of contents for. + Minimum number of entries to create a table of contents for. github: bool (default: False) Uses GitHub TOC syntax if True. From f3c678c0ab2afd5511d6ea4ff82ad3c5349312c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 20 Apr 2023 20:56:48 +0200 Subject: [PATCH 06/26] Constexprify constants in estimate_clock.hpp --- .../benchmark/detail/catch_estimate_clock.hpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/catch2/benchmark/detail/catch_estimate_clock.hpp b/src/catch2/benchmark/detail/catch_estimate_clock.hpp index 907773f2..fb65450e 100644 --- a/src/catch2/benchmark/detail/catch_estimate_clock.hpp +++ b/src/catch2/benchmark/detail/catch_estimate_clock.hpp @@ -41,15 +41,15 @@ namespace Catch { return deltas; } - const auto warmup_iterations = 10000; - const auto warmup_time = std::chrono::milliseconds(100); - const auto minimum_ticks = 1000; - const auto warmup_seed = 10000; - const auto clock_resolution_estimation_time = std::chrono::milliseconds(500); - const auto clock_cost_estimation_time_limit = std::chrono::seconds(1); - const auto clock_cost_estimation_tick_limit = 100000; - const auto clock_cost_estimation_time = std::chrono::milliseconds(10); - const auto clock_cost_estimation_iterations = 10000; + constexpr auto warmup_iterations = 10000; + constexpr auto warmup_time = std::chrono::milliseconds(100); + constexpr auto minimum_ticks = 1000; + constexpr auto warmup_seed = 10000; + constexpr auto clock_resolution_estimation_time = std::chrono::milliseconds(500); + constexpr auto clock_cost_estimation_time_limit = std::chrono::seconds(1); + constexpr auto clock_cost_estimation_tick_limit = 100000; + constexpr auto clock_cost_estimation_time = std::chrono::milliseconds(10); + constexpr auto clock_cost_estimation_iterations = 10000; template int warmup() { From 7d07efc92b626da9d03223a3b5cfd5f80b7cc377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Thu, 20 Apr 2023 22:47:21 +0200 Subject: [PATCH 07/26] Clean up iterator usage in benchmarks Specifically we turned `mean`, `classify_outliers`, `jackknife`, into concrete functions that take only `const_iterator` from vecs, instead of generic iterators over anything. I also changed `resample` to take `const_iterator` instead of plain `iterator`, and similar for `standard_deviation`, and `analyse_samples`. --- src/catch2/benchmark/detail/catch_stats.cpp | 62 +++++++++++++++++++-- src/catch2/benchmark/detail/catch_stats.hpp | 53 +++++++----------- 2 files changed, 75 insertions(+), 40 deletions(-) diff --git a/src/catch2/benchmark/detail/catch_stats.cpp b/src/catch2/benchmark/detail/catch_stats.cpp index 514ed1f7..c6c87be3 100644 --- a/src/catch2/benchmark/detail/catch_stats.cpp +++ b/src/catch2/benchmark/detail/catch_stats.cpp @@ -26,7 +26,10 @@ namespace { using Catch::Benchmark::Detail::sample; template - sample resample(URng& rng, unsigned int resamples, std::vector::iterator first, std::vector::iterator last, Estimator& estimator) { + static sample resample(URng& rng, unsigned int resamples, + std::vector::const_iterator first, + std::vector::const_iterator last, + Estimator& estimator) { auto n = static_cast(last - first); std::uniform_int_distribution dist(0, n - 1); @@ -118,7 +121,8 @@ using Catch::Benchmark::Detail::sample; return p * x; } - double standard_deviation(std::vector::iterator first, std::vector::iterator last) { + double standard_deviation(std::vector::const_iterator first, + std::vector::const_iterator last) { auto m = Catch::Benchmark::Detail::mean(first, last); double variance = std::accumulate( first, last, @@ -161,6 +165,47 @@ namespace Catch { return xj + g * (xj1 - xj); } + OutlierClassification + classify_outliers( std::vector::const_iterator first, + std::vector::const_iterator last ) { + std::vector copy( first, last ); + + auto q1 = weighted_average_quantile( 1, 4, copy.begin(), copy.end() ); + auto q3 = weighted_average_quantile( 3, 4, copy.begin(), copy.end() ); + auto iqr = q3 - q1; + auto los = q1 - ( iqr * 3. ); + auto lom = q1 - ( iqr * 1.5 ); + auto him = q3 + ( iqr * 1.5 ); + auto his = q3 + ( iqr * 3. ); + + OutlierClassification o; + for ( ; first != last; ++first ) { + const double t = *first; + if ( t < los ) { + ++o.low_severe; + } else if ( t < lom ) { + ++o.low_mild; + } else if ( t > his ) { + ++o.high_severe; + } else if ( t > him ) { + ++o.high_mild; + } + ++o.samples_seen; + } + return o; + } + + double mean( std::vector::const_iterator first, + std::vector::const_iterator last ) { + auto count = last - first; + double sum = 0.; + while (first != last) { + sum += *first; + ++first; + } + return sum / static_cast(count); + } + double erfc_inv(double x) { return erf_inv(1.0 - x); @@ -210,7 +255,10 @@ namespace Catch { } - bootstrap_analysis analyse_samples(double confidence_level, unsigned int n_resamples, std::vector::iterator first, std::vector::iterator last) { + bootstrap_analysis analyse_samples(double confidence_level, + unsigned int n_resamples, + std::vector::iterator first, + std::vector::iterator last) { CATCH_INTERNAL_START_WARNINGS_SUPPRESSION CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS static std::random_device entropy; @@ -218,11 +266,12 @@ namespace Catch { auto n = static_cast(last - first); // seriously, one can't use integral types without hell in C++ - auto mean = &Detail::mean::iterator>; + auto mean = &Detail::mean; auto stddev = &standard_deviation; #if defined(CATCH_CONFIG_USE_ASYNC) - auto Estimate = [=](double(*f)(std::vector::iterator, std::vector::iterator)) { + auto Estimate = [=](double(*f)(std::vector::const_iterator, + std::vector::const_iterator)) { auto seed = entropy(); return std::async(std::launch::async, [=] { std::mt19937 rng(seed); @@ -237,7 +286,8 @@ namespace Catch { auto mean_estimate = mean_future.get(); auto stddev_estimate = stddev_future.get(); #else - auto Estimate = [=](double(*f)(std::vector::iterator, std::vector::iterator)) { + auto Estimate = [=](double(*f)(std::vector::const_iterator, + std::vector::const_iterator)) { auto seed = entropy(); std::mt19937 rng(seed); auto resampled = resample(rng, n_resamples, first, last, f); diff --git a/src/catch2/benchmark/detail/catch_stats.hpp b/src/catch2/benchmark/detail/catch_stats.hpp index 4c54ec52..b71c5842 100644 --- a/src/catch2/benchmark/detail/catch_stats.hpp +++ b/src/catch2/benchmark/detail/catch_stats.hpp @@ -30,39 +30,17 @@ namespace Catch { double weighted_average_quantile(int k, int q, std::vector::iterator first, std::vector::iterator last); - template - OutlierClassification classify_outliers(Iterator first, Iterator last) { - std::vector copy(first, last); + OutlierClassification + classify_outliers( std::vector::const_iterator first, + std::vector::const_iterator last ); - auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end()); - auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end()); - auto iqr = q3 - q1; - auto los = q1 - (iqr * 3.); - auto lom = q1 - (iqr * 1.5); - auto him = q3 + (iqr * 1.5); - auto his = q3 + (iqr * 3.); + double mean( std::vector::const_iterator first, + std::vector::const_iterator last ); - OutlierClassification o; - for (; first != last; ++first) { - auto&& t = *first; - if (t < los) ++o.low_severe; - else if (t < lom) ++o.low_mild; - else if (t > his) ++o.high_severe; - else if (t > him) ++o.high_mild; - ++o.samples_seen; - } - return o; - } - - template - double mean(Iterator first, Iterator last) { - auto count = last - first; - double sum = std::accumulate(first, last, 0.); - return sum / static_cast(count); - } - - template - sample jackknife(Estimator&& estimator, Iterator first, Iterator last) { + template + sample jackknife(Estimator&& estimator, + std::vector::iterator first, + std::vector::iterator last) { auto n = static_cast(last - first); auto second = first; ++second; @@ -85,8 +63,12 @@ namespace Catch { double normal_quantile(double p); - template - Estimate bootstrap(double confidence_level, Iterator first, Iterator last, sample const& resample, Estimator&& estimator) { + template + Estimate bootstrap( double confidence_level, + std::vector::iterator first, + std::vector::iterator last, + sample const& resample, + Estimator&& estimator ) { auto n_samples = last - first; double point = estimator(first, last); @@ -136,7 +118,10 @@ namespace Catch { double outlier_variance; }; - bootstrap_analysis analyse_samples(double confidence_level, unsigned int n_resamples, std::vector::iterator first, std::vector::iterator last); + bootstrap_analysis analyse_samples(double confidence_level, + unsigned int n_resamples, + std::vector::iterator first, + std::vector::iterator last); } // namespace Detail } // namespace Benchmark } // namespace Catch From fe64c28925d31292516ba0a172870e7deb3baad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 10 Apr 2023 15:03:29 +0200 Subject: [PATCH 08/26] Reduce compilation costs of benchmarks We replaced some simple std::algorithm usage by loops, and reduced header inclusion. --- src/catch2/benchmark/catch_execution_plan.hpp | 18 +++++++++------- .../benchmark/catch_sample_analysis.hpp | 7 +++---- src/catch2/benchmark/detail/catch_analyse.hpp | 11 ++++++---- .../benchmark/detail/catch_estimate_clock.hpp | 20 +++++++++++------- src/catch2/benchmark/detail/catch_stats.cpp | 21 ++++++++++++------- src/catch2/benchmark/detail/catch_stats.hpp | 16 +++++++------- .../InternalBenchmark.tests.cpp | 2 ++ 7 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/catch2/benchmark/catch_execution_plan.hpp b/src/catch2/benchmark/catch_execution_plan.hpp index 039de7ee..4f60a646 100644 --- a/src/catch2/benchmark/catch_execution_plan.hpp +++ b/src/catch2/benchmark/catch_execution_plan.hpp @@ -17,8 +17,7 @@ #include #include -#include -#include +#include namespace Catch { namespace Benchmark { @@ -41,14 +40,17 @@ namespace Catch { Detail::run_for_at_least(std::chrono::duration_cast>(warmup_time), warmup_iterations, Detail::repeat(now{})); std::vector> times; - times.reserve(cfg.benchmarkSamples()); - std::generate_n(std::back_inserter(times), cfg.benchmarkSamples(), [this, env] { + const auto num_samples = cfg.benchmarkSamples(); + times.reserve( num_samples ); + for ( size_t i = 0; i < num_samples; ++i ) { Detail::ChronometerModel model; - this->benchmark(Chronometer(model, iterations_per_sample)); + this->benchmark( Chronometer( model, iterations_per_sample ) ); auto sample_time = model.elapsed() - env.clock_cost.mean; - if (sample_time < FloatDuration::zero()) sample_time = FloatDuration::zero(); - return sample_time / iterations_per_sample; - }); + if ( sample_time < FloatDuration::zero() ) { + sample_time = FloatDuration::zero(); + } + times.push_back(sample_time / iterations_per_sample); + } return times; } }; diff --git a/src/catch2/benchmark/catch_sample_analysis.hpp b/src/catch2/benchmark/catch_sample_analysis.hpp index d849d246..97b8fe50 100644 --- a/src/catch2/benchmark/catch_sample_analysis.hpp +++ b/src/catch2/benchmark/catch_sample_analysis.hpp @@ -10,14 +10,11 @@ #ifndef CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED #define CATCH_SAMPLE_ANALYSIS_HPP_INCLUDED -#include #include #include #include -#include #include -#include namespace Catch { namespace Benchmark { @@ -33,7 +30,9 @@ namespace Catch { operator SampleAnalysis() const { std::vector samples2; samples2.reserve(samples.size()); - std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); }); + for (auto const& d : samples) { + samples2.push_back(Duration2(d)); + } return { CATCH_MOVE(samples2), mean, diff --git a/src/catch2/benchmark/detail/catch_analyse.hpp b/src/catch2/benchmark/detail/catch_analyse.hpp index 1751543c..c932ff26 100644 --- a/src/catch2/benchmark/detail/catch_analyse.hpp +++ b/src/catch2/benchmark/detail/catch_analyse.hpp @@ -16,8 +16,6 @@ #include #include -#include -#include #include namespace Catch { @@ -28,7 +26,9 @@ namespace Catch { if (!cfg.benchmarkNoAnalysis()) { std::vector samples; samples.reserve(static_cast(last - first)); - std::transform(first, last, std::back_inserter(samples), [](Duration d) { return d.count(); }); + for (auto current = first; current != last; ++current) { + samples.push_back( current->count() ); + } auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end()); auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end()); @@ -43,7 +43,10 @@ namespace Catch { }; std::vector samples2; samples2.reserve(samples.size()); - std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](double d) { return Duration(d); }); + for (auto s : samples) { + samples2.push_back( Duration( s ) ); + } + return { CATCH_MOVE(samples2), wrap_estimate(analysis.mean), diff --git a/src/catch2/benchmark/detail/catch_estimate_clock.hpp b/src/catch2/benchmark/detail/catch_estimate_clock.hpp index fb65450e..1e916ae4 100644 --- a/src/catch2/benchmark/detail/catch_estimate_clock.hpp +++ b/src/catch2/benchmark/detail/catch_estimate_clock.hpp @@ -19,7 +19,6 @@ #include #include -#include #include #include @@ -30,13 +29,16 @@ namespace Catch { std::vector resolution(int k) { std::vector> times; times.reserve(static_cast(k + 1)); - std::generate_n(std::back_inserter(times), k + 1, now{}); + for ( int i = 0; i < k + 1; ++i ) { + times.push_back( Clock::now() ); + } std::vector deltas; deltas.reserve(static_cast(k)); - std::transform(std::next(times.begin()), times.end(), times.begin(), - std::back_inserter(deltas), - [](TimePoint a, TimePoint b) { return static_cast((a - b).count()); }); + for ( size_t idx = 1; idx < times.size(); ++idx ) { + deltas.push_back( static_cast( + ( times[idx] - times[idx - 1] ).count() ) ); + } return deltas; } @@ -84,9 +86,11 @@ namespace Catch { std::vector times; int nsamples = static_cast(std::ceil(time_limit / r.elapsed)); times.reserve(static_cast(nsamples)); - std::generate_n(std::back_inserter(times), nsamples, [time_clock, &r] { - return static_cast((time_clock(r.iterations) / r.iterations).count()); - }); + for ( int s = 0; s < nsamples; ++s ) { + times.push_back( static_cast( + ( time_clock( r.iterations ) / r.iterations ) + .count() ) ); + } return { FloatDuration(mean(times.begin(), times.end())), classify_outliers(times.begin(), times.end()), diff --git a/src/catch2/benchmark/detail/catch_stats.cpp b/src/catch2/benchmark/detail/catch_stats.cpp index c6c87be3..a7863224 100644 --- a/src/catch2/benchmark/detail/catch_stats.cpp +++ b/src/catch2/benchmark/detail/catch_stats.cpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include @@ -35,12 +35,19 @@ using Catch::Benchmark::Detail::sample; sample out; out.reserve(resamples); - std::generate_n(std::back_inserter(out), resamples, [n, first, &estimator, &dist, &rng] { - std::vector resampled; - resampled.reserve(n); - std::generate_n(std::back_inserter(resampled), n, [first, &dist, &rng] { return first[static_cast(dist(rng))]; }); - return estimator(resampled.begin(), resampled.end()); - }); + // We allocate the vector outside the loop to avoid realloc per resample + std::vector resampled; + resampled.reserve( n ); + for ( size_t i = 0; i < resamples; ++i ) { + resampled.clear(); + for ( size_t s = 0; s < n; ++s ) { + resampled.push_back( + first[static_cast( dist( rng ) )] ); + } + const auto estimate = + estimator( resampled.begin(), resampled.end() ); + out.push_back( estimate ); + } std::sort(out.begin(), out.end()); return out; } diff --git a/src/catch2/benchmark/detail/catch_stats.hpp b/src/catch2/benchmark/detail/catch_stats.hpp index b71c5842..62ca80f2 100644 --- a/src/catch2/benchmark/detail/catch_stats.hpp +++ b/src/catch2/benchmark/detail/catch_stats.hpp @@ -15,8 +15,6 @@ #include #include -#include -#include #include namespace Catch { @@ -77,13 +75,13 @@ namespace Catch { sample jack = jackknife(estimator, first, last); double jack_mean = mean(jack.begin(), jack.end()); - double sum_squares, sum_cubes; - std::tie(sum_squares, sum_cubes) = std::accumulate(jack.begin(), jack.end(), std::make_pair(0., 0.), [jack_mean](std::pair sqcb, double x) -> std::pair { - auto d = jack_mean - x; - auto d2 = d * d; - auto d3 = d2 * d; - return { sqcb.first + d2, sqcb.second + d3 }; - }); + double sum_squares = 0, sum_cubes = 0; + for (double x : jack) { + auto difference = jack_mean - x; + auto square = difference * difference; + auto cube = square * difference; + sum_squares += square; sum_cubes += cube; + } double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5)); long n = static_cast(resample.size()); diff --git a/tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp b/tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp index 96c0977b..fa9f8e2e 100644 --- a/tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp @@ -22,6 +22,8 @@ #include #include +#include + namespace { struct manual_clock { public: From 10f0a5864319c0baa5c4cecb5e6138fd0c78a3e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 29 Apr 2023 14:29:59 +0200 Subject: [PATCH 09/26] Some template instantiation reductions --- src/catch2/catch_test_spec.cpp | 18 ++++++++++-------- .../internal/catch_reporter_spec_parser.cpp | 6 +++--- src/catch2/internal/catch_string_manip.cpp | 7 +++---- .../reporters/catch_reporter_compact.cpp | 2 +- src/catch2/reporters/catch_reporter_tap.cpp | 3 +-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/catch2/catch_test_spec.cpp b/src/catch2/catch_test_spec.cpp index 2a7fd563..99d83792 100644 --- a/src/catch2/catch_test_spec.cpp +++ b/src/catch2/catch_test_spec.cpp @@ -107,16 +107,18 @@ namespace Catch { return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } ); } - TestSpec::Matches TestSpec::matchesByFilter( std::vector const& testCases, IConfig const& config ) const - { - Matches matches( m_filters.size() ); - std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){ + TestSpec::Matches TestSpec::matchesByFilter( std::vector const& testCases, IConfig const& config ) const { + Matches matches; + matches.reserve( m_filters.size() ); + for ( auto const& filter : m_filters ) { std::vector currentMatches; - for( auto const& test : testCases ) - if( isThrowSafe( test, config ) && filter.matches( test.getTestCaseInfo() ) ) + for ( auto const& test : testCases ) + if ( isThrowSafe( test, config ) && + filter.matches( test.getTestCaseInfo() ) ) currentMatches.emplace_back( &test ); - return FilterMatch{ extractFilterName(filter), currentMatches }; - } ); + matches.push_back( + FilterMatch{ extractFilterName( filter ), currentMatches } ); + } return matches; } diff --git a/src/catch2/internal/catch_reporter_spec_parser.cpp b/src/catch2/internal/catch_reporter_spec_parser.cpp index f6591d9a..8b88b170 100644 --- a/src/catch2/internal/catch_reporter_spec_parser.cpp +++ b/src/catch2/internal/catch_reporter_spec_parser.cpp @@ -21,9 +21,9 @@ namespace Catch { }; kvPair splitKVPair(StringRef kvString) { - auto splitPos = static_cast( std::distance( - kvString.begin(), - std::find( kvString.begin(), kvString.end(), '=' ) ) ); + auto splitPos = static_cast( + std::find( kvString.begin(), kvString.end(), '=' ) - + kvString.begin() ); return { kvString.substr( 0, splitPos ), kvString.substr( splitPos + 1, kvString.size() ) }; diff --git a/src/catch2/internal/catch_string_manip.cpp b/src/catch2/internal/catch_string_manip.cpp index cb96dd4f..0c889ca1 100644 --- a/src/catch2/internal/catch_string_manip.cpp +++ b/src/catch2/internal/catch_string_manip.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -32,9 +31,9 @@ namespace Catch { return s.find( infix ) != std::string::npos; } void toLowerInPlace( std::string& s ) { - std::transform( s.begin(), s.end(), s.begin(), []( char c ) { - return toLower( c ); - } ); + for ( char& c : s ) { + c = toLower( c ); + } } std::string toLower( std::string const& s ) { std::string lc = s; diff --git a/src/catch2/reporters/catch_reporter_compact.cpp b/src/catch2/reporters/catch_reporter_compact.cpp index 3a9b870c..88acb6a4 100644 --- a/src/catch2/reporters/catch_reporter_compact.cpp +++ b/src/catch2/reporters/catch_reporter_compact.cpp @@ -171,7 +171,7 @@ private: return; const auto itEnd = messages.cend(); - const auto N = static_cast(std::distance(itMessage, itEnd)); + const auto N = static_cast(itEnd - itMessage); stream << colourImpl->guardColour( colour ) << " with " << pluralise( N, "message"_sr ) << ':'; diff --git a/src/catch2/reporters/catch_reporter_tap.cpp b/src/catch2/reporters/catch_reporter_tap.cpp index 563d6fb1..67d406fb 100644 --- a/src/catch2/reporters/catch_reporter_tap.cpp +++ b/src/catch2/reporters/catch_reporter_tap.cpp @@ -14,7 +14,6 @@ #include #include -#include #include namespace Catch { @@ -165,7 +164,7 @@ namespace Catch { // using messages.end() directly (or auto) yields compilation error: std::vector::const_iterator itEnd = messages.end(); - const std::size_t N = static_cast(std::distance(itMessage, itEnd)); + const std::size_t N = static_cast(itEnd - itMessage); stream << colourImpl->guardColour( colour ) << " with " << pluralise( N, "message"_sr ) << ':'; From 51fdbedd1337955bedc02b570bb2a7fb19061f2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Mon, 1 May 2023 00:51:43 +0200 Subject: [PATCH 10/26] Internal linkage for outlier_variance --- src/catch2/benchmark/detail/catch_stats.cpp | 298 +++++++++++--------- src/catch2/benchmark/detail/catch_stats.hpp | 2 - 2 files changed, 157 insertions(+), 143 deletions(-) diff --git a/src/catch2/benchmark/detail/catch_stats.cpp b/src/catch2/benchmark/detail/catch_stats.cpp index a7863224..ea483a30 100644 --- a/src/catch2/benchmark/detail/catch_stats.cpp +++ b/src/catch2/benchmark/detail/catch_stats.cpp @@ -21,128 +21,172 @@ #include #endif -namespace { +namespace Catch { + namespace Benchmark { + namespace Detail { + namespace { -using Catch::Benchmark::Detail::sample; + template + static sample + resample( URng& rng, + unsigned int resamples, + std::vector::const_iterator first, + std::vector::const_iterator last, + Estimator& estimator ) { + auto n = static_cast( last - first ); + std::uniform_int_distribution dist( 0, + n - 1 ); - template - static sample resample(URng& rng, unsigned int resamples, - std::vector::const_iterator first, - std::vector::const_iterator last, - Estimator& estimator) { - auto n = static_cast(last - first); - std::uniform_int_distribution dist(0, n - 1); + sample out; + out.reserve( resamples ); + // We allocate the vector outside the loop to avoid realloc + // per resample + std::vector resampled; + resampled.reserve( n ); + for ( size_t i = 0; i < resamples; ++i ) { + resampled.clear(); + for ( size_t s = 0; s < n; ++s ) { + resampled.push_back( + first[static_cast( + dist( rng ) )] ); + } + const auto estimate = + estimator( resampled.begin(), resampled.end() ); + out.push_back( estimate ); + } + std::sort( out.begin(), out.end() ); + return out; + } - sample out; - out.reserve(resamples); - // We allocate the vector outside the loop to avoid realloc per resample - std::vector resampled; - resampled.reserve( n ); - for ( size_t i = 0; i < resamples; ++i ) { - resampled.clear(); - for ( size_t s = 0; s < n; ++s ) { - resampled.push_back( - first[static_cast( dist( rng ) )] ); - } - const auto estimate = - estimator( resampled.begin(), resampled.end() ); - out.push_back( estimate ); - } - std::sort(out.begin(), out.end()); - return out; - } + static double outlier_variance( Estimate mean, + Estimate stddev, + int n ) { + double sb = stddev.point; + double mn = mean.point / n; + double mg_min = mn / 2.; + double sg = (std::min)( mg_min / 4., sb / std::sqrt( n ) ); + double sg2 = sg * sg; + double sb2 = sb * sb; + auto c_max = [n, mn, sb2, sg2]( double x ) -> double { + double k = mn - x; + double d = k * k; + double nd = n * d; + double k0 = -n * nd; + double k1 = sb2 - n * sg2 + nd; + double det = k1 * k1 - 4 * sg2 * k0; + return static_cast( -2. * k0 / + ( k1 + std::sqrt( det ) ) ); + }; - double erf_inv(double x) { - // Code accompanying the article "Approximating the erfinv function" in GPU Computing Gems, Volume 2 - double w, p; + auto var_out = [n, sb2, sg2]( double c ) { + double nc = n - c; + return ( nc / n ) * ( sb2 - nc * sg2 ); + }; - w = -log((1.0 - x) * (1.0 + x)); + return (std::min)( var_out( 1 ), + var_out( + (std::min)( c_max( 0. ), + c_max( mg_min ) ) ) ) / + sb2; + } - if (w < 6.250000) { - w = w - 3.125000; - p = -3.6444120640178196996e-21; - p = -1.685059138182016589e-19 + p * w; - p = 1.2858480715256400167e-18 + p * w; - p = 1.115787767802518096e-17 + p * w; - p = -1.333171662854620906e-16 + p * w; - p = 2.0972767875968561637e-17 + p * w; - p = 6.6376381343583238325e-15 + p * w; - p = -4.0545662729752068639e-14 + p * w; - p = -8.1519341976054721522e-14 + p * w; - p = 2.6335093153082322977e-12 + p * w; - p = -1.2975133253453532498e-11 + p * w; - p = -5.4154120542946279317e-11 + p * w; - p = 1.051212273321532285e-09 + p * w; - p = -4.1126339803469836976e-09 + p * w; - p = -2.9070369957882005086e-08 + p * w; - p = 4.2347877827932403518e-07 + p * w; - p = -1.3654692000834678645e-06 + p * w; - p = -1.3882523362786468719e-05 + p * w; - p = 0.0001867342080340571352 + p * w; - p = -0.00074070253416626697512 + p * w; - p = -0.0060336708714301490533 + p * w; - p = 0.24015818242558961693 + p * w; - p = 1.6536545626831027356 + p * w; - } else if (w < 16.000000) { - w = sqrt(w) - 3.250000; - p = 2.2137376921775787049e-09; - p = 9.0756561938885390979e-08 + p * w; - p = -2.7517406297064545428e-07 + p * w; - p = 1.8239629214389227755e-08 + p * w; - p = 1.5027403968909827627e-06 + p * w; - p = -4.013867526981545969e-06 + p * w; - p = 2.9234449089955446044e-06 + p * w; - p = 1.2475304481671778723e-05 + p * w; - p = -4.7318229009055733981e-05 + p * w; - p = 6.8284851459573175448e-05 + p * w; - p = 2.4031110387097893999e-05 + p * w; - p = -0.0003550375203628474796 + p * w; - p = 0.00095328937973738049703 + p * w; - p = -0.0016882755560235047313 + p * w; - p = 0.0024914420961078508066 + p * w; - p = -0.0037512085075692412107 + p * w; - p = 0.005370914553590063617 + p * w; - p = 1.0052589676941592334 + p * w; - p = 3.0838856104922207635 + p * w; - } else { - w = sqrt(w) - 5.000000; - p = -2.7109920616438573243e-11; - p = -2.5556418169965252055e-10 + p * w; - p = 1.5076572693500548083e-09 + p * w; - p = -3.7894654401267369937e-09 + p * w; - p = 7.6157012080783393804e-09 + p * w; - p = -1.4960026627149240478e-08 + p * w; - p = 2.9147953450901080826e-08 + p * w; - p = -6.7711997758452339498e-08 + p * w; - p = 2.2900482228026654717e-07 + p * w; - p = -9.9298272942317002539e-07 + p * w; - p = 4.5260625972231537039e-06 + p * w; - p = -1.9681778105531670567e-05 + p * w; - p = 7.5995277030017761139e-05 + p * w; - p = -0.00021503011930044477347 + p * w; - p = -0.00013871931833623122026 + p * w; - p = 1.0103004648645343977 + p * w; - p = 4.8499064014085844221 + p * w; - } - return p * x; - } + static double erf_inv( double x ) { + // Code accompanying the article "Approximating the erfinv + // function" in GPU Computing Gems, Volume 2 + double w, p; - double standard_deviation(std::vector::const_iterator first, - std::vector::const_iterator last) { - auto m = Catch::Benchmark::Detail::mean(first, last); - double variance = std::accumulate( first, - last, - 0., - [m]( double a, double b ) { - double diff = b - m; - return a + diff * diff; - } ) / - ( last - first ); - return std::sqrt( variance ); - } + w = -log( ( 1.0 - x ) * ( 1.0 + x ) ); -} + if ( w < 6.250000 ) { + w = w - 3.125000; + p = -3.6444120640178196996e-21; + p = -1.685059138182016589e-19 + p * w; + p = 1.2858480715256400167e-18 + p * w; + p = 1.115787767802518096e-17 + p * w; + p = -1.333171662854620906e-16 + p * w; + p = 2.0972767875968561637e-17 + p * w; + p = 6.6376381343583238325e-15 + p * w; + p = -4.0545662729752068639e-14 + p * w; + p = -8.1519341976054721522e-14 + p * w; + p = 2.6335093153082322977e-12 + p * w; + p = -1.2975133253453532498e-11 + p * w; + p = -5.4154120542946279317e-11 + p * w; + p = 1.051212273321532285e-09 + p * w; + p = -4.1126339803469836976e-09 + p * w; + p = -2.9070369957882005086e-08 + p * w; + p = 4.2347877827932403518e-07 + p * w; + p = -1.3654692000834678645e-06 + p * w; + p = -1.3882523362786468719e-05 + p * w; + p = 0.0001867342080340571352 + p * w; + p = -0.00074070253416626697512 + p * w; + p = -0.0060336708714301490533 + p * w; + p = 0.24015818242558961693 + p * w; + p = 1.6536545626831027356 + p * w; + } else if ( w < 16.000000 ) { + w = sqrt( w ) - 3.250000; + p = 2.2137376921775787049e-09; + p = 9.0756561938885390979e-08 + p * w; + p = -2.7517406297064545428e-07 + p * w; + p = 1.8239629214389227755e-08 + p * w; + p = 1.5027403968909827627e-06 + p * w; + p = -4.013867526981545969e-06 + p * w; + p = 2.9234449089955446044e-06 + p * w; + p = 1.2475304481671778723e-05 + p * w; + p = -4.7318229009055733981e-05 + p * w; + p = 6.8284851459573175448e-05 + p * w; + p = 2.4031110387097893999e-05 + p * w; + p = -0.0003550375203628474796 + p * w; + p = 0.00095328937973738049703 + p * w; + p = -0.0016882755560235047313 + p * w; + p = 0.0024914420961078508066 + p * w; + p = -0.0037512085075692412107 + p * w; + p = 0.005370914553590063617 + p * w; + p = 1.0052589676941592334 + p * w; + p = 3.0838856104922207635 + p * w; + } else { + w = sqrt( w ) - 5.000000; + p = -2.7109920616438573243e-11; + p = -2.5556418169965252055e-10 + p * w; + p = 1.5076572693500548083e-09 + p * w; + p = -3.7894654401267369937e-09 + p * w; + p = 7.6157012080783393804e-09 + p * w; + p = -1.4960026627149240478e-08 + p * w; + p = 2.9147953450901080826e-08 + p * w; + p = -6.7711997758452339498e-08 + p * w; + p = 2.2900482228026654717e-07 + p * w; + p = -9.9298272942317002539e-07 + p * w; + p = 4.5260625972231537039e-06 + p * w; + p = -1.9681778105531670567e-05 + p * w; + p = 7.5995277030017761139e-05 + p * w; + p = -0.00021503011930044477347 + p * w; + p = -0.00013871931833623122026 + p * w; + p = 1.0103004648645343977 + p * w; + p = 4.8499064014085844221 + p * w; + } + return p * x; + } + + static double + standard_deviation( std::vector::const_iterator first, + std::vector::const_iterator last ) { + auto m = Catch::Benchmark::Detail::mean( first, last ); + double variance = + std::accumulate( first, + last, + 0., + [m]( double a, double b ) { + double diff = b - m; + return a + diff * diff; + } ) / + ( last - first ); + return std::sqrt( variance ); + } + + } // namespace + } // namespace Detail + } // namespace Benchmark +} // namespace Catch namespace Catch { namespace Benchmark { @@ -234,34 +278,6 @@ namespace Catch { return result; } - - double outlier_variance(Estimate mean, Estimate stddev, int n) { - double sb = stddev.point; - double mn = mean.point / n; - double mg_min = mn / 2.; - double sg = (std::min)(mg_min / 4., sb / std::sqrt(n)); - double sg2 = sg * sg; - double sb2 = sb * sb; - - auto c_max = [n, mn, sb2, sg2](double x) -> double { - double k = mn - x; - double d = k * k; - double nd = n * d; - double k0 = -n * nd; - double k1 = sb2 - n * sg2 + nd; - double det = k1 * k1 - 4 * sg2 * k0; - return static_cast(-2. * k0 / (k1 + std::sqrt(det))); - }; - - auto var_out = [n, sb2, sg2](double c) { - double nc = n - c; - return (nc / n) * (sb2 - nc * sg2); - }; - - return (std::min)(var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / sb2; - } - - bootstrap_analysis analyse_samples(double confidence_level, unsigned int n_resamples, std::vector::iterator first, diff --git a/src/catch2/benchmark/detail/catch_stats.hpp b/src/catch2/benchmark/detail/catch_stats.hpp index 62ca80f2..c1ce5664 100644 --- a/src/catch2/benchmark/detail/catch_stats.hpp +++ b/src/catch2/benchmark/detail/catch_stats.hpp @@ -108,8 +108,6 @@ namespace Catch { return { point, resample[lo], resample[hi], confidence_level }; } - double outlier_variance(Estimate mean, Estimate stddev, int n); - struct bootstrap_analysis { Estimate mean; Estimate standard_deviation; From d84777c9cbf5b1b7d0e9ef2e14606ece254adf7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 6 May 2023 11:48:25 +0200 Subject: [PATCH 11/26] Fix assertionStarting events being sent after the expr is evaluated Closes #2678 --- docs/reporter-events.md | 12 +-- .../interfaces/catch_interfaces_capture.hpp | 1 + .../internal/catch_assertion_handler.cpp | 4 +- src/catch2/internal/catch_run_context.cpp | 12 +-- src/catch2/internal/catch_run_context.hpp | 1 + tests/ExtraTests/CMakeLists.txt | 11 +++ ...ingEventGoesBeforeAssertionIsEvaluated.cpp | 81 +++++++++++++++++++ 7 files changed, 110 insertions(+), 12 deletions(-) create mode 100644 tests/ExtraTests/X20-AssertionStartingEventGoesBeforeAssertionIsEvaluated.cpp diff --git a/docs/reporter-events.md b/docs/reporter-events.md index 32a0ae50..015f67be 100644 --- a/docs/reporter-events.md +++ b/docs/reporter-events.md @@ -96,12 +96,12 @@ void assertionStarting( AssertionInfo const& assertionInfo ); void assertionEnded( AssertionStats const& assertionStats ); ``` -`assertionStarting` is called after the expression is captured, but before -the assertion expression is evaluated. This might seem like a minor -distinction, but what it means is that if you have assertion like -`REQUIRE( a + b == c + d )`, then what happens is that `a + b` and `c + d` -are evaluated before `assertionStarting` is emitted, while the `==` is -evaluated after the event. +The `assertionStarting` event is emitted before the expression in the +assertion is captured or evaluated and `assertionEnded` is emitted +afterwards. This means that given assertion like `REQUIRE(a + b == c + d)`, +Catch2 first emits `assertionStarting` event, then `a + b` and `c + d` +are evaluated, then their results are captured, the comparison is evaluated, +and then `assertionEnded` event is emitted. ## Benchmarking events diff --git a/src/catch2/interfaces/catch_interfaces_capture.hpp b/src/catch2/interfaces/catch_interfaces_capture.hpp index e605f998..a1876a4c 100644 --- a/src/catch2/interfaces/catch_interfaces_capture.hpp +++ b/src/catch2/interfaces/catch_interfaces_capture.hpp @@ -43,6 +43,7 @@ namespace Catch { public: virtual ~IResultCapture(); + virtual void notifyAssertionStarted( AssertionInfo const& info ) = 0; virtual bool sectionStarted( StringRef sectionName, SourceLineInfo const& sectionLineInfo, Counts& assertions ) = 0; diff --git a/src/catch2/internal/catch_assertion_handler.cpp b/src/catch2/internal/catch_assertion_handler.cpp index b66a1456..e5232f70 100644 --- a/src/catch2/internal/catch_assertion_handler.cpp +++ b/src/catch2/internal/catch_assertion_handler.cpp @@ -23,7 +23,9 @@ namespace Catch { ResultDisposition::Flags resultDisposition ) : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition }, m_resultCapture( getResultCapture() ) - {} + { + m_resultCapture.notifyAssertionStarted( m_assertionInfo ); + } void AssertionHandler::handleExpr( ITransientExpression const& expr ) { m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction ); diff --git a/src/catch2/internal/catch_run_context.cpp b/src/catch2/internal/catch_run_context.cpp index 6fd63450..c6171a5c 100644 --- a/src/catch2/internal/catch_run_context.cpp +++ b/src/catch2/internal/catch_run_context.cpp @@ -301,7 +301,13 @@ namespace Catch { m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr; } - bool RunContext::sectionStarted(StringRef sectionName, SourceLineInfo const& sectionLineInfo, Counts & assertions) { + void RunContext::notifyAssertionStarted( AssertionInfo const& info ) { + m_reporter->assertionStarting( info ); + } + + bool RunContext::sectionStarted( StringRef sectionName, + SourceLineInfo const& sectionLineInfo, + Counts& assertions ) { ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocationRef( @@ -561,8 +567,6 @@ namespace Catch { ITransientExpression const& expr, AssertionReaction& reaction ) { - m_reporter->assertionStarting( info ); - bool negated = isFalseTest( info.resultDisposition ); bool result = expr.getResult() != negated; @@ -600,8 +604,6 @@ namespace Catch { StringRef message, AssertionReaction& reaction ) { - m_reporter->assertionStarting( info ); - m_lastAssertionInfo = info; AssertionResultData data( resultType, LazyExpression( false ) ); diff --git a/src/catch2/internal/catch_run_context.hpp b/src/catch2/internal/catch_run_context.hpp index fc65f651..76cdd84d 100644 --- a/src/catch2/internal/catch_run_context.hpp +++ b/src/catch2/internal/catch_run_context.hpp @@ -70,6 +70,7 @@ namespace Catch { ResultWas::OfType resultType, AssertionReaction &reaction ) override; + void notifyAssertionStarted( AssertionInfo const& info ) override; bool sectionStarted( StringRef sectionName, SourceLineInfo const& sectionLineInfo, Counts& assertions ) override; diff --git a/tests/ExtraTests/CMakeLists.txt b/tests/ExtraTests/CMakeLists.txt index 4172d7a0..2a810e25 100644 --- a/tests/ExtraTests/CMakeLists.txt +++ b/tests/ExtraTests/CMakeLists.txt @@ -468,6 +468,17 @@ set_tests_properties( ) +add_executable(AssertionStartingEventGoesBeforeAssertionIsEvaluated + X20-AssertionStartingEventGoesBeforeAssertionIsEvaluated.cpp +) +target_link_libraries(AssertionStartingEventGoesBeforeAssertionIsEvaluated + PRIVATE Catch2::Catch2WithMain +) +add_test( + NAME ReporterEvents::AssertionStartingHappensBeforeAssertionIsEvaluated + COMMAND $ +) + #add_executable(DebugBreakMacros ${TESTS_DIR}/X12-CustomDebugBreakMacro.cpp) #target_link_libraries(DebugBreakMacros Catch2) #add_test(NAME DebugBreakMacros COMMAND DebugBreakMacros --break) diff --git a/tests/ExtraTests/X20-AssertionStartingEventGoesBeforeAssertionIsEvaluated.cpp b/tests/ExtraTests/X20-AssertionStartingEventGoesBeforeAssertionIsEvaluated.cpp new file mode 100644 index 00000000..ef5b46b9 --- /dev/null +++ b/tests/ExtraTests/X20-AssertionStartingEventGoesBeforeAssertionIsEvaluated.cpp @@ -0,0 +1,81 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 + +/**\file + * TODO: FIXES Registers custom reporter that reports testCase* events + * + * The resulting executable can then be used by an external Python script + * to verify that testCase{Starting,Ended} and testCasePartial{Starting,Ended} + * events are properly nested. + */ + +#include +#include +#include +#include + +namespace { + + static size_t assertion_starting_events_seen = 0; + + // TODO: custom matcher to check that "assertion_starting_events_seen" has + // the right number of checks + + class AssertionStartingListener : public Catch::EventListenerBase { + public: + AssertionStartingListener( Catch::IConfig const* config ): + EventListenerBase( config ) {} + + void assertionStarting( Catch::AssertionInfo const& ) override { + ++assertion_starting_events_seen; + } + }; + + static bool f1() { + return assertion_starting_events_seen == 1; + } + + static void f2() { + if ( assertion_starting_events_seen != 2 ) { throw 1; } + } + + static void f3() { + if ( assertion_starting_events_seen == 3 ) { throw 1; } + } + + static bool f4() { return assertion_starting_events_seen == 4; } + + static void f5() { throw assertion_starting_events_seen; } + +} // anonymous namespace + +CATCH_REGISTER_LISTENER( AssertionStartingListener ) + +TEST_CASE() { + // **IMPORTANT** + // The order of assertions below matters. + REQUIRE( f1() ); + REQUIRE_NOTHROW( f2() ); + REQUIRE_THROWS( f3() ); + REQUIRE_THAT( f4(), + Catch::Matchers::Predicate( []( bool b ) { return b; } ) ); + REQUIRE_THROWS_MATCHES( + f5(), size_t, Catch::Matchers::Predicate( []( size_t i ) { + return i == 5; + } ) ); + + CAPTURE( assertion_starting_events_seen ); // **not** an assertion + INFO( "some info msg" ); // **not** an assertion + WARN( "warning! warning!" ); // assertion-like message + SUCCEED(); // assertion-like message + + // We skip FAIL/SKIP and so on, which fail the test. + + // This require will also increment the count once + REQUIRE( assertion_starting_events_seen == 8 ); +} From c57b5cdf432b1983c6f1b1fd9fb1f7ff11397391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 6 May 2023 14:31:29 +0200 Subject: [PATCH 12/26] Move-enable Catch::optional This avoids copies in couple places through Catch2, e.g. reporter spec handling, and moving around `AssertionResult` in `RunContext`. --- src/catch2/internal/catch_optional.hpp | 53 ++++++++++++------- .../IntrospectiveTests/Details.tests.cpp | 41 ++++++++++++++ 2 files changed, 76 insertions(+), 18 deletions(-) diff --git a/src/catch2/internal/catch_optional.hpp b/src/catch2/internal/catch_optional.hpp index ac3714ee..d1e953ad 100644 --- a/src/catch2/internal/catch_optional.hpp +++ b/src/catch2/internal/catch_optional.hpp @@ -8,6 +8,8 @@ #ifndef CATCH_OPTIONAL_HPP_INCLUDED #define CATCH_OPTIONAL_HPP_INCLUDED +#include + #include namespace Catch { @@ -16,35 +18,50 @@ namespace Catch { template class Optional { public: - Optional() : nullableValue( nullptr ) {} - Optional( T const& _value ) - : nullableValue( new( storage ) T( _value ) ) - {} - Optional( Optional const& _other ) - : nullableValue( _other ? new( storage ) T( *_other ) : nullptr ) - {} + Optional(): nullableValue( nullptr ) {} + ~Optional() { reset(); } - ~Optional() { + Optional( T const& _value ): + nullableValue( new ( storage ) T( _value ) ) {} + Optional( T&& _value ): + nullableValue( new ( storage ) T( CATCH_MOVE( _value ) ) ) {} + + Optional& operator=( T const& _value ) { reset(); + nullableValue = new ( storage ) T( _value ); + return *this; + } + Optional& operator=( T&& _value ) { + reset(); + nullableValue = new ( storage ) T( CATCH_MOVE( _value ) ); + return *this; } - Optional& operator= ( Optional const& _other ) { - if( &_other != this ) { + Optional( Optional const& _other ): + nullableValue( _other ? new ( storage ) T( *_other ) : nullptr ) {} + Optional( Optional&& _other ): + nullableValue( _other ? new ( storage ) T( CATCH_MOVE( *_other ) ) + : nullptr ) {} + + Optional& operator=( Optional const& _other ) { + if ( &_other != this ) { reset(); - if( _other ) - nullableValue = new( storage ) T( *_other ); + if ( _other ) { nullableValue = new ( storage ) T( *_other ); } } return *this; } - Optional& operator = ( T const& _value ) { - reset(); - nullableValue = new( storage ) T( _value ); + Optional& operator=( Optional&& _other ) { + if ( &_other != this ) { + reset(); + if ( _other ) { + nullableValue = new ( storage ) T( CATCH_MOVE( *_other ) ); + } + } return *this; } void reset() { - if( nullableValue ) - nullableValue->~T(); + if ( nullableValue ) { nullableValue->~T(); } nullableValue = nullptr; } @@ -91,7 +108,7 @@ namespace Catch { } private: - T *nullableValue; + T* nullableValue; alignas(alignof(T)) char storage[sizeof(T)]; }; diff --git a/tests/SelfTest/IntrospectiveTests/Details.tests.cpp b/tests/SelfTest/IntrospectiveTests/Details.tests.cpp index a5a43926..80eb647b 100644 --- a/tests/SelfTest/IntrospectiveTests/Details.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/Details.tests.cpp @@ -89,6 +89,47 @@ TEST_CASE("Optional comparison ops", "[optional][approvals]") { } } +namespace { + struct MoveChecker { + bool has_moved = false; + MoveChecker() = default; + MoveChecker( MoveChecker const& rhs ) = default; + MoveChecker& operator=( MoveChecker const& rhs ) = default; + MoveChecker( MoveChecker&& rhs ) { rhs.has_moved = true; } + MoveChecker& operator=( MoveChecker&& rhs ) { + rhs.has_moved = true; + return *this; + } + }; +} + +TEST_CASE( "Optional supports move ops", "[optional][approvals]" ) { + using Catch::Optional; + MoveChecker a; + Optional opt_A( a ); + REQUIRE_FALSE( a.has_moved ); + REQUIRE_FALSE( opt_A->has_moved ); + + SECTION( "Move construction from element" ) { + Optional opt_B( CATCH_MOVE( a ) ); + REQUIRE( a.has_moved ); + } + SECTION( "Move assignment from element" ) { + opt_A = CATCH_MOVE( a ); + REQUIRE( a.has_moved ); + } + SECTION( "Move construction from optional" ) { + Optional opt_B( CATCH_MOVE( opt_A ) ); + REQUIRE( opt_A->has_moved ); + } + SECTION( "Move assignment from optional" ) { + Optional opt_B( opt_A ); + REQUIRE_FALSE( opt_A->has_moved ); + opt_B = CATCH_MOVE( opt_A ); + REQUIRE( opt_A->has_moved ); + } +} + TEST_CASE( "Decomposer checks that the argument is 0 when handling " "only-0-comparable types", "[decomposition][approvals]" ) { From 8ca504cbc956d566ea77a8d59928146ad4cc3844 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 6 May 2023 21:45:39 +0200 Subject: [PATCH 13/26] Move AssertionResult when passing it inside RunContext --- src/catch2/internal/catch_run_context.cpp | 27 +++++++++++++---------- src/catch2/internal/catch_run_context.hpp | 2 +- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/catch2/internal/catch_run_context.cpp b/src/catch2/internal/catch_run_context.cpp index c6171a5c..6f15cfb1 100644 --- a/src/catch2/internal/catch_run_context.cpp +++ b/src/catch2/internal/catch_run_context.cpp @@ -267,7 +267,7 @@ namespace Catch { } - void RunContext::assertionEnded(AssertionResult const & result) { + void RunContext::assertionEnded(AssertionResult&& result) { if (result.getResultType() == ResultWas::Ok) { m_totals.assertions.passed++; m_lastAssertionPassed = true; @@ -289,12 +289,13 @@ namespace Catch { m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)); - if (result.getResultType() != ResultWas::Warning) + if ( result.getResultType() != ResultWas::Warning ) { m_messageScopes.clear(); + } // Reset working state resetAssertionInfo(); - m_lastResult = result; + m_lastResult = CATCH_MOVE( result ); } void RunContext::resetAssertionInfo() { m_lastAssertionInfo.macroName = StringRef(); @@ -445,7 +446,7 @@ namespace Catch { tempResult.message = static_cast(message); AssertionResult result(m_lastAssertionInfo, CATCH_MOVE(tempResult)); - assertionEnded(result); + assertionEnded(CATCH_MOVE(result) ); handleUnfinishedSections(); @@ -595,7 +596,7 @@ namespace Catch { AssertionResult assertionResult{ info, CATCH_MOVE( data ) }; assertionResult.m_resultData.lazyExpression.m_transientExpression = expr; - assertionEnded( assertionResult ); + assertionEnded( CATCH_MOVE(assertionResult) ); } void RunContext::handleMessage( @@ -610,8 +611,10 @@ namespace Catch { data.message = static_cast(message); AssertionResult assertionResult{ m_lastAssertionInfo, CATCH_MOVE( data ) }; - assertionEnded( assertionResult ); - if ( !assertionResult.isOk() ) { + + const auto isOk = assertionResult.isOk(); + assertionEnded( CATCH_MOVE(assertionResult) ); + if ( !isOk ) { populateReaction( reaction ); } else if ( resultType == ResultWas::ExplicitSkip ) { // TODO: Need to handle this explicitly, as ExplicitSkip is @@ -636,7 +639,7 @@ namespace Catch { AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); data.message = CATCH_MOVE(message); AssertionResult assertionResult{ info, CATCH_MOVE(data) }; - assertionEnded( assertionResult ); + assertionEnded( CATCH_MOVE(assertionResult) ); populateReaction( reaction ); } @@ -654,7 +657,7 @@ namespace Catch { AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) ); data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"s; AssertionResult assertionResult{ info, CATCH_MOVE( data ) }; - assertionEnded( assertionResult ); + assertionEnded( CATCH_MOVE(assertionResult) ); } void RunContext::handleNonExpr( AssertionInfo const &info, @@ -665,10 +668,10 @@ namespace Catch { AssertionResultData data( resultType, LazyExpression( false ) ); AssertionResult assertionResult{ info, CATCH_MOVE( data ) }; - assertionEnded( assertionResult ); - if( !assertionResult.isOk() ) - populateReaction( reaction ); + const auto isOk = assertionResult.isOk(); + assertionEnded( CATCH_MOVE(assertionResult) ); + if ( !isOk ) { populateReaction( reaction ); } } diff --git a/src/catch2/internal/catch_run_context.hpp b/src/catch2/internal/catch_run_context.hpp index 76cdd84d..c749304d 100644 --- a/src/catch2/internal/catch_run_context.hpp +++ b/src/catch2/internal/catch_run_context.hpp @@ -121,7 +121,7 @@ namespace Catch { void resetAssertionInfo(); bool testForMissingAssertions( Counts& assertions ); - void assertionEnded( AssertionResult const& result ); + void assertionEnded( AssertionResult&& result ); void reportExpr ( AssertionInfo const &info, ResultWas::OfType resultType, From 0dc82e08dfec25faf6c6c145f3592984db7276cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sun, 7 May 2023 12:09:22 +0200 Subject: [PATCH 14/26] Move CATCH_INTERNAL_STRINGIFY macro into its own header --- src/catch2/catch_all.hpp | 1 + .../catch_preprocessor_internal_stringify.hpp | 19 +++++++++++++++++++ src/catch2/internal/catch_test_macro_impl.hpp | 7 +------ .../matchers/internal/catch_matchers_impl.hpp | 7 ++++++- src/catch2/meson.build | 1 + 5 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 src/catch2/internal/catch_preprocessor_internal_stringify.hpp diff --git a/src/catch2/catch_all.hpp b/src/catch2/catch_all.hpp index 9b2cbe20..72de8de9 100644 --- a/src/catch2/catch_all.hpp +++ b/src/catch2/catch_all.hpp @@ -86,6 +86,7 @@ #include #include #include +#include #include #include #include diff --git a/src/catch2/internal/catch_preprocessor_internal_stringify.hpp b/src/catch2/internal/catch_preprocessor_internal_stringify.hpp new file mode 100644 index 00000000..2fd64e1c --- /dev/null +++ b/src/catch2/internal/catch_preprocessor_internal_stringify.hpp @@ -0,0 +1,19 @@ + +// Copyright Catch2 Authors +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE.txt or copy at +// https://www.boost.org/LICENSE_1_0.txt) + +// SPDX-License-Identifier: BSL-1.0 +#ifndef CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED +#define CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED + +#include + +#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) + #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr +#else + #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr +#endif + +#endif // CATCH_PREPROCESSOR_INTERNAL_STRINGIFY_HPP_INCLUDED diff --git a/src/catch2/internal/catch_test_macro_impl.hpp b/src/catch2/internal/catch_test_macro_impl.hpp index e569680b..8ed672ca 100644 --- a/src/catch2/internal/catch_test_macro_impl.hpp +++ b/src/catch2/internal/catch_test_macro_impl.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -22,12 +23,6 @@ #if !defined(CATCH_CONFIG_DISABLE) -#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION) - #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__##_catch_sr -#else - #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"_catch_sr -#endif - #if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) /////////////////////////////////////////////////////////////////////////////// diff --git a/src/catch2/matchers/internal/catch_matchers_impl.hpp b/src/catch2/matchers/internal/catch_matchers_impl.hpp index 12455bfe..2ee9f0c0 100644 --- a/src/catch2/matchers/internal/catch_matchers_impl.hpp +++ b/src/catch2/matchers/internal/catch_matchers_impl.hpp @@ -8,9 +8,14 @@ #ifndef CATCH_MATCHERS_IMPL_HPP_INCLUDED #define CATCH_MATCHERS_IMPL_HPP_INCLUDED -#include +#include +#include +#include +#include #include +#include + namespace Catch { template diff --git a/src/catch2/meson.build b/src/catch2/meson.build index 6aa1d9e1..89e96e23 100644 --- a/src/catch2/meson.build +++ b/src/catch2/meson.build @@ -110,6 +110,7 @@ internal_headers = [ 'internal/catch_platform.hpp', 'internal/catch_polyfills.hpp', 'internal/catch_preprocessor.hpp', + 'internal/catch_preprocessor_internal_stringify.hpp', 'internal/catch_preprocessor_remove_parens.hpp', 'internal/catch_random_number_generator.hpp', 'internal/catch_random_seed_generation.hpp', From 598895d04866c6e85f1d703a8c3d89e8d38a2311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 12 May 2023 09:50:59 +0200 Subject: [PATCH 15/26] Fix Wredundant-decls Closes #2682 --- CMake/CatchMiscFunctions.cmake | 1 + src/catch2/catch_session.cpp | 2 +- src/catch2/catch_test_spec.cpp | 1 + .../interfaces/catch_interfaces_testcase.hpp | 6 -- src/catch2/internal/catch_list.cpp | 2 +- .../catch_test_case_registry_impl.cpp | 55 +++++++++++-------- .../catch_test_case_registry_impl.hpp | 3 - 7 files changed, 36 insertions(+), 34 deletions(-) diff --git a/CMake/CatchMiscFunctions.cmake b/CMake/CatchMiscFunctions.cmake index 735c7868..44c87500 100644 --- a/CMake/CatchMiscFunctions.cmake +++ b/CMake/CatchMiscFunctions.cmake @@ -74,6 +74,7 @@ function(add_warnings_to_targets targets) "-Woverloaded-virtual" "-Wparentheses" "-Wpedantic" + "-Wredundant-decls" "-Wreorder" "-Wreturn-std-move" "-Wshadow" diff --git a/src/catch2/catch_session.cpp b/src/catch2/catch_session.cpp index af817017..86e215a9 100644 --- a/src/catch2/catch_session.cpp +++ b/src/catch2/catch_session.cpp @@ -13,9 +13,9 @@ #include #include #include -#include #include #include +#include #include #include #include diff --git a/src/catch2/catch_test_spec.cpp b/src/catch2/catch_test_spec.cpp index 99d83792..f32f9864 100644 --- a/src/catch2/catch_test_spec.cpp +++ b/src/catch2/catch_test_spec.cpp @@ -7,6 +7,7 @@ // SPDX-License-Identifier: BSL-1.0 #include #include +#include #include #include #include diff --git a/src/catch2/interfaces/catch_interfaces_testcase.hpp b/src/catch2/interfaces/catch_interfaces_testcase.hpp index f8e20351..daee8482 100644 --- a/src/catch2/interfaces/catch_interfaces_testcase.hpp +++ b/src/catch2/interfaces/catch_interfaces_testcase.hpp @@ -12,7 +12,6 @@ namespace Catch { - class TestSpec; struct TestCaseInfo; class TestCaseHandle; class IConfig; @@ -26,11 +25,6 @@ namespace Catch { virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; }; - bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config ); - bool matchTest( TestCaseHandle const& testCase, TestSpec const& testSpec, IConfig const& config ); - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); - } #endif // CATCH_INTERFACES_TESTCASE_HPP_INCLUDED diff --git a/src/catch2/internal/catch_list.cpp b/src/catch2/internal/catch_list.cpp index 4eb8bb7d..97e4c593 100644 --- a/src/catch2/internal/catch_list.cpp +++ b/src/catch2/internal/catch_list.cpp @@ -9,8 +9,8 @@ #include #include -#include #include +#include #include #include #include diff --git a/src/catch2/internal/catch_test_case_registry_impl.cpp b/src/catch2/internal/catch_test_case_registry_impl.cpp index b66469bc..f1702979 100644 --- a/src/catch2/internal/catch_test_case_registry_impl.cpp +++ b/src/catch2/internal/catch_test_case_registry_impl.cpp @@ -24,6 +24,38 @@ namespace Catch { + namespace { + static void enforceNoDuplicateTestCases( + std::vector const& tests ) { + auto testInfoCmp = []( TestCaseInfo const* lhs, + TestCaseInfo const* rhs ) { + return *lhs < *rhs; + }; + std::set seenTests( + testInfoCmp ); + for ( auto const& test : tests ) { + const auto infoPtr = &test.getTestCaseInfo(); + const auto prev = seenTests.insert( infoPtr ); + CATCH_ENFORCE( prev.second, + "error: test case \"" + << infoPtr->name << "\", with tags \"" + << infoPtr->tagsAsString() + << "\" already defined.\n" + << "\tFirst seen at " + << ( *prev.first )->lineInfo << "\n" + << "\tRedefined at " << infoPtr->lineInfo ); + } + } + + static bool matchTest( TestCaseHandle const& testCase, + TestSpec const& testSpec, + IConfig const& config ) { + return testSpec.matches( testCase.getTestCaseInfo() ) && + isThrowSafe( testCase, config ); + } + + } // end unnamed namespace + std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ) { switch (config.runOrder()) { case TestRunOrder::Declared: @@ -80,29 +112,6 @@ namespace Catch { return !testCase.getTestCaseInfo().throws() || config.allowThrows(); } - bool matchTest( TestCaseHandle const& testCase, TestSpec const& testSpec, IConfig const& config ) { - return testSpec.matches( testCase.getTestCaseInfo() ) && isThrowSafe( testCase, config ); - } - - void - enforceNoDuplicateTestCases( std::vector const& tests ) { - auto testInfoCmp = []( TestCaseInfo const* lhs, - TestCaseInfo const* rhs ) { - return *lhs < *rhs; - }; - std::set seenTests(testInfoCmp); - for ( auto const& test : tests ) { - const auto infoPtr = &test.getTestCaseInfo(); - const auto prev = seenTests.insert( infoPtr ); - CATCH_ENFORCE( - prev.second, - "error: test case \"" << infoPtr->name << "\", with tags \"" - << infoPtr->tagsAsString() << "\" already defined.\n" - << "\tFirst seen at " << ( *prev.first )->lineInfo << "\n" - << "\tRedefined at " << infoPtr->lineInfo ); - } - } - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ) { std::vector filtered; filtered.reserve( testCases.size() ); diff --git a/src/catch2/internal/catch_test_case_registry_impl.hpp b/src/catch2/internal/catch_test_case_registry_impl.hpp index 6784e034..a4a27ed1 100644 --- a/src/catch2/internal/catch_test_case_registry_impl.hpp +++ b/src/catch2/internal/catch_test_case_registry_impl.hpp @@ -24,9 +24,6 @@ namespace Catch { std::vector sortTests( IConfig const& config, std::vector const& unsortedTestCases ); bool isThrowSafe( TestCaseHandle const& testCase, IConfig const& config ); - bool matchTest( TestCaseHandle const& testCase, TestSpec const& testSpec, IConfig const& config ); - - void enforceNoDuplicateTestCases( std::vector const& functions ); std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); std::vector const& getAllTestCasesSorted( IConfig const& config ); From 5a40b2275caa05cf809bf04df848764a9d7df2e2 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 9 May 2023 21:23:03 +0300 Subject: [PATCH 16/26] Update CatchConfigOptions.cmake Fix CMake warning CMake Warning (dev) at catch2-src/CMake/CatchConfigOptions.cmake:71 (set): uninitialized variable 'BUILD_SHARED_LIBS' --- CMake/CatchConfigOptions.cmake | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CMake/CatchConfigOptions.cmake b/CMake/CatchConfigOptions.cmake index 733ec65e..e59f3a1e 100644 --- a/CMake/CatchConfigOptions.cmake +++ b/CMake/CatchConfigOptions.cmake @@ -68,7 +68,11 @@ set(_OtherConfigOptions foreach(OptionName ${_OtherConfigOptions}) AddConfigOption(${OptionName}) endforeach() -set(CATCH_CONFIG_SHARED_LIBRARY ${BUILD_SHARED_LIBS}) +if(DEFINED BUILD_SHARED_LIBS) + set(CATCH_CONFIG_SHARED_LIBRARY ${BUILD_SHARED_LIBS}) +else() + set(CATCH_CONFIG_SHARED_LIBRARY "") +endif() set(CATCH_CONFIG_DEFAULT_REPORTER "console" CACHE STRING "Read docs/configuration.md for details. The name of the reporter should be without quotes.") set(CATCH_CONFIG_CONSOLE_WIDTH "80" CACHE STRING "Read docs/configuration.md for details. Must form a valid integer literal.") From 6dce539faddd8002676e2158b8104ae161656559 Mon Sep 17 00:00:00 2001 From: Chris Thrasher Date: Sat, 13 May 2023 14:33:25 -0600 Subject: [PATCH 17/26] Add SFML to the list of open source users --- docs/opensource-users.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/opensource-users.md b/docs/opensource-users.md index df015f08..a02d0b98 100644 --- a/docs/opensource-users.md +++ b/docs/opensource-users.md @@ -95,6 +95,9 @@ A C++ client library for Consul. Consul is a distributed tool for discovering an ### [Reactive-Extensions/ RxCpp](https://github.com/Reactive-Extensions/RxCpp) A library of algorithms for values-distributed-in-time. +### [SFML](https://github.com/SFML/SFML) +Simple and Fast Multimedia Library. + ### [SOCI](https://github.com/SOCI/soci) The C++ Database Access Library. From f53bb3ae7b145f6d1e2f728980f8ef64b6f1d8fa Mon Sep 17 00:00:00 2001 From: Valeri Date: Sun, 14 May 2023 12:17:34 +0300 Subject: [PATCH 18/26] meson: require version >=0.54.1 See discussion in https://github.com/mesonbuild/wrapdb/pull/1016. --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 1faca35f..5b361d63 100644 --- a/meson.build +++ b/meson.build @@ -10,7 +10,7 @@ project( 'cpp', version: '3.3.2', # CML version placeholder, don't delete license: 'BSL-1.0', - meson_version: '>=0.50.0', + meson_version: '>=0.54.1', ) subdir('src/catch2') From 05d7eb5a0028906e4c6270b2340ae0d88d3cfa2a Mon Sep 17 00:00:00 2001 From: ThePhD Date: Tue, 16 May 2023 12:13:49 -0400 Subject: [PATCH 19/26] =?UTF-8?q?=F0=9F=9B=A0=20Add=20=20header?= =?UTF-8?q?=20where=20strictly=20necessary?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/catch2/benchmark/catch_benchmark.hpp | 1 + src/catch2/catch_registry_hub.cpp | 2 ++ src/catch2/catch_session.cpp | 1 + src/catch2/internal/catch_exception_translator_registry.cpp | 2 ++ 4 files changed, 6 insertions(+) diff --git a/src/catch2/benchmark/catch_benchmark.hpp b/src/catch2/benchmark/catch_benchmark.hpp index 3623133d..99d1c9df 100644 --- a/src/catch2/benchmark/catch_benchmark.hpp +++ b/src/catch2/benchmark/catch_benchmark.hpp @@ -30,6 +30,7 @@ #include #include +#include #include #include #include diff --git a/src/catch2/catch_registry_hub.cpp b/src/catch2/catch_registry_hub.cpp index 0e43db92..8716db3a 100644 --- a/src/catch2/catch_registry_hub.cpp +++ b/src/catch2/catch_registry_hub.cpp @@ -22,6 +22,8 @@ #include #include +#include + namespace Catch { namespace { diff --git a/src/catch2/catch_session.cpp b/src/catch2/catch_session.cpp index 86e215a9..f1ed5f9c 100644 --- a/src/catch2/catch_session.cpp +++ b/src/catch2/catch_session.cpp @@ -27,6 +27,7 @@ #include #include +#include #include #include diff --git a/src/catch2/internal/catch_exception_translator_registry.cpp b/src/catch2/internal/catch_exception_translator_registry.cpp index 0805d74c..f3d47c0c 100644 --- a/src/catch2/internal/catch_exception_translator_registry.cpp +++ b/src/catch2/internal/catch_exception_translator_registry.cpp @@ -11,6 +11,8 @@ #include #include +#include + namespace Catch { namespace { From a153fce72402c74bb8480c0776f86f889b658fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 20 May 2023 19:25:00 +0200 Subject: [PATCH 20/26] Improve error messages for TEST_CASE tag parsing errors Also removes a duplicated test case checking for empty tag error. Related to #2650 --- src/catch2/catch_test_case_info.cpp | 24 +++++++++++++++---- .../Baselines/automake.sw.approved.txt | 1 - .../Baselines/automake.sw.multi.approved.txt | 1 - .../Baselines/compact.sw.approved.txt | 5 ++-- .../Baselines/compact.sw.multi.approved.txt | 5 ++-- .../Baselines/console.std.approved.txt | 4 ++-- .../Baselines/console.sw.approved.txt | 13 ++-------- .../Baselines/console.sw.multi.approved.txt | 13 ++-------- .../SelfTest/Baselines/junit.sw.approved.txt | 3 +-- .../Baselines/junit.sw.multi.approved.txt | 3 +-- .../Baselines/sonarqube.sw.approved.txt | 1 - .../Baselines/sonarqube.sw.multi.approved.txt | 1 - tests/SelfTest/Baselines/tap.sw.approved.txt | 4 +--- .../Baselines/tap.sw.multi.approved.txt | 4 +--- .../Baselines/teamcity.sw.approved.txt | 2 -- .../Baselines/teamcity.sw.multi.approved.txt | 2 -- tests/SelfTest/Baselines/xml.sw.approved.txt | 15 ++---------- .../Baselines/xml.sw.multi.approved.txt | 15 ++---------- .../SelfTest/IntrospectiveTests/Tag.tests.cpp | 19 ++++++++++++--- 19 files changed, 54 insertions(+), 81 deletions(-) diff --git a/src/catch2/catch_test_case_info.cpp b/src/catch2/catch_test_case_info.cpp index a6adce0a..e9dad577 100644 --- a/src/catch2/catch_test_case_info.cpp +++ b/src/catch2/catch_test_case_info.cpp @@ -139,12 +139,20 @@ namespace Catch { for (size_t idx = 0; idx < originalTags.size(); ++idx) { auto c = originalTags[idx]; if (c == '[') { - assert(!inTag); + CATCH_ENFORCE( + !inTag, + "Found '[' inside a tag while registering test case '" + << _nameAndTags.name << "' at " << _lineInfo ); + inTag = true; tagStart = idx; } if (c == ']') { - assert(inTag); + CATCH_ENFORCE( + inTag, + "Found unmatched ']' while registering test case '" + << _nameAndTags.name << "' at " << _lineInfo ); + inTag = false; tagEnd = idx; assert(tagStart < tagEnd); @@ -153,7 +161,11 @@ namespace Catch { // it over to backing storage and actually reference the // backing storage in the saved tags StringRef tagStr = originalTags.substr(tagStart+1, tagEnd - tagStart - 1); - CATCH_ENFORCE(!tagStr.empty(), "Empty tags are not allowed"); + CATCH_ENFORCE( !tagStr.empty(), + "Found an empty tag while registering test case '" + << _nameAndTags.name << "' at " + << _lineInfo ); + enforceNotReservedTag(tagStr, lineInfo); properties |= parseSpecialTag(tagStr); // When copying a tag to the backing storage, we need to @@ -167,8 +179,12 @@ namespace Catch { // the tags. internalAppendTag(tagStr); } - (void)inTag; // Silence "set-but-unused" warning in release mode. } + CATCH_ENFORCE( !inTag, + "Found an unclosed tag while registering test case '" + << _nameAndTags.name << "' at " << _lineInfo ); + + // Add [.] if relevant if (isHidden()) { internalAppendTag("."_sr); diff --git a/tests/SelfTest/Baselines/automake.sw.approved.txt b/tests/SelfTest/Baselines/automake.sw.approved.txt index d33effdd..7c2836e8 100644 --- a/tests/SelfTest/Baselines/automake.sw.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.approved.txt @@ -131,7 +131,6 @@ Nor would this :test-result: PASS Default scale is invisible to comparison :test-result: PASS Directly creating an EnumInfo :test-result: PASS Empty stream name opens cout stream -:test-result: PASS Empty tag is not allowed :test-result: FAIL EndsWith string matcher :test-result: PASS Enums can quickly have stringification enabled using REGISTER_ENUM :test-result: PASS Enums in namespaces can quickly have stringification enabled using REGISTER_ENUM diff --git a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt index f698f0c5..75569816 100644 --- a/tests/SelfTest/Baselines/automake.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/automake.sw.multi.approved.txt @@ -129,7 +129,6 @@ :test-result: PASS Default scale is invisible to comparison :test-result: PASS Directly creating an EnumInfo :test-result: PASS Empty stream name opens cout stream -:test-result: PASS Empty tag is not allowed :test-result: FAIL EndsWith string matcher :test-result: PASS Enums can quickly have stringification enabled using REGISTER_ENUM :test-result: PASS Enums in namespaces can quickly have stringification enabled using REGISTER_ENUM diff --git a/tests/SelfTest/Baselines/compact.sw.approved.txt b/tests/SelfTest/Baselines/compact.sw.approved.txt index 541770cc..c72f140d 100644 --- a/tests/SelfTest/Baselines/compact.sw.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.approved.txt @@ -521,7 +521,6 @@ ToString.tests.cpp:: passed: enumInfo->lookup(3) == "{** unexpected == "{** unexpected enum value **}" Stream.tests.cpp:: passed: Catch::makeStream( "" )->isConsole() for: true -Tag.tests.cpp:: passed: Catch::TestCaseInfo( "", { "fake test name", "[]" }, dummySourceLineInfo ) Matchers.tests.cpp:: failed: testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring" Matchers.tests.cpp:: failed: testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive) EnumToString.tests.cpp:: passed: stringify( EnumClass3::Value1 ) == "Value1" for: "Value1" == "Value1" @@ -2538,7 +2537,7 @@ InternalBenchmark.tests.cpp:: passed: med == 18. for: 18.0 == 18.0 InternalBenchmark.tests.cpp:: passed: q3 == 23. for: 23.0 == 23.0 Misc.tests.cpp:: passed: Misc.tests.cpp:: passed: -test cases: 409 | 309 passed | 84 failed | 5 skipped | 11 failed as expected -assertions: 2226 | 2049 passed | 145 failed | 32 failed as expected +test cases: 408 | 308 passed | 84 failed | 5 skipped | 11 failed as expected +assertions: 2225 | 2048 passed | 145 failed | 32 failed as expected diff --git a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt index 5b292da1..7970ca44 100644 --- a/tests/SelfTest/Baselines/compact.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/compact.sw.multi.approved.txt @@ -519,7 +519,6 @@ ToString.tests.cpp:: passed: enumInfo->lookup(3) == "{** unexpected == "{** unexpected enum value **}" Stream.tests.cpp:: passed: Catch::makeStream( "" )->isConsole() for: true -Tag.tests.cpp:: passed: Catch::TestCaseInfo( "", { "fake test name", "[]" }, dummySourceLineInfo ) Matchers.tests.cpp:: failed: testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring" Matchers.tests.cpp:: failed: testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) for: "this string contains 'abc' as a substring" ends with: "this" (case insensitive) EnumToString.tests.cpp:: passed: stringify( EnumClass3::Value1 ) == "Value1" for: "Value1" == "Value1" @@ -2527,7 +2526,7 @@ InternalBenchmark.tests.cpp:: passed: med == 18. for: 18.0 == 18.0 InternalBenchmark.tests.cpp:: passed: q3 == 23. for: 23.0 == 23.0 Misc.tests.cpp:: passed: Misc.tests.cpp:: passed: -test cases: 409 | 309 passed | 84 failed | 5 skipped | 11 failed as expected -assertions: 2226 | 2049 passed | 145 failed | 32 failed as expected +test cases: 408 | 308 passed | 84 failed | 5 skipped | 11 failed as expected +assertions: 2225 | 2048 passed | 145 failed | 32 failed as expected diff --git a/tests/SelfTest/Baselines/console.std.approved.txt b/tests/SelfTest/Baselines/console.std.approved.txt index 15d8b024..31ca04f0 100644 --- a/tests/SelfTest/Baselines/console.std.approved.txt +++ b/tests/SelfTest/Baselines/console.std.approved.txt @@ -1533,6 +1533,6 @@ due to unexpected exception with message: Why would you throw a std::string? =============================================================================== -test cases: 409 | 323 passed | 69 failed | 6 skipped | 11 failed as expected -assertions: 2209 | 2049 passed | 128 failed | 32 failed as expected +test cases: 408 | 322 passed | 69 failed | 6 skipped | 11 failed as expected +assertions: 2208 | 2048 passed | 128 failed | 32 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.approved.txt b/tests/SelfTest/Baselines/console.sw.approved.txt index db724867..68bda6cd 100644 --- a/tests/SelfTest/Baselines/console.sw.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.approved.txt @@ -3967,15 +3967,6 @@ Stream.tests.cpp:: PASSED: with expansion: true -------------------------------------------------------------------------------- -Empty tag is not allowed -------------------------------------------------------------------------------- -Tag.tests.cpp: -............................................................................... - -Tag.tests.cpp:: PASSED: - REQUIRE_THROWS( Catch::TestCaseInfo( "", { "fake test name", "[]" }, dummySourceLineInfo ) ) - ------------------------------------------------------------------------------- EndsWith string matcher ------------------------------------------------------------------------------- @@ -18231,6 +18222,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 409 | 309 passed | 84 failed | 5 skipped | 11 failed as expected -assertions: 2226 | 2049 passed | 145 failed | 32 failed as expected +test cases: 408 | 308 passed | 84 failed | 5 skipped | 11 failed as expected +assertions: 2225 | 2048 passed | 145 failed | 32 failed as expected diff --git a/tests/SelfTest/Baselines/console.sw.multi.approved.txt b/tests/SelfTest/Baselines/console.sw.multi.approved.txt index 67b2dcb8..3f5e91d1 100644 --- a/tests/SelfTest/Baselines/console.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/console.sw.multi.approved.txt @@ -3965,15 +3965,6 @@ Stream.tests.cpp:: PASSED: with expansion: true -------------------------------------------------------------------------------- -Empty tag is not allowed -------------------------------------------------------------------------------- -Tag.tests.cpp: -............................................................................... - -Tag.tests.cpp:: PASSED: - REQUIRE_THROWS( Catch::TestCaseInfo( "", { "fake test name", "[]" }, dummySourceLineInfo ) ) - ------------------------------------------------------------------------------- EndsWith string matcher ------------------------------------------------------------------------------- @@ -18220,6 +18211,6 @@ Misc.tests.cpp: Misc.tests.cpp:: PASSED: =============================================================================== -test cases: 409 | 309 passed | 84 failed | 5 skipped | 11 failed as expected -assertions: 2226 | 2049 passed | 145 failed | 32 failed as expected +test cases: 408 | 308 passed | 84 failed | 5 skipped | 11 failed as expected +assertions: 2225 | 2048 passed | 145 failed | 32 failed as expected diff --git a/tests/SelfTest/Baselines/junit.sw.approved.txt b/tests/SelfTest/Baselines/junit.sw.approved.txt index cf0c9170..74e08986 100644 --- a/tests/SelfTest/Baselines/junit.sw.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.approved.txt @@ -1,7 +1,7 @@ - + @@ -463,7 +463,6 @@ at Exception.tests.cpp: - FAILED: diff --git a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt index f900bc99..73f37422 100644 --- a/tests/SelfTest/Baselines/junit.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/junit.sw.multi.approved.txt @@ -1,6 +1,6 @@ - + @@ -462,7 +462,6 @@ at Exception.tests.cpp: - FAILED: diff --git a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt index 5e78a714..eeb8d17b 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -233,7 +233,6 @@ - diff --git a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt index b8f7d646..a804cb6b 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt @@ -232,7 +232,6 @@ - diff --git a/tests/SelfTest/Baselines/tap.sw.approved.txt b/tests/SelfTest/Baselines/tap.sw.approved.txt index 920c95fd..ba7d2dfa 100644 --- a/tests/SelfTest/Baselines/tap.sw.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.approved.txt @@ -986,8 +986,6 @@ ok {test-number} - enumInfo->lookup(1) == "Value2" for: Value2 == "Value2" ok {test-number} - enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} == "{** unexpected enum value **}" # Empty stream name opens cout stream ok {test-number} - Catch::makeStream( "" )->isConsole() for: true -# Empty tag is not allowed -ok {test-number} - Catch::TestCaseInfo( "", { "fake test name", "[]" }, dummySourceLineInfo ) # EndsWith string matcher not ok {test-number} - testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring" # EndsWith string matcher @@ -4477,5 +4475,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2237 +1..2236 diff --git a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt index c0e0c4db..07014c2e 100644 --- a/tests/SelfTest/Baselines/tap.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/tap.sw.multi.approved.txt @@ -984,8 +984,6 @@ ok {test-number} - enumInfo->lookup(1) == "Value2" for: Value2 == "Value2" ok {test-number} - enumInfo->lookup(3) == "{** unexpected enum value **}" for: {** unexpected enum value **} == "{** unexpected enum value **}" # Empty stream name opens cout stream ok {test-number} - Catch::makeStream( "" )->isConsole() for: true -# Empty tag is not allowed -ok {test-number} - Catch::TestCaseInfo( "", { "fake test name", "[]" }, dummySourceLineInfo ) # EndsWith string matcher not ok {test-number} - testStringForMatching(), EndsWith( "Substring" ) for: "this string contains 'abc' as a substring" ends with: "Substring" # EndsWith string matcher @@ -4466,5 +4464,5 @@ ok {test-number} - q3 == 23. for: 23.0 == 23.0 ok {test-number} - # xmlentitycheck ok {test-number} - -1..2237 +1..2236 diff --git a/tests/SelfTest/Baselines/teamcity.sw.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.approved.txt index 8a8b55e2..aff95cf6 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.approved.txt @@ -301,8 +301,6 @@ ##teamcity[testFinished name='Directly creating an EnumInfo' duration="{duration}"] ##teamcity[testStarted name='Empty stream name opens cout stream'] ##teamcity[testFinished name='Empty stream name opens cout stream' duration="{duration}"] -##teamcity[testStarted name='Empty tag is not allowed'] -##teamcity[testFinished name='Empty tag is not allowed' duration="{duration}"] ##teamcity[testStarted name='EndsWith string matcher'] ##teamcity[testFailed name='EndsWith string matcher' message='Matchers.tests.cpp:|n...............................................................................|n|nMatchers.tests.cpp:|nexpression failed|n CHECK_THAT( testStringForMatching(), EndsWith( "Substring" ) )|nwith expansion:|n "this string contains |'abc|' as a substring" ends with: "Substring"|n'] ##teamcity[testFailed name='EndsWith string matcher' message='Matchers.tests.cpp:|nexpression failed|n CHECK_THAT( testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) )|nwith expansion:|n "this string contains |'abc|' as a substring" ends with: "this" (case insensitive)|n'] diff --git a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt index 77f70a63..f16bc135 100644 --- a/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/teamcity.sw.multi.approved.txt @@ -301,8 +301,6 @@ ##teamcity[testFinished name='Directly creating an EnumInfo' duration="{duration}"] ##teamcity[testStarted name='Empty stream name opens cout stream'] ##teamcity[testFinished name='Empty stream name opens cout stream' duration="{duration}"] -##teamcity[testStarted name='Empty tag is not allowed'] -##teamcity[testFinished name='Empty tag is not allowed' duration="{duration}"] ##teamcity[testStarted name='EndsWith string matcher'] ##teamcity[testFailed name='EndsWith string matcher' message='Matchers.tests.cpp:|n...............................................................................|n|nMatchers.tests.cpp:|nexpression failed|n CHECK_THAT( testStringForMatching(), EndsWith( "Substring" ) )|nwith expansion:|n "this string contains |'abc|' as a substring" ends with: "Substring"|n'] ##teamcity[testFailed name='EndsWith string matcher' message='Matchers.tests.cpp:|nexpression failed|n CHECK_THAT( testStringForMatching(), EndsWith( "this", Catch::CaseSensitive::No ) )|nwith expansion:|n "this string contains |'abc|' as a substring" ends with: "this" (case insensitive)|n'] diff --git a/tests/SelfTest/Baselines/xml.sw.approved.txt b/tests/SelfTest/Baselines/xml.sw.approved.txt index aaf28b61..8509e370 100644 --- a/tests/SelfTest/Baselines/xml.sw.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.approved.txt @@ -4375,17 +4375,6 @@ C - - - - Catch::TestCaseInfo( "", { "fake test name", "[]" }, dummySourceLineInfo ) - - - Catch::TestCaseInfo( "", { "fake test name", "[]" }, dummySourceLineInfo ) - - - - @@ -21203,6 +21192,6 @@ b1!
- - + + diff --git a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt index 706c4ac9..adf83986 100644 --- a/tests/SelfTest/Baselines/xml.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/xml.sw.multi.approved.txt @@ -4375,17 +4375,6 @@ C - - - - Catch::TestCaseInfo( "", { "fake test name", "[]" }, dummySourceLineInfo ) - - - Catch::TestCaseInfo( "", { "fake test name", "[]" }, dummySourceLineInfo ) - - - - @@ -21202,6 +21191,6 @@ b1!
- - + + diff --git a/tests/SelfTest/IntrospectiveTests/Tag.tests.cpp b/tests/SelfTest/IntrospectiveTests/Tag.tests.cpp index ef321b27..43723758 100644 --- a/tests/SelfTest/IntrospectiveTests/Tag.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/Tag.tests.cpp @@ -98,7 +98,20 @@ TEST_CASE( "Test case with identical tags keeps just one", "[tags]" ) { REQUIRE( testCase.tags[0] == Tag( "tag1" ) ); } -TEST_CASE( "Empty tag is not allowed" ) { - REQUIRE_THROWS( Catch::TestCaseInfo( - "", { "fake test name", "[]" }, dummySourceLineInfo ) ); +TEST_CASE("Mismatched square brackets in tags are caught and reported", + "[tags][approvals]") { + using Catch::TestCaseInfo; + using Catch::Matchers::ContainsSubstring; + REQUIRE_THROWS_WITH( TestCaseInfo( "", + { "test with unclosed tag", "[abc" }, + dummySourceLineInfo ), + ContainsSubstring("registering test case 'test with unclosed tag'") ); + REQUIRE_THROWS_WITH( TestCaseInfo( "", + { "test with nested tags", "[abc[def]]" }, + dummySourceLineInfo ), + ContainsSubstring("registering test case 'test with nested tags'") ); + REQUIRE_THROWS_WITH( TestCaseInfo( "", + { "test with superfluous close tags", "[abc][def]]" }, + dummySourceLineInfo ), + ContainsSubstring("registering test case 'test with superfluous close tags'") ); } From 689fdcd7dca80533791d67f7bf90bf5c4f63cac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Sat, 20 May 2023 22:03:48 +0200 Subject: [PATCH 21/26] Fix some tests never being run --- tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp b/tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp index fa9f8e2e..24bfe68c 100644 --- a/tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp @@ -444,6 +444,6 @@ TEST_CASE("Failing benchmarks", "[!benchmark][.approvals]") { } TEST_CASE( "Failing benchmark respects should-fail", - "[!shouldfail][!benchmark][.approvals]" ) { + "[!shouldfail][!benchmark][approvals]" ) { BENCHMARK( "Asserting benchmark" ) { REQUIRE( 1 == 2 ); }; } From 535205e2ac0d26d03126d93327b15c79ac35d3ef Mon Sep 17 00:00:00 2001 From: Cristian Morales Vega Date: Mon, 22 May 2023 09:45:43 +0100 Subject: [PATCH 22/26] Suppress -Wunused-result warning in gcc See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425. --- src/catch2/internal/catch_compiler_capabilities.hpp | 6 ++++++ src/catch2/internal/catch_test_macro_impl.hpp | 3 +++ 2 files changed, 9 insertions(+) diff --git a/src/catch2/internal/catch_compiler_capabilities.hpp b/src/catch2/internal/catch_compiler_capabilities.hpp index 42631a5f..76afb45f 100644 --- a/src/catch2/internal/catch_compiler_capabilities.hpp +++ b/src/catch2/internal/catch_compiler_capabilities.hpp @@ -50,6 +50,9 @@ # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ + _Pragma( "GCC diagnostic ignored \"-Wunused-result\"" ) + # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS \ _Pragma( "GCC diagnostic ignored \"-Wunused-variable\"" ) @@ -365,6 +368,9 @@ #if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS #endif +#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT +#endif #if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_UNUSED_VARIABLE_WARNINGS #endif diff --git a/src/catch2/internal/catch_test_macro_impl.hpp b/src/catch2/internal/catch_test_macro_impl.hpp index 8ed672ca..39366023 100644 --- a/src/catch2/internal/catch_test_macro_impl.hpp +++ b/src/catch2/internal/catch_test_macro_impl.hpp @@ -90,6 +90,7 @@ if( catchAssertionHandler.allowThrows() ) \ try { \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ static_cast(__VA_ARGS__); \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ @@ -110,6 +111,7 @@ if( catchAssertionHandler.allowThrows() ) \ try { \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ static_cast(expr); \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ @@ -136,6 +138,7 @@ if( catchAssertionHandler.allowThrows() ) \ try { \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ + CATCH_INTERNAL_SUPPRESS_UNUSED_RESULT \ CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ static_cast(__VA_ARGS__); \ CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ From ce7b1530219a638b0852805544e99f673c38ca86 Mon Sep 17 00:00:00 2001 From: Ali-Amir Aldan Date: Fri, 26 May 2023 10:05:06 -0700 Subject: [PATCH 23/26] Add option to disable building unit tests in Meson build file. --- meson.build | 4 +++- meson_options.txt | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 meson_options.txt diff --git a/meson.build b/meson.build index 5b361d63..ed5033ac 100644 --- a/meson.build +++ b/meson.build @@ -14,4 +14,6 @@ project( ) subdir('src/catch2') -subdir('tests') +if get_option('tests') + subdir('tests') +endif diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 00000000..76904873 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1 @@ +option('tests', type: 'boolean', value: true, description: 'Build the unit tests') From 73b93ce6bc1310f9e759f023da74805d311162e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Fri, 12 May 2023 17:03:35 +0200 Subject: [PATCH 24/26] Include catch_user_config.hpp in all catch_config_* files --- src/catch2/internal/catch_config_counter.hpp | 2 ++ src/catch2/internal/catch_config_uncaught_exceptions.hpp | 2 ++ src/catch2/internal/catch_config_wchar.hpp | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/catch2/internal/catch_config_counter.hpp b/src/catch2/internal/catch_config_counter.hpp index 23b22324..a482ce34 100644 --- a/src/catch2/internal/catch_config_counter.hpp +++ b/src/catch2/internal/catch_config_counter.hpp @@ -18,6 +18,8 @@ #ifndef CATCH_CONFIG_COUNTER_HPP_INCLUDED #define CATCH_CONFIG_COUNTER_HPP_INCLUDED +#include + #if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) #define CATCH_INTERNAL_CONFIG_COUNTER #endif diff --git a/src/catch2/internal/catch_config_uncaught_exceptions.hpp b/src/catch2/internal/catch_config_uncaught_exceptions.hpp index 5c4cb930..20b1dfca 100644 --- a/src/catch2/internal/catch_config_uncaught_exceptions.hpp +++ b/src/catch2/internal/catch_config_uncaught_exceptions.hpp @@ -17,6 +17,8 @@ #ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED #define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED +#include + #if defined(_MSC_VER) # if _MSC_VER >= 1900 // Visual Studio 2015 or newer # define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS diff --git a/src/catch2/internal/catch_config_wchar.hpp b/src/catch2/internal/catch_config_wchar.hpp index 8c758ec4..90d85d05 100644 --- a/src/catch2/internal/catch_config_wchar.hpp +++ b/src/catch2/internal/catch_config_wchar.hpp @@ -17,6 +17,8 @@ #ifndef CATCH_CONFIG_WCHAR_HPP_INCLUDED #define CATCH_CONFIG_WCHAR_HPP_INCLUDED +#include + // We assume that WCHAR should be enabled by default, and only disabled // for a shortlist (so far only DJGPP) of compilers. From b3cf1bfb5d2476b1793c9ebc845803d60ce34171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 17 May 2023 11:08:45 +0200 Subject: [PATCH 25/26] Avoid unused variable warning in GeneratorsImpl tests --- tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp b/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp index 64e943f8..f7b7c57c 100644 --- a/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp +++ b/tests/SelfTest/IntrospectiveTests/GeneratorsImpl.tests.cpp @@ -412,6 +412,7 @@ TEST_CASE("GENERATE handles function (pointers)", "[generators][compilation][app TEST_CASE("GENERATE decays arrays", "[generators][compilation][approvals]") { auto str = GENERATE("abc", "def", "gh"); + (void)str; STATIC_REQUIRE(std::is_same::value); } From f60c15364bb4be1c9a34f19eac06f085828a2c5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Ho=C5=99e=C5=88ovsk=C3=BD?= Date: Wed, 17 May 2023 11:10:57 +0200 Subject: [PATCH 26/26] Add macro for suppressing Wshadow --- .../internal/catch_compiler_capabilities.hpp | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/catch2/internal/catch_compiler_capabilities.hpp b/src/catch2/internal/catch_compiler_capabilities.hpp index 76afb45f..fc5d4f31 100644 --- a/src/catch2/internal/catch_compiler_capabilities.hpp +++ b/src/catch2/internal/catch_compiler_capabilities.hpp @@ -59,6 +59,9 @@ # define CATCH_INTERNAL_SUPPRESS_USELESS_CAST_WARNINGS \ _Pragma( "GCC diagnostic ignored \"-Wuseless-cast\"" ) +# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ + _Pragma( "GCC diagnostic ignored \"-Wshadow\"" ) + # define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) #endif @@ -131,6 +134,9 @@ # define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS \ _Pragma( "clang diagnostic ignored \"-Wcomma\"" ) +# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS \ + _Pragma( "clang diagnostic ignored \"-Wshadow\"" ) + #endif // __clang__ @@ -380,6 +386,16 @@ #if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) # define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS #endif +#if !defined( CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS ) +# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS +#endif +#if !defined( CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS ) +# define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS +#endif +#if !defined( CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS ) +# define CATCH_INTERNAL_SUPPRESS_SHADOW_WARNINGS +#endif + // The goal of this macro is to avoid evaluation of the arguments, but // still have the compiler warn on problems inside... @@ -393,13 +409,6 @@ # undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS #endif -#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#endif - -#if !defined(CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_COMMA_WARNINGS -#endif #if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) #define CATCH_TRY if ((true))