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.") diff --git a/CMake/CatchMiscFunctions.cmake b/CMake/CatchMiscFunctions.cmake index 3758d956..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" @@ -83,7 +84,7 @@ function(add_warnings_to_targets targets) "-Wundef" "-Wuninitialized" "-Wunneeded-internal-declaration" - "-Wunreachable-code" + "-Wunreachable-code-aggressive" "-Wunused" "-Wunused-function" "-Wunused-parameter" 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/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..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. @@ -143,7 +146,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/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/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/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() 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}") diff --git a/meson.build b/meson.build index 1faca35f..ed5033ac 100644 --- a/meson.build +++ b/meson.build @@ -10,8 +10,10 @@ 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') -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') 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/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 907773f2..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,26 +29,29 @@ 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; } - 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() { @@ -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 514ed1f7..ea483a30 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 @@ -21,117 +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 - sample resample(URng& rng, unsigned int resamples, std::vector::iterator first, std::vector::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); - 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()); - }); - 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::iterator first, std::vector::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 { @@ -161,6 +216,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); @@ -182,35 +278,10 @@ 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, 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 +289,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 +309,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..c1ce5664 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 { @@ -30,39 +28,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 +61,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); @@ -95,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()); @@ -128,15 +108,16 @@ 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; 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 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/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_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 af817017..f1ed5f9c 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 @@ -27,6 +27,7 @@ #include #include +#include #include #include 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/src/catch2/catch_test_spec.cpp b/src/catch2/catch_test_spec.cpp index 2a7fd563..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 @@ -107,16 +108,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/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_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/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/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_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_compiler_capabilities.hpp b/src/catch2/internal/catch_compiler_capabilities.hpp index 42631a5f..fc5d4f31 100644 --- a/src/catch2/internal/catch_compiler_capabilities.hpp +++ b/src/catch2/internal/catch_compiler_capabilities.hpp @@ -50,12 +50,18 @@ # 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\"" ) # 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 @@ -128,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__ @@ -365,6 +374,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 @@ -374,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... @@ -387,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)) 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. 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 { 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_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/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_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/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_run_context.cpp b/src/catch2/internal/catch_run_context.cpp index 6fd63450..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,19 +289,26 @@ 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(); 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( @@ -439,7 +446,7 @@ namespace Catch { tempResult.message = static_cast(message); AssertionResult result(m_lastAssertionInfo, CATCH_MOVE(tempResult)); - assertionEnded(result); + assertionEnded(CATCH_MOVE(result) ); handleUnfinishedSections(); @@ -561,8 +568,6 @@ namespace Catch { ITransientExpression const& expr, AssertionReaction& reaction ) { - m_reporter->assertionStarting( info ); - bool negated = isFalseTest( info.resultDisposition ); bool result = expr.getResult() != negated; @@ -591,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( @@ -600,16 +605,16 @@ namespace Catch { StringRef message, AssertionReaction& reaction ) { - m_reporter->assertionStarting( info ); - m_lastAssertionInfo = info; AssertionResultData data( resultType, LazyExpression( false ) ); 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 @@ -634,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 ); } @@ -652,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, @@ -663,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 fc65f651..c749304d 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; @@ -120,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, 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/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 ); 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_test_macro_impl.hpp b/src/catch2/internal/catch_test_macro_impl.hpp index e569680b..39366023 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) /////////////////////////////////////////////////////////////////////////////// @@ -95,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 \ @@ -115,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 \ @@ -141,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 \ 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/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', 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_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/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 ) << ':'; 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 ); +} 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 26d5e8f3..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 ------------------------------------------------------------------------------- @@ -13460,7 +13451,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 +13490,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 +13726,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 +13765,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 +14001,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 +14040,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: ............................................................................... @@ -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 80b63ab8..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 ------------------------------------------------------------------------------- @@ -13453,7 +13444,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 +13483,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 +13719,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 +13758,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 +13994,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 +14033,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: ............................................................................... @@ -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 25129349..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: @@ -1401,10 +1400,10 @@ at Exception.tests.cpp: - + - + @@ -1414,10 +1413,10 @@ at Exception.tests.cpp: - + - + @@ -1427,10 +1426,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..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: @@ -1400,10 +1399,10 @@ at Exception.tests.cpp: - + - + @@ -1413,10 +1412,10 @@ at Exception.tests.cpp: - + - + @@ -1426,10 +1425,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..eeb8d17b 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.approved.txt @@ -233,7 +233,6 @@ - @@ -1389,10 +1388,10 @@ at Matchers.tests.cpp: - + - + @@ -1402,10 +1401,10 @@ at Matchers.tests.cpp: - + - + @@ -1415,10 +1414,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..a804cb6b 100644 --- a/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt +++ b/tests/SelfTest/Baselines/sonarqube.sw.multi.approved.txt @@ -232,7 +232,6 @@ - @@ -1388,10 +1387,10 @@ at Matchers.tests.cpp: - + - + @@ -1401,10 +1400,10 @@ at Matchers.tests.cpp: - + - + @@ -1414,10 +1413,10 @@ at Matchers.tests.cpp: - + - + 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 d4d4858b..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 ) - - - - @@ -15670,7 +15659,7 @@ There is no extra whitespace here
-
+
data, !AllTrue() @@ -15712,7 +15701,7 @@ There is no extra whitespace here
-
+
data, !AllTrue() @@ -16020,7 +16009,7 @@ There is no extra whitespace here
-
+
data, AnyTrue() @@ -16062,7 +16051,7 @@ There is no extra whitespace here
-
+
data, AnyTrue() @@ -16370,7 +16359,7 @@ There is no extra whitespace here
-
+
data, !NoneTrue() @@ -16412,7 +16401,7 @@ There is no extra whitespace here
-
+
data, !NoneTrue() @@ -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 12229a99..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 ) - - - - @@ -15670,7 +15659,7 @@ There is no extra whitespace here
-
+
data, !AllTrue() @@ -15712,7 +15701,7 @@ There is no extra whitespace here
-
+
data, !AllTrue() @@ -16020,7 +16009,7 @@ There is no extra whitespace here
-
+
data, AnyTrue() @@ -16062,7 +16051,7 @@ There is no extra whitespace here
-
+
data, AnyTrue() @@ -16370,7 +16359,7 @@ There is no extra whitespace here
-
+
data, !NoneTrue() @@ -16412,7 +16401,7 @@ There is no extra whitespace here
-
+
data, !NoneTrue() @@ -21202,6 +21191,6 @@ b1!
- - + + 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]" ) { 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); } diff --git a/tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp b/tests/SelfTest/IntrospectiveTests/InternalBenchmark.tests.cpp index 96c0977b..24bfe68c 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: @@ -442,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 ); }; } 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'") ); } 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 { 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.