| # Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| # file Copyright.txt or https://cmake.org/licensing for details. |
| |
| #[=======================================================================[.rst: |
| GoogleTest |
| ---------- |
| |
| .. versionadded:: 3.9 |
| |
| This module defines functions to help use the Google Test infrastructure. Two |
| mechanisms for adding tests are provided. :command:`gtest_add_tests` has been |
| around for some time, originally via ``find_package(GTest)``. |
| :command:`gtest_discover_tests` was introduced in CMake 3.10. |
| |
| The (older) :command:`gtest_add_tests` scans source files to identify tests. |
| This is usually effective, with some caveats, including in cross-compiling |
| environments, and makes setting additional properties on tests more convenient. |
| However, its handling of parameterized tests is less comprehensive, and it |
| requires re-running CMake to detect changes to the list of tests. |
| |
| The (newer) :command:`gtest_discover_tests` discovers tests by asking the |
| compiled test executable to enumerate its tests. This is more robust and |
| provides better handling of parameterized tests, and does not require CMake |
| to be re-run when tests change. However, it may not work in a cross-compiling |
| environment, and setting test properties is less convenient. |
| |
| More details can be found in the documentation of the respective functions. |
| |
| Both commands are intended to replace use of :command:`add_test` to register |
| tests, and will create a separate CTest test for each Google Test test case. |
| Note that this is in some cases less efficient, as common set-up and tear-down |
| logic cannot be shared by multiple test cases executing in the same instance. |
| However, it provides more fine-grained pass/fail information to CTest, which is |
| usually considered as more beneficial. By default, the CTest test name is the |
| same as the Google Test name (i.e. ``suite.testcase``); see also |
| ``TEST_PREFIX`` and ``TEST_SUFFIX``. |
| |
| .. command:: gtest_add_tests |
| |
| Automatically add tests with CTest by scanning source code for Google Test |
| macros:: |
| |
| gtest_add_tests(TARGET target |
| [SOURCES src1...] |
| [EXTRA_ARGS args...] |
| [WORKING_DIRECTORY dir] |
| [TEST_PREFIX prefix] |
| [TEST_SUFFIX suffix] |
| [SKIP_DEPENDENCY] |
| [TEST_LIST outVar] |
| ) |
| |
| ``gtest_add_tests`` attempts to identify tests by scanning source files. |
| Although this is generally effective, it uses only a basic regular expression |
| match, which can be defeated by atypical test declarations, and is unable to |
| fully "split" parameterized tests. Additionally, it requires that CMake be |
| re-run to discover any newly added, removed or renamed tests (by default, |
| this means that CMake is re-run when any test source file is changed, but see |
| ``SKIP_DEPENDENCY``). However, it has the advantage of declaring tests at |
| CMake time, which somewhat simplifies setting additional properties on tests, |
| and always works in a cross-compiling environment. |
| |
| The options are: |
| |
| ``TARGET target`` |
| Specifies the Google Test executable, which must be a known CMake |
| executable target. CMake will substitute the location of the built |
| executable when running the test. |
| |
| ``SOURCES src1...`` |
| When provided, only the listed files will be scanned for test cases. If |
| this option is not given, the :prop_tgt:`SOURCES` property of the |
| specified ``target`` will be used to obtain the list of sources. |
| |
| ``EXTRA_ARGS args...`` |
| Any extra arguments to pass on the command line to each test case. |
| |
| .. versionchanged:: 3.31 |
| Empty values in ``args...`` are preserved, see :policy:`CMP0178`. |
| |
| ``WORKING_DIRECTORY dir`` |
| Specifies the directory in which to run the discovered test cases. If this |
| option is not provided, the current binary directory is used. |
| |
| ``TEST_PREFIX prefix`` |
| Specifies a ``prefix`` to be prepended to the name of each discovered test |
| case. This can be useful when the same source files are being used in |
| multiple calls to ``gtest_add_test()`` but with different ``EXTRA_ARGS``. |
| |
| ``TEST_SUFFIX suffix`` |
| Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of |
| every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may |
| be specified. |
| |
| ``SKIP_DEPENDENCY`` |
| Normally, the function creates a dependency which will cause CMake to be |
| re-run if any of the sources being scanned are changed. This is to ensure |
| that the list of discovered tests is updated. If this behavior is not |
| desired (as may be the case while actually writing the test cases), this |
| option can be used to prevent the dependency from being added. |
| |
| ``TEST_LIST outVar`` |
| The variable named by ``outVar`` will be populated in the calling scope |
| with the list of discovered test cases. This allows the caller to do |
| things like manipulate test properties of the discovered tests. |
| |
| .. versionchanged:: 3.31 |
| Empty values in the :prop_tgt:`TEST_LAUNCHER` and |
| :prop_tgt:`CROSSCOMPILING_EMULATOR` target properties are preserved, |
| see policy :policy:`CMP0178`. |
| |
| Usage example: |
| |
| .. code-block:: cmake |
| |
| include(GoogleTest) |
| add_executable(FooTest FooUnitTest.cxx) |
| gtest_add_tests(TARGET FooTest |
| TEST_SUFFIX .noArgs |
| TEST_LIST noArgsTests |
| ) |
| gtest_add_tests(TARGET FooTest |
| EXTRA_ARGS --someArg someValue |
| TEST_SUFFIX .withArgs |
| TEST_LIST withArgsTests |
| ) |
| set_tests_properties(${noArgsTests} PROPERTIES TIMEOUT 10) |
| set_tests_properties(${withArgsTests} PROPERTIES TIMEOUT 20) |
| |
| For backward compatibility, the following form is also supported:: |
| |
| gtest_add_tests(exe args files...) |
| |
| ``exe`` |
| The path to the test executable or the name of a CMake target. |
| ``args`` |
| A ;-list of extra arguments to be passed to executable. The entire |
| list must be passed as a single argument. Enclose it in quotes, |
| or pass ``""`` for no arguments. |
| ``files...`` |
| A list of source files to search for tests and test fixtures. |
| Alternatively, use ``AUTO`` to specify that ``exe`` is the name |
| of a CMake executable target whose sources should be scanned. |
| |
| .. code-block:: cmake |
| |
| include(GoogleTest) |
| set(FooTestArgs --foo 1 --bar 2) |
| add_executable(FooTest FooUnitTest.cxx) |
| gtest_add_tests(FooTest "${FooTestArgs}" AUTO) |
| |
| .. command:: gtest_discover_tests |
| |
| Automatically add tests with CTest by querying the compiled test executable |
| for available tests:: |
| |
| gtest_discover_tests(target |
| [EXTRA_ARGS args...] |
| [WORKING_DIRECTORY dir] |
| [TEST_PREFIX prefix] |
| [TEST_SUFFIX suffix] |
| [TEST_FILTER expr] |
| [NO_PRETTY_TYPES] [NO_PRETTY_VALUES] |
| [PROPERTIES name1 value1...] |
| [TEST_LIST var] |
| [DISCOVERY_TIMEOUT seconds] |
| [XML_OUTPUT_DIR dir] |
| [DISCOVERY_MODE <POST_BUILD|PRE_TEST>] |
| [DISCOVERY_EXTRA_ARGS args...] |
| ) |
| |
| .. versionadded:: 3.10 |
| |
| ``gtest_discover_tests()`` sets up a post-build or pre-test command on the |
| test executable that generates the list of tests by parsing the output from |
| running the test executable with the ``--gtest_list_tests`` argument. |
| Compared to the source parsing approach of :command:`gtest_add_tests`, |
| this ensures that the full list of tests, including instantiations of |
| parameterized tests, is obtained. Since test discovery occurs at build |
| or test time, it is not necessary to re-run CMake when the list of tests |
| changes. However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` |
| is properly set in order to function in a cross-compiling environment. |
| |
| Additionally, setting properties on tests is somewhat less convenient, since |
| the tests are not available at CMake time. Additional test properties may be |
| assigned to the set of tests as a whole using the ``PROPERTIES`` option. If |
| more fine-grained test control is needed, custom content may be provided |
| through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES` |
| directory property. The set of discovered tests is made accessible to such a |
| script via the ``<target>_TESTS`` variable (see the ``TEST_LIST`` option |
| below for further discussion and limitations). |
| |
| The options are: |
| |
| ``target`` |
| Specifies the Google Test executable, which must be a known CMake |
| executable target. CMake will substitute the location of the built |
| executable when running the test. |
| |
| ``EXTRA_ARGS args...`` |
| Any extra arguments to pass on the command line to each test case. |
| |
| .. versionchanged:: 3.31 |
| Empty values in ``args...`` are preserved, see :policy:`CMP0178`. |
| |
| ``WORKING_DIRECTORY dir`` |
| Specifies the directory in which to run the discovered test cases. If this |
| option is not provided, the current binary directory is used. |
| |
| ``TEST_PREFIX prefix`` |
| Specifies a ``prefix`` to be prepended to the name of each discovered test |
| case. This can be useful when the same test executable is being used in |
| multiple calls to ``gtest_discover_tests()`` but with different |
| ``EXTRA_ARGS``. |
| |
| ``TEST_SUFFIX suffix`` |
| Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of |
| every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may |
| be specified. |
| |
| ``TEST_FILTER expr`` |
| .. versionadded:: 3.22 |
| |
| Filter expression to pass as a ``--gtest_filter`` argument during test |
| discovery. Note that the expression is a wildcard-based format that |
| matches against the original test names as used by gtest. For type or |
| value-parameterized tests, these names may be different to the potentially |
| pretty-printed test names that :program:`ctest` uses. |
| |
| ``NO_PRETTY_TYPES`` |
| By default, the type index of type-parameterized tests is replaced by the |
| actual type name in the CTest test name. If this behavior is undesirable |
| (e.g. because the type names are unwieldy), this option will suppress this |
| behavior. |
| |
| ``NO_PRETTY_VALUES`` |
| By default, the value index of value-parameterized tests is replaced by the |
| actual value in the CTest test name. If this behavior is undesirable |
| (e.g. because the value strings are unwieldy), this option will suppress |
| this behavior. |
| |
| ``PROPERTIES name1 value1...`` |
| Specifies additional properties to be set on all tests discovered by this |
| invocation of ``gtest_discover_tests()``. |
| |
| ``TEST_LIST var`` |
| Make the list of tests available in the variable ``var``, rather than the |
| default ``<target>_TESTS``. This can be useful when the same test |
| executable is being used in multiple calls to ``gtest_discover_tests()``. |
| Note that this variable is only available in CTest. |
| |
| Due to a limitation of CMake's parsing rules, any test with a square |
| bracket in its name will be omitted from the list of tests stored in |
| this variable. Such tests will still be defined and executed by |
| ``ctest`` as normal though. |
| |
| ``DISCOVERY_TIMEOUT num`` |
| .. versionadded:: 3.10.3 |
| |
| Specifies how long (in seconds) CMake will wait for the test to enumerate |
| available tests. If the test takes longer than this, discovery (and your |
| build) will fail. Most test executables will enumerate their tests very |
| quickly, but under some exceptional circumstances, a test may require a |
| longer timeout. The default is 5. See also the ``TIMEOUT`` option of |
| :command:`execute_process`. |
| |
| .. note:: |
| |
| In CMake versions 3.10.1 and 3.10.2, this option was called ``TIMEOUT``. |
| This clashed with the ``TIMEOUT`` test property, which is one of the |
| common properties that would be set with the ``PROPERTIES`` keyword, |
| usually leading to legal but unintended behavior. The keyword was |
| changed to ``DISCOVERY_TIMEOUT`` in CMake 3.10.3 to address this |
| problem. The ambiguous behavior of the ``TIMEOUT`` keyword in 3.10.1 |
| and 3.10.2 has not been preserved. |
| |
| ``XML_OUTPUT_DIR dir`` |
| .. versionadded:: 3.18 |
| |
| If specified, the parameter is passed along with ``--gtest_output=xml:`` |
| to test executable. The actual file name is the same as the test target, |
| including prefix and suffix. This should be used instead of |
| ``EXTRA_ARGS --gtest_output=xml`` to avoid race conditions writing the |
| XML result output when using parallel test execution. |
| |
| ``DISCOVERY_MODE`` |
| .. versionadded:: 3.18 |
| |
| Provides greater control over when ``gtest_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_GTEST_DISCOVER_TESTS_DISCOVERY_MODE`` variable if it is not |
| passed when calling ``gtest_discover_tests()``. This provides a mechanism |
| for globally selecting a preferred test discovery behavior without having |
| to modify each call site. |
| |
| ``DISCOVERY_EXTRA_ARGS args...`` |
| .. versionadded:: 3.31 |
| |
| Any extra arguments to pass on the command line for the discovery command. |
| |
| .. versionadded:: 3.29 |
| The :prop_tgt:`TEST_LAUNCHER` target property is honored during test |
| discovery and test execution. |
| |
| .. versionchanged:: 3.31 |
| Empty values in the :prop_tgt:`TEST_LAUNCHER` and |
| :prop_tgt:`CROSSCOMPILING_EMULATOR` target properties are preserved, |
| see policy :policy:`CMP0178`. |
| |
| #]=======================================================================] |
| |
| # Save project's policies |
| block(SCOPE_FOR POLICIES) |
| cmake_policy(VERSION 3.30) |
| |
| #------------------------------------------------------------------------------ |
| function(gtest_add_tests) |
| |
| if (ARGC LESS 1) |
| message(FATAL_ERROR "No arguments supplied to gtest_add_tests()") |
| endif() |
| |
| set(options |
| SKIP_DEPENDENCY |
| ) |
| set(oneValueArgs |
| TARGET |
| WORKING_DIRECTORY |
| TEST_PREFIX |
| TEST_SUFFIX |
| TEST_LIST |
| ) |
| set(multiValueArgs |
| SOURCES |
| EXTRA_ARGS |
| ) |
| set(allKeywords ${options} ${oneValueArgs} ${multiValueArgs}) |
| |
| cmake_policy(GET CMP0178 cmp0178 |
| PARENT_SCOPE # undocumented, do not use outside of CMake |
| ) |
| |
| unset(sources) |
| if("${ARGV0}" IN_LIST allKeywords) |
| if(cmp0178 STREQUAL "NEW") |
| cmake_parse_arguments(PARSE_ARGV 0 arg |
| "${options}" "${oneValueArgs}" "${multiValueArgs}" |
| ) |
| else() |
| cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) |
| if(NOT cmp0178 STREQUAL "OLD") |
| block(SCOPE_FOR VARIABLES) |
| cmake_parse_arguments(PARSE_ARGV 0 arg_new |
| "${options}" "${oneValueArgs}" "${multiValueArgs}" |
| ) |
| # Due to a quirk of cmake_parse_arguments(PARSE_ARGV), |
| # arg_new_EXTRA_ARGS will have semicolons already escaped, but |
| # arg_EXTRA_ARGS won't. We need to pass the former through one round |
| # of command argument parsing to de-escape them for comparison with |
| # the latter. |
| set(__newArgs ${arg_new_EXTRA_ARGS}) |
| if(NOT "${arg_EXTRA_ARGS}" STREQUAL "${__newArgs}") |
| cmake_policy(GET_WARNING CMP0178 cmp0178_warning) |
| message(AUTHOR_WARNING |
| "The EXTRA_ARGS contain one or more empty values. Those empty " |
| "values are being silently discarded to preserve backward " |
| "compatibility.\n" |
| "${cmp0178_warning}" |
| ) |
| endif() |
| endblock() |
| endif() |
| endif() |
| set(autoAddSources YES) |
| else() |
| # Non-keyword syntax, convert to keyword form |
| if (ARGC LESS 3) |
| message(FATAL_ERROR "gtest_add_tests() without keyword options requires at least 3 arguments") |
| endif() |
| set(arg_TARGET "${ARGV0}") |
| set(arg_EXTRA_ARGS "${ARGV1}") |
| if(NOT "${ARGV2}" STREQUAL "AUTO") |
| set(arg_SOURCES "${ARGV}") |
| list(REMOVE_AT arg_SOURCES 0 1) |
| endif() |
| endif() |
| |
| # The non-keyword syntax allows the first argument to be an arbitrary |
| # executable rather than a target if source files are also provided. In all |
| # other cases, both forms require a target. |
| if(NOT TARGET "${arg_TARGET}" AND NOT arg_SOURCES) |
| message(FATAL_ERROR "${arg_TARGET} does not define an existing CMake target") |
| endif() |
| if(NOT arg_WORKING_DIRECTORY) |
| unset(workDir) |
| else() |
| set(workDir WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}") |
| endif() |
| |
| if(NOT arg_SOURCES) |
| get_property(arg_SOURCES TARGET ${arg_TARGET} PROPERTY SOURCES) |
| endif() |
| |
| unset(testList) |
| |
| set(gtest_case_name_regex ".*\\([ \r\n\t]*([A-Za-z_0-9]+)[ \r\n\t]*,[ \r\n\t]*([A-Za-z_0-9]+)[ \r\n\t]*\\).*") |
| set(gtest_test_type_regex "(TYPED_TEST|TEST)_?[FP]?") |
| set(each_line_regex "([^\r\n]*[\r\n])") |
| |
| foreach(source IN LISTS arg_SOURCES) |
| if(NOT arg_SKIP_DEPENDENCY) |
| set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${source}) |
| endif() |
| file(READ "${source}" contents) |
| # Replace characters in file content that are special to CMake |
| string(REPLACE "[" "<OPEN_BRACKET>" contents "${contents}") |
| string(REPLACE "]" "<CLOSE_BRACKET>" contents "${contents}") |
| string(REPLACE ";" "\\;" contents "${contents}") |
| # Split into lines |
| string(REGEX MATCHALL "${each_line_regex}" content_lines "${contents}") |
| set(line "0") |
| # Stores the line number of the start of a test definition |
| set(accumulate_line "0") |
| # Stores accumulated lines to match multi-line test definitions |
| set(accumulated "") |
| # Iterate over each line in the file so that we know the line number of a test definition |
| foreach(line_str IN LISTS content_lines) |
| MATH(EXPR line "${line}+1") |
| # Check if the current line is the start of a test definition |
| string(REGEX MATCH "[ \t]*${gtest_test_type_regex}[ \t]*[\\(]*" accumlate_start_hit "${line_str}") |
| if(accumlate_start_hit) |
| set(accumulate_line "${line}") |
| endif() |
| # Append the current line to the accumulated string |
| set(accumulated "${accumulated}${line_str}") |
| # Attempt to match a complete test definition in the accumulated string |
| string(REGEX MATCH "${gtest_test_type_regex}[ \r\n\t]*\\(([A-Za-z_0-9 ,\r\n\t]+)\\)" hit "${accumulated}") |
| if(hit) |
| # Reset accumulated for the next match |
| set(accumulated "") |
| else() |
| # Continue accumulating lines |
| continue() |
| endif() |
| # At this point, the start line of the test definition is known |
| # Hence, we can set the test's DEF_SOURCE_LINE property with |
| # ${source}:${accumulate_line} below. |
| # VS Code CMake Tools extension looks for DEF_SOURCE_LINE |
| # to locate the test definition for its "Go to test" feature. |
| |
| string(REGEX MATCH "${gtest_test_type_regex}" test_type ${hit}) |
| |
| # Parameterized tests have a different signature for the filter |
| if("x${test_type}" STREQUAL "xTEST_P") |
| string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1.\\2/*" gtest_test_name ${hit}) |
| elseif("x${test_type}" STREQUAL "xTYPED_TEST_P") |
| string(REGEX REPLACE ${gtest_case_name_regex} "*/\\1/*.\\2" gtest_test_name ${hit}) |
| elseif("x${test_type}" STREQUAL "xTEST_F" OR "x${test_type}" STREQUAL "xTEST") |
| string(REGEX REPLACE ${gtest_case_name_regex} "\\1.\\2" gtest_test_name ${hit}) |
| elseif("x${test_type}" STREQUAL "xTYPED_TEST") |
| string(REGEX REPLACE ${gtest_case_name_regex} "\\1/*.\\2" gtest_test_name ${hit}) |
| else() |
| message(WARNING "Could not parse GTest ${hit} for adding to CTest.") |
| continue() |
| endif() |
| |
| set(extra_args "") |
| foreach(arg IN LISTS arg_EXTRA_ARGS) |
| string(APPEND extra_args " [==[${arg}]==]") |
| endforeach() |
| |
| # Make sure tests disabled in GTest get disabled in CTest |
| if(gtest_test_name MATCHES "(^|\\.)DISABLED_") |
| # Add the disabled test if CMake is new enough |
| # Note that this check is to allow backwards compatibility so this |
| # module can be copied locally in projects to use with older CMake |
| # versions |
| if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.8.20170401) |
| string(REGEX REPLACE |
| "(^|\\.)DISABLED_" "\\1" |
| orig_test_name "${gtest_test_name}" |
| ) |
| set(ctest_test_name |
| ${arg_TEST_PREFIX}${orig_test_name}${arg_TEST_SUFFIX} |
| ) |
| cmake_language(EVAL CODE " |
| add_test(NAME ${ctest_test_name} |
| ${workDir} |
| COMMAND ${arg_TARGET} |
| --gtest_also_run_disabled_tests |
| --gtest_filter=${gtest_test_name} |
| ${extra_args} |
| __CMP0178 [==[${cmp0178}]==] |
| )" |
| ) |
| set_tests_properties(${ctest_test_name} PROPERTIES DISABLED TRUE |
| DEF_SOURCE_LINE "${source}:${accumulate_line}") |
| list(APPEND testList ${ctest_test_name}) |
| endif() |
| else() |
| set(ctest_test_name ${arg_TEST_PREFIX}${gtest_test_name}${arg_TEST_SUFFIX}) |
| cmake_language(EVAL CODE " |
| add_test(NAME ${ctest_test_name} |
| ${workDir} |
| COMMAND ${arg_TARGET} |
| --gtest_filter=${gtest_test_name} |
| ${extra_args} |
| __CMP0178 [==[${cmp0178}]==] |
| )" |
| ) |
| # Makes sure a skipped GTest is reported as so by CTest |
| set_tests_properties( |
| ${ctest_test_name} |
| PROPERTIES |
| SKIP_REGULAR_EXPRESSION "\\[ SKIPPED \\]" |
| DEF_SOURCE_LINE "${source}:${accumulate_line}" |
| ) |
| list(APPEND testList ${ctest_test_name}) |
| endif() |
| endforeach() |
| endforeach() |
| |
| if(arg_TEST_LIST) |
| set(${arg_TEST_LIST} ${testList} PARENT_SCOPE) |
| endif() |
| |
| endfunction() |
| |
| #------------------------------------------------------------------------------ |
| |
| function(gtest_discover_tests target) |
| set(options |
| NO_PRETTY_TYPES |
| NO_PRETTY_VALUES |
| ) |
| set(oneValueArgs |
| TEST_PREFIX |
| TEST_SUFFIX |
| WORKING_DIRECTORY |
| TEST_LIST |
| DISCOVERY_TIMEOUT |
| XML_OUTPUT_DIR |
| DISCOVERY_MODE |
| ) |
| set(multiValueArgs |
| EXTRA_ARGS |
| DISCOVERY_EXTRA_ARGS |
| PROPERTIES |
| TEST_FILTER |
| ) |
| cmake_parse_arguments(PARSE_ARGV 1 arg |
| "${options}" "${oneValueArgs}" "${multiValueArgs}" |
| ) |
| |
| if(NOT arg_WORKING_DIRECTORY) |
| set(arg_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") |
| endif() |
| if(NOT arg_TEST_LIST) |
| set(arg_TEST_LIST ${target}_TESTS) |
| endif() |
| if(NOT arg_DISCOVERY_TIMEOUT) |
| set(arg_DISCOVERY_TIMEOUT 5) |
| endif() |
| if(NOT arg_DISCOVERY_MODE) |
| if(NOT CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE) |
| set(CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE "POST_BUILD") |
| endif() |
| set(arg_DISCOVERY_MODE ${CMAKE_GTEST_DISCOVER_TESTS_DISCOVERY_MODE}) |
| endif() |
| |
| get_property( |
| has_counter |
| TARGET ${target} |
| PROPERTY CTEST_DISCOVERED_TEST_COUNTER |
| SET |
| ) |
| if(has_counter) |
| get_property( |
| counter |
| TARGET ${target} |
| PROPERTY CTEST_DISCOVERED_TEST_COUNTER |
| ) |
| math(EXPR counter "${counter} + 1") |
| else() |
| set(counter 1) |
| endif() |
| set_property( |
| TARGET ${target} |
| PROPERTY CTEST_DISCOVERED_TEST_COUNTER |
| ${counter} |
| ) |
| |
| # Define rule to generate test list for aforementioned test executable |
| set(ctest_file_base "${CMAKE_CURRENT_BINARY_DIR}/${target}[${counter}]") |
| set(ctest_include_file "${ctest_file_base}_include.cmake") |
| set(ctest_tests_file "${ctest_file_base}_tests.cmake") |
| get_property(test_launcher |
| TARGET ${target} |
| PROPERTY TEST_LAUNCHER |
| ) |
| cmake_policy(GET CMP0158 _CMP0158 |
| PARENT_SCOPE # undocumented, do not use outside of CMake |
| ) |
| if(NOT _CMP0158 OR _CMP0158 STREQUAL "OLD" OR _CMP0158 STREQUAL "NEW" AND CMAKE_CROSSCOMPILING) |
| get_property(crosscompiling_emulator |
| TARGET ${target} |
| PROPERTY CROSSCOMPILING_EMULATOR |
| ) |
| endif() |
| |
| if(test_launcher AND crosscompiling_emulator) |
| set(test_executor "${test_launcher}" "${crosscompiling_emulator}") |
| elseif(test_launcher) |
| set(test_executor "${test_launcher}") |
| elseif(crosscompiling_emulator) |
| set(test_executor "${crosscompiling_emulator}") |
| else() |
| set(test_executor "") |
| endif() |
| |
| cmake_policy(GET CMP0178 cmp0178 |
| PARENT_SCOPE # undocumented, do not use outside of CMake |
| ) |
| if(NOT cmp0178 STREQUAL "NEW") |
| # Preserve old behavior where empty list items are silently discarded |
| set(test_executor_orig "${test_executor}") |
| set(test_executor ${test_executor}) |
| set(arg_EXTRA_ARGS_orig "${arg_EXTRA_ARGS}") |
| set(arg_EXTRA_ARGS ${arg_EXTRA_ARGS}) |
| if(NOT cmp0178 STREQUAL "OLD") |
| if(NOT "${test_executor}" STREQUAL "${test_executor_orig}") |
| cmake_policy(GET_WARNING CMP0178 cmp0178_warning) |
| message(AUTHOR_WARNING |
| "The '${target}' target's TEST_LAUNCHER or CROSSCOMPILING_EMULATOR " |
| "test properties contain one or more empty values. Those empty " |
| "values are being silently discarded to preserve backward " |
| "compatibility.\n" |
| "${cmp0178_warning}" |
| ) |
| endif() |
| if(NOT "${arg_EXTRA_ARGS}" STREQUAL "${arg_EXTRA_ARGS_orig}") |
| cmake_policy(GET_WARNING CMP0178 cmp0178_warning) |
| message(AUTHOR_WARNING |
| "The EXTRA_ARGS value contains one or more empty values. " |
| "Those empty values are being silently discarded to preserve " |
| "backward compatibility.\n" |
| "${cmp0178_warning}" |
| ) |
| endif() |
| endif() |
| endif() |
| |
| if(arg_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=$<TARGET_FILE:${target}>" |
| -D "TEST_EXECUTOR=${test_executor}" |
| -D "TEST_WORKING_DIR=${arg_WORKING_DIRECTORY}" |
| -D "TEST_EXTRA_ARGS=${arg_EXTRA_ARGS}" |
| -D "TEST_PROPERTIES=${arg_PROPERTIES}" |
| -D "TEST_PREFIX=${arg_TEST_PREFIX}" |
| -D "TEST_SUFFIX=${arg_TEST_SUFFIX}" |
| -D "TEST_FILTER=${arg_TEST_FILTER}" |
| -D "NO_PRETTY_TYPES=${arg_NO_PRETTY_TYPES}" |
| -D "NO_PRETTY_VALUES=${arg_NO_PRETTY_VALUES}" |
| -D "TEST_LIST=${arg_TEST_LIST}" |
| -D "CTEST_FILE=${ctest_tests_file}" |
| -D "TEST_DISCOVERY_TIMEOUT=${arg_DISCOVERY_TIMEOUT}" |
| -D "TEST_DISCOVERY_EXTRA_ARGS=${arg_DISCOVERY_EXTRA_ARGS}" |
| -D "TEST_XML_OUTPUT_DIR=${arg_XML_OUTPUT_DIR}" |
| -P "${CMAKE_ROOT}/Modules/GoogleTestAddTests.cmake" |
| VERBATIM |
| ) |
| |
| file(WRITE "${ctest_include_file}" |
| "if(EXISTS \"${ctest_tests_file}\")\n" |
| " include(\"${ctest_tests_file}\")\n" |
| "else()\n" |
| " add_test(${target}_NOT_BUILT ${target}_NOT_BUILT)\n" |
| "endif()\n" |
| ) |
| elseif(arg_DISCOVERY_MODE STREQUAL "PRE_TEST") |
| |
| get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL |
| PROPERTY GENERATOR_IS_MULTI_CONFIG |
| ) |
| |
| if(GENERATOR_IS_MULTI_CONFIG) |
| set(ctest_tests_file "${ctest_file_base}_tests-$<CONFIG>.cmake") |
| endif() |
| |
| string(CONCAT ctest_include_content |
| "if(EXISTS \"$<TARGET_FILE:${target}>\")" "\n" |
| " if(NOT EXISTS \"${ctest_tests_file}\" OR" "\n" |
| " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"$<TARGET_FILE:${target}>\" OR\n" |
| " NOT \"${ctest_tests_file}\" IS_NEWER_THAN \"\${CMAKE_CURRENT_LIST_FILE}\")\n" |
| " include(\"${CMAKE_ROOT}/Modules/GoogleTestAddTests.cmake\")" "\n" |
| " gtest_discover_tests_impl(" "\n" |
| " TEST_EXECUTABLE" " [==[$<TARGET_FILE:${target}>]==]" "\n" |
| " TEST_EXECUTOR" " [==[${test_executor}]==]" "\n" |
| " TEST_WORKING_DIR" " [==[${arg_WORKING_DIRECTORY}]==]" "\n" |
| " TEST_EXTRA_ARGS" " [==[${arg_EXTRA_ARGS}]==]" "\n" |
| " TEST_PROPERTIES" " [==[${arg_PROPERTIES}]==]" "\n" |
| " TEST_PREFIX" " [==[${arg_TEST_PREFIX}]==]" "\n" |
| " TEST_SUFFIX" " [==[${arg_TEST_SUFFIX}]==]" "\n" |
| " TEST_FILTER" " [==[${arg_TEST_FILTER}]==]" "\n" |
| " NO_PRETTY_TYPES" " [==[${arg_NO_PRETTY_TYPES}]==]" "\n" |
| " NO_PRETTY_VALUES" " [==[${arg_NO_PRETTY_VALUES}]==]" "\n" |
| " TEST_LIST" " [==[${arg_TEST_LIST}]==]" "\n" |
| " CTEST_FILE" " [==[${ctest_tests_file}]==]" "\n" |
| " TEST_DISCOVERY_TIMEOUT" " [==[${arg_DISCOVERY_TIMEOUT}]==]" "\n" |
| " TEST_DISCOVERY_EXTRA_ARGS [==[${arg_DISCOVERY_EXTRA_ARGS}]==]" "\n" |
| " TEST_XML_OUTPUT_DIR" " [==[${arg_XML_OUTPUT_DIR}]==]" "\n" |
| " )" "\n" |
| " endif()" "\n" |
| " include(\"${ctest_tests_file}\")" "\n" |
| "else()" "\n" |
| " add_test(${target}_NOT_BUILT ${target}_NOT_BUILT)" "\n" |
| "endif()" "\n" |
| ) |
| |
| if(GENERATOR_IS_MULTI_CONFIG) |
| foreach(_config ${CMAKE_CONFIGURATION_TYPES}) |
| file(GENERATE |
| OUTPUT "${ctest_file_base}_include-${_config}.cmake" |
| CONTENT "${ctest_include_content}" |
| CONDITION $<CONFIG:${_config}> |
| ) |
| endforeach() |
| file(WRITE "${ctest_include_file}" |
| "include(\"${ctest_file_base}_include-\${CTEST_CONFIGURATION_TYPE}.cmake\")" |
| ) |
| else() |
| file(GENERATE |
| OUTPUT "${ctest_file_base}_include.cmake" |
| CONTENT "${ctest_include_content}" |
| ) |
| file(WRITE "${ctest_include_file}" |
| "include(\"${ctest_file_base}_include.cmake\")" |
| ) |
| endif() |
| |
| else() |
| message(FATAL_ERROR "Unknown DISCOVERY_MODE: ${arg_DISCOVERY_MODE}") |
| endif() |
| |
| # Add discovered tests to directory TEST_INCLUDE_FILES |
| set_property(DIRECTORY |
| APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}" |
| ) |
| |
| endfunction() |
| |
| ############################################################################### |
| |
| # Restore project's policies |
| endblock() |