diff options
| author | Leitwolf | 2026-10-25 10:31:36 +0300 |
|---|---|---|
| committer | GitHub | 2026-10-25 10:31:36 +0300 |
| commit | d2e3e074bb2e1b8ffd9fc990d0b87667ea602f58 (patch) | |
| tree | 0bce4462b2e190c39b3e1c5f697e3e4abd1a5e2a /extras | |
| parent | 13f81a480a93807c14dddb5abdb97355ced4d4c5 (diff) | |
| parent | 126dc333564cb72b5115d9a9242d66694694b6d0 (diff) | |
| download | catch3-d2e3e074bb2e1b8ffd9fc990d0b87667ea602f58.tar.gz | |
Merge pull request #18 from Progmasoft/build/catch3-identity
Give Catch3 its own build names and headers
Diffstat (limited to 'extras')
| -rw-r--r-- | extras/Catch3.cmake (renamed from extras/Catch.cmake) | 46 | ||||
| -rw-r--r-- | extras/Catch3AddTests.cmake (renamed from extras/CatchAddTests.cmake) | 50 | ||||
| -rw-r--r-- | extras/Catch3ShardTests.cmake (renamed from extras/CatchShardTests.cmake) | 10 | ||||
| -rw-r--r-- | extras/Catch3ShardTestsImpl.cmake (renamed from extras/CatchShardTestsImpl.cmake) | 0 | ||||
| -rw-r--r-- | extras/ParseAndAddCatchTests.cmake | 250 | ||||
| -rw-r--r-- | extras/catch_amalgamated.cpp | 2739 | ||||
| -rw-r--r-- | extras/catch_amalgamated.hpp | 8575 |
7 files changed, 5473 insertions, 6197 deletions
diff --git a/extras/Catch.cmake b/extras/Catch3.cmake index 1b068de6..064d44b6 100644 --- a/extras/Catch.cmake +++ b/extras/Catch3.cmake @@ -2,12 +2,12 @@ # file Copyright.txt or https://cmake.org/licensing for details. #[=======================================================================[.rst: -Catch ------ +Catch3 +------ -This module defines a function to help use the Catch test framework. +This module defines a function to help use the Catch3 test framework. -The :command:`catch_discover_tests` discovers tests by asking the compiled test +The :command:`catch3_discover_tests` discovers tests by asking the compiled test executable to enumerate its tests. This does not require CMake to be re-run when tests change. However, it may not work in a cross-compiling environment, and setting test properties is less convenient. @@ -20,12 +20,12 @@ However, it provides more fine-grained pass/fail information to CTest, which is usually considered as more beneficial. By default, the CTest test name is the same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. -.. command:: catch_discover_tests +.. command:: catch3_discover_tests Automatically add tests with CTest by querying the compiled test executable for available tests:: - catch_discover_tests(target + catch3_discover_tests(target [TEST_SPEC arg1...] [EXTRA_ARGS arg1...] [WORKING_DIRECTORY dir] @@ -42,7 +42,7 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. [ADD_TAGS_AS_LABELS] ) - ``catch_discover_tests`` sets up a post-build command on the test executable + ``catch3_discover_tests`` sets up a post-build command on the test executable that generates the list of tests by parsing the output from running the test with the ``--list=json`` argument, the discovery protocol of the Catch3 runner (``"format": "catch3-tests"``, version 1). This ensures that the full @@ -85,7 +85,7 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. ``TEST_PREFIX prefix`` Specifies a ``prefix`` to be prepended to the name of each discovered test case. This can be useful when the same test executable is being used in - multiple calls to ``catch_discover_tests()`` but with different + multiple calls to ``catch3_discover_tests()`` but with different ``TEST_SPEC`` or ``EXTRA_ARGS``. ``TEST_SUFFIX suffix`` @@ -95,12 +95,12 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. ``PROPERTIES name1 value1...`` Specifies additional properties to be set on all tests discovered by this - invocation of ``catch_discover_tests``. + invocation of ``catch3_discover_tests``. ``TEST_LIST var`` Make the list of tests available in the variable ``var``, rather than the default ``<target>_TESTS``. This can be useful when the same test - executable is being used in multiple calls to ``catch_discover_tests()``. + executable is being used in multiple calls to ``catch3_discover_tests()``. Note that this variable is only available in CTest. ``REPORTER reporter`` @@ -139,7 +139,7 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. This requires cmake/ctest >= 3.22. ``DISCOVERY_MODE mode`` - Provides control over when ``catch_discover_tests`` performs test discovery. + Provides control over when ``catch3_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 @@ -147,8 +147,8 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. 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 + ``CMAKE_CATCH3_DISCOVER_TESTS_DISCOVERY_MODE`` variable if it is not passed when + calling ``catch3_discover_tests``. This provides a mechanism for globally selecting a preferred test discovery behavior without having to modify each call site. On Apple Silicon with the Xcode generator you must use ``PRE_TEST``. With the @@ -166,7 +166,7 @@ same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. #]=======================================================================] #------------------------------------------------------------------------------ -function(catch_discover_tests TARGET) +function(catch3_discover_tests TARGET) cmake_parse_arguments( "" @@ -193,10 +193,10 @@ function(catch_discover_tests TARGET) message(FATAL_ERROR "The DL_FRAMEWORK_PATHS option requires at least cmake 3.22") endif() if(NOT _DISCOVERY_MODE) - if(NOT CMAKE_CATCH_DISCOVER_TESTS_DISCOVERY_MODE) - set(CMAKE_CATCH_DISCOVER_TESTS_DISCOVERY_MODE "POST_BUILD") + if(NOT CMAKE_CATCH3_DISCOVER_TESTS_DISCOVERY_MODE) + set(CMAKE_CATCH3_DISCOVER_TESTS_DISCOVERY_MODE "POST_BUILD") endif() - set(_DISCOVERY_MODE ${CMAKE_CATCH_DISCOVER_TESTS_DISCOVERY_MODE}) + set(_DISCOVERY_MODE ${CMAKE_CATCH3_DISCOVER_TESTS_DISCOVERY_MODE}) endif() if(NOT _DISCOVERY_MODE MATCHES "^(POST_BUILD|PRE_TEST)$") message(FATAL_ERROR "Unknown DISCOVERY_MODE: ${_DISCOVERY_MODE}") @@ -242,7 +242,7 @@ function(catch_discover_tests TARGET) -D "TEST_DL_FRAMEWORK_PATHS=${_DL_FRAMEWORK_PATHS}" -D "CTEST_FILE=${ctest_tests_file}" -D "ADD_TAGS_AS_LABELS=${_ADD_TAGS_AS_LABELS}" - -P "${_CATCH_DISCOVER_TESTS_SCRIPT}" + -P "${_CATCH3_DISCOVER_TESTS_SCRIPT}" VERBATIM ) @@ -269,8 +269,8 @@ function(catch_discover_tests TARGET) " if(NOT EXISTS \"${ctest_tests_file}\" OR" "\n" " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"$<TARGET_FILE:${TARGET}>\" 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" + " include(\"${_CATCH3_DISCOVER_TESTS_SCRIPT}\")" "\n" + " catch3_discover_tests_impl(" "\n" " TEST_EXECUTABLE" " [==[" "$<TARGET_FILE:${TARGET}>" "]==]" "\n" " TEST_EXECUTOR" " [==[" "${crosscompiling_emulator}" "]==]" "\n" " TEST_WORKING_DIR" " [==[" "${_WORKING_DIRECTORY}" "]==]" "\n" @@ -323,7 +323,7 @@ endfunction() ############################################################################### -set(_CATCH_DISCOVER_TESTS_SCRIPT - ${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake - CACHE INTERNAL "Catch2 full path to CatchAddTests.cmake helper file" +set(_CATCH3_DISCOVER_TESTS_SCRIPT + ${CMAKE_CURRENT_LIST_DIR}/Catch3AddTests.cmake + CACHE INTERNAL "Full path to the Catch3AddTests.cmake helper file" ) diff --git a/extras/CatchAddTests.cmake b/extras/Catch3AddTests.cmake index ef2fb439..cbe431d4 100644 --- a/extras/CatchAddTests.cmake +++ b/extras/Catch3AddTests.cmake @@ -39,7 +39,7 @@ string(ASCII 3 _CloseBracketListingEscape) # Placeholder bytes in the listing would break our parsing hack, so # we check they don't exist. They shouldn't exist in valid JSON, but # the reporter might not be escaping them properly. -function(validate_input_noescapes listing_var) +function(catch3_validate_input_noescapes listing_var) foreach(byte "${_SemicolonEscape}" "${_BoundaryEscape}" "${_OpenBracketEscape}" "${_CloseBracketEscape}") string(FIND "${${listing_var}}" "${byte}" found) if(NOT found EQUAL -1) @@ -54,7 +54,7 @@ endfunction() # Replaces relevant characters with their placeholders, see the top of this file. # Modifies argument `var` in place. -function(magic_escape_chars var) +function(catch3_magic_escape_chars var) set(value "${${var}}") string(REPLACE ";" "${_SemicolonEscape}" value "${value}") string(REPLACE "[" "${_OpenBracketEscape}" value "${value}") @@ -65,7 +65,7 @@ endfunction() # Turns placeholders back into original characters, see the top of this file. # Modifies argument `var` in place. -function(magic_unescape_chars var) +function(catch3_magic_unescape_chars var) set(value "${${var}}") string(REPLACE "${_SemicolonEscape}" ";" value "${value}") string(REPLACE "${_OpenBracketEscape}" "[" value "${value}") @@ -95,7 +95,7 @@ endfunction() # Note that to support passing the object strings back from the function, # they will still contain the placeholders and need to be unescaped before # further processing (e.g. sending them into CMake's JSON parsing API). -function(split_json_array json_array_var out_var) +function(catch3_split_json_array json_array_var out_var) # We have to pass the input by var name to avoid CMake processing # the input as an arg. set(json_in "${${json_array_var}}") @@ -106,7 +106,7 @@ function(split_json_array json_array_var out_var) string(REGEX REPLACE "^[ \t\r\n]*\\[" "" json_in "${json_in}") string(REGEX REPLACE "\\][ \t\r\n]*$" "" json_in "${json_in}") - magic_escape_chars(json_in) + catch3_magic_escape_chars(json_in) # We need to keep the whitespace around comma around, so that if we # split inside the test object, we can reconstruct it losslessly. @@ -129,7 +129,7 @@ function(split_json_array json_array_var out_var) # Because the fragments (might) contain invalid JSON characters due # to escaping, we have to unescape it before checking if we can parse it. set(maybe_json "${accumulator}") - magic_unescape_chars(maybe_json) + catch3_magic_unescape_chars(maybe_json) string(JSON unused ERROR_VARIABLE err GET "${maybe_json}" "name") if(err STREQUAL "NOTFOUND") list(APPEND array_elements "${accumulator}") @@ -145,7 +145,7 @@ endfunction() # # This allows the registration script to escape parts of the test script # only once, instead of escaping the unchanged arguments over and over again. -function(prepare_command_fragment out_var) +function(catch3_prepare_command_fragment out_var) set(_args "") math(EXPR _last_arg ${ARGC}-1) if(_last_arg GREATER_EQUAL 1) @@ -164,7 +164,7 @@ endfunction() # Generates random filename in the temp folder. # Temp folder is retrieved by checking env vars from various platforms. -function(make_temp_file_path OUT_VARIABLE FALLBACK_PATH) +function(catch3_make_temp_file_path OUT_VARIABLE FALLBACK_PATH) set(TEMP_DIR "") set(ENV_VARS # From XDG base dir specification @@ -192,7 +192,7 @@ function(make_temp_file_path OUT_VARIABLE FALLBACK_PATH) # Generate the random file name string(RANDOM LENGTH 8 RAND_ID) - set(FINAL_TEMP_PATH "${TEMP_DIR}/Catch2-test-listing.${RAND_ID}.json") + set(FINAL_TEMP_PATH "${TEMP_DIR}/Catch3-test-listing.${RAND_ID}.json") set(${OUT_VARIABLE} "${FINAL_TEMP_PATH}" PARENT_SCOPE) endfunction() @@ -205,7 +205,7 @@ endfunction() # # <base>_tests.cmake -> <base>_test-list.cmake # <base>_tests-Debug.cmake -> <base>_test-list-Debug.cmake -function(make_test_list_file_path CTEST_FILE OUT_VARIABLE) +function(catch3_make_test_list_file_path CTEST_FILE OUT_VARIABLE) if("${CTEST_FILE}" MATCHES "_tests(.*)\\.cmake$") string(REGEX REPLACE "_tests(.*)\\.cmake$" "_test-list\\1.cmake" list_file "${CTEST_FILE}") else() @@ -214,7 +214,7 @@ function(make_test_list_file_path CTEST_FILE OUT_VARIABLE) set(${OUT_VARIABLE} "${list_file}" PARENT_SCOPE) endfunction() -function(catch_discover_tests_impl) +function(catch3_discover_tests_impl) cmake_parse_arguments( "" "" @@ -224,7 +224,7 @@ function(catch_discover_tests_impl) ) # We write the list of all discovered tests into a separate file - make_test_list_file_path("${_CTEST_FILE}" _CTEST_LIST_FILE) + catch3_make_test_list_file_path("${_CTEST_FILE}" _CTEST_LIST_FILE) # We periodically append to the output files below, so we have to ensure # that it is empty at the start, or we get duplicated test scripts. @@ -306,7 +306,7 @@ function(catch_discover_tests_impl) if(listing_start GREATER 0) string(SUBSTRING "${listing_output}" ${listing_start} -1 listing_output) endif() - validate_input_noescapes(listing_output) + catch3_validate_input_noescapes(listing_output) # The runner writes reports itself: REPORTER chooses which, OUTPUT_DIR where. set(report_option "") @@ -360,7 +360,7 @@ function(catch_discover_tests_impl) # Extract just the JSON array with tests and then split them into # individual objects. string(JSON test_listing GET "${listing_output}" "tests") - split_json_array(test_listing tests) + catch3_split_json_array(test_listing tests) # Exit early if no tests are detected if(NOT tests) @@ -378,7 +378,7 @@ function(catch_discover_tests_impl) set(test_names "set(${_TEST_LIST}") # Most of the commands/arguments in the CTest script are identical - # for every test registered with one `catch_discover_tests` call. + # for every test registered with one `catch3_discover_tests` call. # To avoid repeating the work in escaping them, we escape them before # the per-test loop and reuse the escaped fragments. # @@ -386,11 +386,11 @@ function(catch_discover_tests_impl) # add_test(<name><exec><exe><escaped_name><extra_args><reporter><out_dir>) # Of these, <exec>,<exe>,<extra_args>, and <reporter> are the same between # all tests. - prepare_command_fragment(_exec_exe_fragment + catch3_prepare_command_fragment(_exec_exe_fragment ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" ) - prepare_command_fragment(_args_reporter_fragment + catch3_prepare_command_fragment(_args_reporter_fragment "${extra_args}" ) @@ -398,14 +398,14 @@ function(catch_discover_tests_impl) # set_tests_properties(<name> PROPERTIES WORKING_DIRECTORY <dir> <properties>) # set_tests_properties(<name> PROPERTIES ENVIRONMENT_MODIFICATION <env_mod>) # Of these, only the <name> changes between tests. - prepare_command_fragment(_properties_fragment + catch3_prepare_command_fragment(_properties_fragment PROPERTIES WORKING_DIRECTORY "${_TEST_WORKING_DIR}" ${properties} ) # Env modification is optional, so we prepare it in a separate command if(environment_modifications) - prepare_command_fragment(_env_modification_fragment + catch3_prepare_command_fragment(_env_modification_fragment PROPERTIES ENVIRONMENT_MODIFICATION "${environment_modifications}" ) @@ -429,7 +429,7 @@ function(catch_discover_tests_impl) # The elements are still escaped and contain JSON-invalid characters, # they have to be unescaped before parsing them as JSON. - magic_unescape_chars(single_test) + catch3_magic_unescape_chars(single_test) if(add_tags) string(JSON test_tags GET "${single_test}" "tags") endif() @@ -450,9 +450,9 @@ function(catch_discover_tests_impl) endif() set(full_name "${prefix}${plain_name}${suffix}") - prepare_command_fragment(_full_name_fragment "${full_name}") - prepare_command_fragment(_escaped_name_fragment "${escaped_name}") - prepare_command_fragment(_outdir_fragment "${output_dir_arg}") + catch3_prepare_command_fragment(_full_name_fragment "${full_name}") + catch3_prepare_command_fragment(_escaped_name_fragment "${escaped_name}") + catch3_prepare_command_fragment(_outdir_fragment "${output_dir_arg}") string(APPEND script "add_test(${_full_name_fragment}${_exec_exe_fragment}${_escaped_name_fragment}${_args_reporter_fragment}${_outdir_fragment})\n") @@ -477,7 +477,7 @@ function(catch_discover_tests_impl) list(APPEND tag_list "${a_tag}") endforeach() - prepare_command_fragment(_labels_fragment + catch3_prepare_command_fragment(_labels_fragment PROPERTIES LABELS "${tag_list}" ) @@ -515,7 +515,7 @@ endfunction() # To enable `include`ing this file in the unit test scripts, we only run # the impl if an actual `TEST_EXECUTABLE` is provided. if(CMAKE_SCRIPT_MODE_FILE AND DEFINED TEST_EXECUTABLE) - catch_discover_tests_impl( + catch3_discover_tests_impl( TEST_EXECUTABLE ${TEST_EXECUTABLE} TEST_EXECUTOR ${TEST_EXECUTOR} TEST_WORKING_DIR ${TEST_WORKING_DIR} diff --git a/extras/CatchShardTests.cmake b/extras/Catch3ShardTests.cmake index 27f7c9f7..a7d651ef 100644 --- a/extras/CatchShardTests.cmake +++ b/extras/Catch3ShardTests.cmake @@ -10,7 +10,7 @@ # * SHARD_COUNT - number of shards to split target's tests into # * REPORTER - report options for the shards, such as --junit=FILE # * TEST_SPEC - test spec used for filtering tests -function(catch_add_sharded_tests TARGET) +function(catch3_add_sharded_tests TARGET) if(${CMAKE_VERSION} VERSION_LESS "3.10.0") message(FATAL_ERROR "add_sharded_catch_tests only supports CMake versions 3.10.0 and up") endif() @@ -46,7 +46,7 @@ function(catch_add_sharded_tests TARGET) APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}" ) - set(shard_impl_script_file "${_CATCH_DISCOVER_SHARD_TESTS_IMPL_SCRIPT}") + set(shard_impl_script_file "${_CATCH3_DISCOVER_SHARD_TESTS_IMPL_SCRIPT}") add_custom_command( TARGET ${TARGET} POST_BUILD @@ -66,7 +66,7 @@ endfunction() ############################################################################### -set(_CATCH_DISCOVER_SHARD_TESTS_IMPL_SCRIPT - ${CMAKE_CURRENT_LIST_DIR}/CatchShardTestsImpl.cmake - CACHE INTERNAL "Catch2 full path to CatchShardTestsImpl.cmake helper file" +set(_CATCH3_DISCOVER_SHARD_TESTS_IMPL_SCRIPT + ${CMAKE_CURRENT_LIST_DIR}/Catch3ShardTestsImpl.cmake + CACHE INTERNAL "Full path to the Catch3ShardTestsImpl.cmake helper file" ) diff --git a/extras/CatchShardTestsImpl.cmake b/extras/Catch3ShardTestsImpl.cmake index 99fd900a..99fd900a 100644 --- a/extras/CatchShardTestsImpl.cmake +++ b/extras/Catch3ShardTestsImpl.cmake diff --git a/extras/ParseAndAddCatchTests.cmake b/extras/ParseAndAddCatchTests.cmake deleted file mode 100644 index d7c17ace..00000000 --- a/extras/ParseAndAddCatchTests.cmake +++ /dev/null @@ -1,250 +0,0 @@ -#==================================================================================================# -# supported macros # -# - TEST_CASE, # -# - TEMPLATE_TEST_CASE # -# - SCENARIO, # -# - TEST_CASE_METHOD, # -# - CATCH_TEST_CASE, # -# - CATCH_TEMPLATE_TEST_CASE # -# - CATCH_SCENARIO, # -# - CATCH_TEST_CASE_METHOD. # -# # -# Usage # -# 1. make sure this module is in the path or add this otherwise: # -# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") # -# 2. make sure that you've enabled testing option for the project by the call: # -# enable_testing() # -# 3. add the lines to the script for testing target (sample CMakeLists.txt): # -# project(testing_target) # -# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") # -# enable_testing() # -# # -# find_path(CATCH_INCLUDE_DIR "catch.hpp") # -# include_directories(${INCLUDE_DIRECTORIES} ${CATCH_INCLUDE_DIR}) # -# # -# file(GLOB SOURCE_FILES "*.cpp") # -# add_executable(${PROJECT_NAME} ${SOURCE_FILES}) # -# # -# include(ParseAndAddCatchTests) # -# ParseAndAddCatchTests(${PROJECT_NAME}) # -# # -# The following variables affect the behavior of the script: # -# # -# PARSE_CATCH_TESTS_VERBOSE (Default OFF) # -# -- enables debug messages # -# PARSE_CATCH_TESTS_NO_HIDDEN_TESTS (Default OFF) # -# -- excludes tests marked with [!hide], [.] or [.foo] tags # -# PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME (Default ON) # -# -- adds fixture class name to the test name # -# PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) # -# -- adds cmake target name to the test name # -# PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) # -# -- causes CMake to rerun when file with tests changes so that new tests will be discovered # -# # -# One can also set (locally) the optional variable OptionalCatchTestLauncher to precise the way # -# a test should be run. For instance to use test MPI, one can write # -# set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC}) # -# just before calling this ParseAndAddCatchTests function # -# # -# The AdditionalCatchParameters optional variable can be used to pass extra argument to the test # -# command. For example, to include successful tests in the output, one can write # -# set(AdditionalCatchParameters --success) # -# # -# After the script, the ParseAndAddCatchTests_TESTS property for the target, and for each source # -# file in the target is set, and contains the list of the tests extracted from that target, or # -# from that file. This is useful, for example to add further labels or properties to the tests. # -# # -#==================================================================================================# - -if(CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.8) - message(FATAL_ERROR "ParseAndAddCatchTests requires CMake 2.8.8 or newer") -endif() - -option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OFF) -option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF) -option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON) -option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON) -option(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS "Add test file to CMAKE_CONFIGURE_DEPENDS property" OFF) - -function(ParseAndAddCatchTests_PrintDebugMessage) - if(PARSE_CATCH_TESTS_VERBOSE) - message(STATUS "ParseAndAddCatchTests: ${ARGV}") - endif() -endfunction() - -# This removes the contents between -# - block comments (i.e. /* ... */) -# - full line comments (i.e. // ... ) -# contents have been read into '${CppCode}'. -# !keep partial line comments -function(ParseAndAddCatchTests_RemoveComments CppCode) - string(ASCII 2 CMakeBeginBlockComment) - string(ASCII 3 CMakeEndBlockComment) - string(REGEX REPLACE "/\\*" "${CMakeBeginBlockComment}" ${CppCode} "${${CppCode}}") - string(REGEX REPLACE "\\*/" "${CMakeEndBlockComment}" ${CppCode} "${${CppCode}}") - string(REGEX REPLACE "${CMakeBeginBlockComment}[^${CMakeEndBlockComment}]*${CMakeEndBlockComment}" "" ${CppCode} "${${CppCode}}") - string(REGEX REPLACE "\n[ \t]*//+[^\n]+" "\n" ${CppCode} "${${CppCode}}") - - set(${CppCode} "${${CppCode}}" PARENT_SCOPE) -endfunction() - -# Worker function -function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget) - # If SourceFile is an object library, do not scan it (as it is not a file). Exit without giving a warning about a missing file. - if(SourceFile MATCHES "\\\$<TARGET_OBJECTS:.+>") - ParseAndAddCatchTests_PrintDebugMessage("Detected OBJECT library: ${SourceFile} this will not be scanned for tests.") - return() - endif() - # According to CMake docs EXISTS behavior is well-defined only for full paths. - get_filename_component(SourceFile ${SourceFile} ABSOLUTE) - if(NOT EXISTS ${SourceFile}) - message(WARNING "Cannot find source file: ${SourceFile}") - return() - endif() - ParseAndAddCatchTests_PrintDebugMessage("parsing ${SourceFile}") - file(STRINGS ${SourceFile} Contents NEWLINE_CONSUME) - - # Remove block and fullline comments - ParseAndAddCatchTests_RemoveComments(Contents) - - # Find definition of test names - # https://regex101.com/r/JygOND/1 - string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([ \t\n]*\"[^\"]*\"[ \t\n]*(,[ \t\n]*\"[^\"]*\")?(,[ \t\n]*[^\,\)]*)*\\)[ \t\n]*\{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}") - - if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests) - ParseAndAddCatchTests_PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property") - set_property( - DIRECTORY - APPEND - PROPERTY CMAKE_CONFIGURE_DEPENDS ${SourceFile} - ) - endif() - - # check CMP0110 policy for new add_test() behavior - if(POLICY CMP0110) - cmake_policy(GET CMP0110 _cmp0110_value) # new add_test() behavior - else() - # just to be thorough explicitly set the variable - set(_cmp0110_value) - endif() - - foreach(TestName ${Tests}) - # Strip newlines - string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}") - - # Get test type and fixture if applicable - string(REGEX MATCH "(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}") - string(REGEX MATCH "(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}") - string(REGEX REPLACE "${TestType}\\([ \t]*" "" TestFixture "${TestTypeAndFixture}") - - # Get string parts of test definition - string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}") - - # Strip wrapping quotation marks - string(REGEX REPLACE "^\"(.*)\"$" "\\1" TestStrings "${TestStrings}") - string(REPLACE "\";\"" ";" TestStrings "${TestStrings}") - - # Validate that a test name and tags have been provided - list(LENGTH TestStrings TestStringsLength) - if(TestStringsLength GREATER 2 OR TestStringsLength LESS 1) - message(FATAL_ERROR "You must provide a valid test name and tags for all tests in ${SourceFile}") - endif() - - # Assign name and tags - list(GET TestStrings 0 Name) - if("${TestType}" STREQUAL "SCENARIO") - set(Name "Scenario: ${Name}") - endif() - if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND "${TestType}" MATCHES "(CATCH_)?TEST_CASE_METHOD" AND TestFixture) - set(CTestName "${TestFixture}:${Name}") - else() - set(CTestName "${Name}") - endif() - if(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME) - set(CTestName "${TestTarget}:${CTestName}") - endif() - # add target to labels to enable running all tests added from this target - set(Labels ${TestTarget}) - if(TestStringsLength EQUAL 2) - list(GET TestStrings 1 Tags) - string(TOLOWER "${Tags}" Tags) - # remove target from labels if the test is hidden - if("${Tags}" MATCHES ".*\\[!?(hide|\\.)\\].*") - list(REMOVE_ITEM Labels ${TestTarget}) - endif() - string(REPLACE "]" ";" Tags "${Tags}") - string(REPLACE "[" "" Tags "${Tags}") - else() - # unset tags variable from previous loop - unset(Tags) - endif() - - list(APPEND Labels ${Tags}) - - set(HiddenTagFound OFF) - foreach(label ${Labels}) - string(REGEX MATCH "^!hide|^\\." result ${label}) - if(result) - set(HiddenTagFound ON) - break() - endif() - endforeach(label) - if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_LESS "3.9") - ParseAndAddCatchTests_PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label") - else() - ParseAndAddCatchTests_PrintDebugMessage("Adding test \"${CTestName}\"") - if(Labels) - ParseAndAddCatchTests_PrintDebugMessage("Setting labels to ${Labels}") - endif() - - # Escape commas in the test spec - string(REPLACE "," "\\," Name ${Name}) - - # Work around CMake 3.18.0 change in `add_test()`, before the escaped quotes were necessary, - # only with CMake 3.18.0 the escaped double quotes confuse the call. This change is reverted in 3.18.1 - # And properly introduced in 3.19 with the CMP0110 policy - if(_cmp0110_value STREQUAL "NEW" OR ${CMAKE_VERSION} VERSION_EQUAL "3.18") - ParseAndAddCatchTests_PrintDebugMessage("CMP0110 set to NEW, no need for add_test(\"\") workaround") - else() - ParseAndAddCatchTests_PrintDebugMessage("CMP0110 set to OLD adding \"\" for add_test() workaround") - set(CTestName "\"${CTestName}\"") - endif() - - # Handle template test cases - if("${TestTypeAndFixture}" MATCHES ".*TEMPLATE_.*") - set(Name "${Name} - *") - endif() - - # Add the test and set its properties - add_test(NAME "${CTestName}" COMMAND ${OptionalCatchTestLauncher} $<TARGET_FILE:${TestTarget}> ${Name} ${AdditionalCatchParameters}) - # Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead - if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8") - ParseAndAddCatchTests_PrintDebugMessage("Setting DISABLED test property") - set_tests_properties("${CTestName}" PROPERTIES DISABLED ON) - else() - set_tests_properties("${CTestName}" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran" - LABELS "${Labels}") - endif() - set_property( - TARGET ${TestTarget} - APPEND - PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}") - set_property( - SOURCE ${SourceFile} - APPEND - PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}") - endif() - endforeach() -endfunction() - -# entry point -function(ParseAndAddCatchTests TestTarget) - message(DEPRECATION "ParseAndAddCatchTest: function deprecated because of possibility of missed test cases. Consider using 'catch_discover_tests' from 'Catch.cmake'") - ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}") - get_target_property(SourceFiles ${TestTarget} SOURCES) - ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}") - foreach(SourceFile ${SourceFiles}) - ParseAndAddCatchTests_ParseFile(${SourceFile} ${TestTarget}) - endforeach() - ParseAndAddCatchTests_PrintDebugMessage("Finished parsing ${TestTarget}") -endfunction() diff --git a/extras/catch_amalgamated.cpp b/extras/catch_amalgamated.cpp index f5a8b781..0f336b53 100644 --- a/extras/catch_amalgamated.cpp +++ b/extras/catch_amalgamated.cpp @@ -7,7 +7,7 @@ // SPDX-License-Identifier: BSL-1.0 // Catch3 v0.3.0, on the Catch2 v3.16.1 engine -// Generated: 2026-10-24 19:06:40.031209 +// Generated: 2026-10-25 02:37:10.065190 // ---------------------------------------------------------- // This file is an amalgamation of multiple different files. // You probably shouldn't edit it directly. @@ -20,8 +20,6 @@ #include "catch_amalgamated.hpp" -#ifndef CATCH_WINDOWS_H_PROXY_HPP_INCLUDED -#define CATCH_WINDOWS_H_PROXY_HPP_INCLUDED #if defined(CATCH_PLATFORM_WINDOWS) @@ -39,7 +37,6 @@ #endif // defined(CATCH_PLATFORM_WINDOWS) -#endif // CATCH_WINDOWS_H_PROXY_HPP_INCLUDED // Copyright (c) 2026 Progmasoft. // SPDX-License-Identifier: MPL-2.0 WITH AdditionRef-Progmasoft-Exception-1.1 @@ -2160,6 +2157,180 @@ namespace Progmasoft::Catch3 +#include <cmath> +#include <limits> + +namespace { + +// Performs equivalent check of std::fabs(lhs - rhs) <= margin +// But without the subtraction to allow for INFINITY in comparison +bool marginComparison(double lhs, double rhs, double margin) { + return (lhs + margin >= rhs) && (rhs + margin >= lhs); +} + +} + +namespace Catch { + + Approx::Approx ( double value ) + : m_epsilon( static_cast<double>(std::numeric_limits<float>::epsilon())*100. ), + m_margin( 0.0 ), + m_scale( 0.0 ), + m_value( value ) + {} + + Approx Approx::custom() { + return Approx( 0 ); + } + + Approx Approx::operator-() const { + auto temp(*this); + temp.m_value = -temp.m_value; + return temp; + } + + + std::string Approx::toString() const { + ReusableStringStream rss; + rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )"; + return rss.str(); + } + + bool Approx:: |