1# Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2# file Copyright.txt or https://cmake.org/licensing for details. 3 4cmake_minimum_required(VERSION ${CMAKE_VERSION}) 5 6# Overwrite possibly existing ${_CTEST_FILE} with empty file 7set(flush_tests_MODE WRITE) 8 9# Flushes script to ${_CTEST_FILE} 10macro(flush_script) 11 file(${flush_tests_MODE} "${_CTEST_FILE}" "${script}") 12 set(flush_tests_MODE APPEND) 13 14 set(script "") 15endmacro() 16 17# Flushes tests_buffer to tests 18macro(flush_tests_buffer) 19 list(APPEND tests "${tests_buffer}") 20 set(tests_buffer "") 21endmacro() 22 23macro(add_command NAME) 24 set(_args "") 25 foreach(_arg ${ARGN}) 26 if(_arg MATCHES "[^-./:a-zA-Z0-9_]") 27 string(APPEND _args " [==[${_arg}]==]") 28 else() 29 string(APPEND _args " ${_arg}") 30 endif() 31 endforeach() 32 string(APPEND script "${NAME}(${_args})\n") 33 string(LENGTH "${script}" _script_len) 34 if(${_script_len} GREATER "50000") 35 flush_script() 36 endif() 37 # Unsets macro local variables to prevent leakage outside of this macro. 38 unset(_args) 39 unset(_script_len) 40endmacro() 41 42function(gtest_discover_tests_impl) 43 44 cmake_parse_arguments( 45 "" 46 "" 47 "NO_PRETTY_TYPES;NO_PRETTY_VALUES;TEST_EXECUTABLE;TEST_WORKING_DIR;TEST_PREFIX;TEST_SUFFIX;TEST_LIST;CTEST_FILE;TEST_DISCOVERY_TIMEOUT;TEST_XML_OUTPUT_DIR;TEST_FILTER" 48 "TEST_EXTRA_ARGS;TEST_PROPERTIES;TEST_EXECUTOR" 49 ${ARGN} 50 ) 51 52 set(prefix "${_TEST_PREFIX}") 53 set(suffix "${_TEST_SUFFIX}") 54 set(extra_args ${_TEST_EXTRA_ARGS}) 55 set(properties ${_TEST_PROPERTIES}) 56 set(script) 57 set(suite) 58 set(tests) 59 set(tests_buffer) 60 61 if(_TEST_FILTER) 62 set(filter "--gtest_filter=${_TEST_FILTER}") 63 else() 64 set(filter) 65 endif() 66 67 # Run test executable to get list of available tests 68 if(NOT EXISTS "${_TEST_EXECUTABLE}") 69 message(FATAL_ERROR 70 "Specified test executable does not exist.\n" 71 " Path: '${_TEST_EXECUTABLE}'" 72 ) 73 endif() 74 execute_process( 75 COMMAND ${_TEST_EXECUTOR} "${_TEST_EXECUTABLE}" --gtest_list_tests ${filter} 76 WORKING_DIRECTORY "${_TEST_WORKING_DIR}" 77 TIMEOUT ${_TEST_DISCOVERY_TIMEOUT} 78 OUTPUT_VARIABLE output 79 RESULT_VARIABLE result 80 ) 81 if(NOT ${result} EQUAL 0) 82 string(REPLACE "\n" "\n " output "${output}") 83 message(FATAL_ERROR 84 "Error running test executable.\n" 85 " Path: '${_TEST_EXECUTABLE}'\n" 86 " Result: ${result}\n" 87 " Output:\n" 88 " ${output}\n" 89 ) 90 endif() 91 92 # Preserve semicolon in test-parameters 93 string(REPLACE [[;]] [[\;]] output "${output}") 94 string(REPLACE "\n" ";" output "${output}") 95 96 # Parse output 97 foreach(line ${output}) 98 # Skip header 99 if(NOT line MATCHES "gtest_main\\.cc") 100 # Do we have a module name or a test name? 101 if(NOT line MATCHES "^ ") 102 # Module; remove trailing '.' to get just the name... 103 string(REGEX REPLACE "\\.( *#.*)?" "" suite "${line}") 104 if(line MATCHES "#" AND NOT _NO_PRETTY_TYPES) 105 string(REGEX REPLACE "/[0-9]\\.+ +#.*= +" "/" pretty_suite "${line}") 106 else() 107 set(pretty_suite "${suite}") 108 endif() 109 string(REGEX REPLACE "^DISABLED_" "" pretty_suite "${pretty_suite}") 110 else() 111 # Test name; strip spaces and comments to get just the name... 112 string(REGEX REPLACE " +" "" test "${line}") 113 if(test MATCHES "#" AND NOT _NO_PRETTY_VALUES) 114 string(REGEX REPLACE "/[0-9]+#GetParam..=" "/" pretty_test "${test}") 115 else() 116 string(REGEX REPLACE "#.*" "" pretty_test "${test}") 117 endif() 118 string(REGEX REPLACE "^DISABLED_" "" pretty_test "${pretty_test}") 119 string(REGEX REPLACE "#.*" "" test "${test}") 120 if(NOT "${_TEST_XML_OUTPUT_DIR}" STREQUAL "") 121 set(TEST_XML_OUTPUT_PARAM "--gtest_output=xml:${_TEST_XML_OUTPUT_DIR}/${prefix}${suite}.${test}${suffix}.xml") 122 else() 123 unset(TEST_XML_OUTPUT_PARAM) 124 endif() 125 126 # sanitize test name for further processing downstream 127 set(testname "${prefix}${pretty_suite}.${pretty_test}${suffix}") 128 # escape \ 129 string(REPLACE [[\]] [[\\]] testname "${testname}") 130 # escape ; 131 string(REPLACE [[;]] [[\;]] testname "${testname}") 132 # escape $ 133 string(REPLACE [[$]] [[\$]] testname "${testname}") 134 135 # ...and add to script 136 add_command(add_test 137 "${testname}" 138 ${_TEST_EXECUTOR} 139 "${_TEST_EXECUTABLE}" 140 "--gtest_filter=${suite}.${test}" 141 "--gtest_also_run_disabled_tests" 142 ${TEST_XML_OUTPUT_PARAM} 143 ${extra_args} 144 ) 145 if(suite MATCHES "^DISABLED_" OR test MATCHES "^DISABLED_") 146 add_command(set_tests_properties 147 "${testname}" 148 PROPERTIES DISABLED TRUE 149 ) 150 endif() 151 add_command(set_tests_properties 152 "${testname}" 153 PROPERTIES 154 WORKING_DIRECTORY "${_TEST_WORKING_DIR}" 155 SKIP_REGULAR_EXPRESSION "\\\\[ SKIPPED \\\\]" 156 ${properties} 157 ) 158 list(APPEND tests_buffer "${testname}") 159 list(LENGTH tests_buffer tests_buffer_length) 160 if(${tests_buffer_length} GREATER "250") 161 flush_tests_buffer() 162 endif() 163 endif() 164 endif() 165 endforeach() 166 167 168 # Create a list of all discovered tests, which users may use to e.g. set 169 # properties on the tests 170 flush_tests_buffer() 171 add_command(set ${_TEST_LIST} ${tests}) 172 173 # Write CTest script 174 flush_script() 175 176endfunction() 177 178if(CMAKE_SCRIPT_MODE_FILE) 179 gtest_discover_tests_impl( 180 NO_PRETTY_TYPES ${NO_PRETTY_TYPES} 181 NO_PRETTY_VALUES ${NO_PRETTY_VALUES} 182 TEST_EXECUTABLE ${TEST_EXECUTABLE} 183 TEST_EXECUTOR ${TEST_EXECUTOR} 184 TEST_WORKING_DIR ${TEST_WORKING_DIR} 185 TEST_PREFIX ${TEST_PREFIX} 186 TEST_SUFFIX ${TEST_SUFFIX} 187 TEST_FILTER ${TEST_FILTER} 188 TEST_LIST ${TEST_LIST} 189 CTEST_FILE ${CTEST_FILE} 190 TEST_DISCOVERY_TIMEOUT ${TEST_DISCOVERY_TIMEOUT} 191 TEST_XML_OUTPUT_DIR ${TEST_XML_OUTPUT_DIR} 192 TEST_EXTRA_ARGS ${TEST_EXTRA_ARGS} 193 TEST_PROPERTIES ${TEST_PROPERTIES} 194 ) 195endif() 196