1##============================================================================ 2## Copyright (c) Kitware, Inc. 3## All rights reserved. 4## See LICENSE.txt for details. 5## 6## This software is distributed WITHOUT ANY WARRANTY; without even 7## the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 8## PURPOSE. See the above copyright notice for more information. 9##============================================================================ 10 11include(VTKmWrappers) 12 13function(vtkm_create_test_executable 14 prog_name 15 sources 16 libraries 17 defines 18 is_mpi_test 19 use_mpi 20 enable_all_backends 21 use_job_pool) 22 23 vtkm_diy_use_mpi_push() 24 25 set(prog ${prog_name}) 26 27 # for MPI tests, suffix test name and add MPI_Init/MPI_Finalize calls. 28 if (is_mpi_test) 29 set(extraArgs EXTRA_INCLUDE "vtkm/thirdparty/diy/environment.h") 30 31 if (use_mpi) 32 vtkm_diy_use_mpi(ON) 33 set(prog "${prog}_mpi") 34 else() 35 vtkm_diy_use_mpi(OFF) 36 set(prog "${prog}_nompi") 37 endif() 38 else() 39 set(CMAKE_TESTDRIVER_BEFORE_TESTMAIN "") 40 endif() 41 42 #the creation of the test source list needs to occur before the labeling as 43 #cuda. This is so that we get the correctly named entry points generated 44 create_test_sourcelist(test_sources ${prog}.cxx ${sources} ${extraArgs}) 45 46 add_executable(${prog} ${prog}.cxx ${sources}) 47 vtkm_add_drop_unused_function_flags(${prog}) 48 target_compile_definitions(${prog} PRIVATE ${defines}) 49 50 #determine if we have a device that requires a separate compiler enabled 51 set(device_lang_enabled FALSE) 52 if( (TARGET vtkm::cuda) OR (TARGET vtkm::kokkos_cuda) OR (TARGET vtkm::kokkos_hip)) 53 set(device_lang_enabled TRUE) 54 endif() 55 56 #if all backends are enabled, we can use the device compiler to handle all possible backends. 57 set(device_sources) 58 if(device_lang_enabled AND enable_all_backends) 59 set(device_sources ${sources}) 60 endif() 61 vtkm_add_target_information(${prog} DEVICE_SOURCES ${device_sources}) 62 63 if(NOT VTKm_USE_DEFAULT_SYMBOL_VISIBILITY) 64 set_property(TARGET ${prog} PROPERTY CUDA_VISIBILITY_PRESET "hidden") 65 set_property(TARGET ${prog} PROPERTY CXX_VISIBILITY_PRESET "hidden") 66 endif() 67 set_property(TARGET ${prog} PROPERTY ARCHIVE_OUTPUT_DIRECTORY ${VTKm_LIBRARY_OUTPUT_PATH}) 68 set_property(TARGET ${prog} PROPERTY LIBRARY_OUTPUT_DIRECTORY ${VTKm_LIBRARY_OUTPUT_PATH}) 69 set_property(TARGET ${prog} PROPERTY RUNTIME_OUTPUT_DIRECTORY ${VTKm_EXECUTABLE_OUTPUT_PATH}) 70 71 target_link_libraries(${prog} PRIVATE vtkm_cont_testing ${libraries}) 72 73 if(use_job_pool) 74 vtkm_setup_job_pool() 75 set_property(TARGET ${prog} PROPERTY JOB_POOL_COMPILE vtkm_pool) 76 endif() 77 78 vtkm_diy_use_mpi_pop() 79endfunction() 80 81#----------------------------------------------------------------------------- 82# Declare unit tests, which should be in the same directory as a kit 83# (package, module, whatever you call it). Usage: 84# 85# vtkm_unit_tests( 86# NAME 87# SOURCES <source_list> 88# LIBRARIES <dependent_library_list> 89# DEFINES <target_compile_definitions> 90# TEST_ARGS <argument_list> 91# MPI 92# ALL_BACKENDS 93# USE_VTKM_JOB_POOL 94# <options> 95# ) 96# 97# [LIBRARIES] : extra libraries that this set of tests need to link too 98# 99# [DEFINES] : extra defines that need to be set for all unit test sources 100# 101# [LABEL] : CTest Label to associate to this set of tests 102# 103# [TEST_ARGS] : arguments that should be passed on the command line to the 104# test executable 105# 106# [MPI] : when specified, the tests should be run in parallel if 107# MPI is enabled. The tests should also be able to build and run 108# When MPI is not available, i.e., they should not make explicit 109# use of MPI and instead completely rely on DIY. 110# [ALL_BACKENDS] : when specified, the tests would test against all enabled 111# backends. Otherwise we expect the tests to manage the 112# backends at runtime. 113# 114function(vtkm_unit_tests) 115 if (NOT VTKm_ENABLE_TESTING) 116 return() 117 endif() 118 119 set(options) 120 set(global_options ${options} USE_VTKM_JOB_POOL MPI ALL_BACKENDS) 121 set(oneValueArgs BACKEND NAME LABEL) 122 set(multiValueArgs SOURCES LIBRARIES DEFINES TEST_ARGS) 123 cmake_parse_arguments(VTKm_UT 124 "${global_options}" "${oneValueArgs}" "${multiValueArgs}" 125 ${ARGN} 126 ) 127 vtkm_parse_test_options(VTKm_UT_SOURCES "${options}" ${VTKm_UT_SOURCES}) 128 129 set(per_device_command_line_arguments "NONE") 130 set(per_device_suffix "") 131 set(per_device_timeout 180) 132 set(per_device_serial FALSE) 133 134 set(enable_all_backends ${VTKm_UT_ALL_BACKENDS}) 135 if(enable_all_backends) 136 set(per_device_command_line_arguments --device=serial) 137 set(per_device_suffix "SERIAL") 138 if (VTKm_ENABLE_CUDA) 139 list(APPEND per_device_command_line_arguments --device=cuda) 140 list(APPEND per_device_suffix "CUDA") 141 #CUDA tests generally require more time because of kernel generation. 142 list(APPEND per_device_timeout 1500) 143 list(APPEND per_device_serial FALSE) 144 endif() 145 if (VTKm_ENABLE_TBB) 146 list(APPEND per_device_command_line_arguments --device=tbb) 147 list(APPEND per_device_suffix "TBB") 148 list(APPEND per_device_timeout 180) 149 list(APPEND per_device_serial FALSE) 150 endif() 151 if (VTKm_ENABLE_OPENMP) 152 list(APPEND per_device_command_line_arguments --device=openmp) 153 list(APPEND per_device_suffix "OPENMP") 154 list(APPEND per_device_timeout 180) 155 #We need to have all OpenMP tests run serially as they 156 #will uses all the system cores, and we will cause a N*N thread 157 #explosion which causes the tests to run slower than when run 158 #serially 159 list(APPEND per_device_serial TRUE) 160 endif() 161 if (VTKm_ENABLE_KOKKOS) 162 list(APPEND per_device_command_line_arguments --device=kokkos) 163 list(APPEND per_device_suffix "KOKKOS") 164 #may require more time because of kernel generation. 165 list(APPEND per_device_timeout 1500) 166 list(APPEND per_device_serial FALSE) 167 endif() 168 endif() 169 170 set(test_prog) 171 if(VTKm_UT_NAME) 172 set(test_prog "${VTKm_UT_NAME}") 173 else() 174 vtkm_get_kit_name(kit) 175 set(test_prog "UnitTests_${kit}") 176 endif() 177 178 # For Testing Purposes, we will set the default logging level to INFO 179 list(APPEND vtkm_default_test_log_level "-v" "INFO") 180 181 # Add the path to the data directory so tests can find and use data files for testing 182 list(APPEND VTKm_UT_TEST_ARGS "--data-dir=${VTKm_SOURCE_DIR}/data/data") 183 184 # Add the path to the location where regression test images are to be stored 185 list(APPEND VTKm_UT_TEST_ARGS "--baseline-dir=${VTKm_SOURCE_DIR}/data/baseline") 186 187 # Add the path to the location where generated regression test images should be written 188 list(APPEND VTKm_UT_TEST_ARGS "--write-dir=${VTKm_BINARY_DIR}") 189 190 if(VTKm_UT_MPI) 191 if (VTKm_ENABLE_MPI) 192 vtkm_create_test_executable( 193 ${test_prog} 194 "${VTKm_UT_SOURCES}" 195 "${VTKm_UT_LIBRARIES}" 196 "${VTKm_UT_DEFINES}" 197 ON # is_mpi_test 198 ON # use_mpi 199 ${enable_all_backends} 200 ${VTKm_UT_USE_VTKM_JOB_POOL}) 201 endif() 202 if ((NOT VTKm_ENABLE_MPI) OR VTKm_ENABLE_DIY_NOMPI) 203 vtkm_create_test_executable( 204 ${test_prog} 205 "${VTKm_UT_SOURCES}" 206 "${VTKm_UT_LIBRARIES}" 207 "${VTKm_UT_DEFINES}" 208 ON # is_mpi_test 209 OFF # use_mpi 210 ${enable_all_backends} 211 ${VTKm_UT_USE_VTKM_JOB_POOL}) 212 endif() 213 else() 214 vtkm_create_test_executable( 215 ${test_prog} 216 "${VTKm_UT_SOURCES}" 217 "${VTKm_UT_LIBRARIES}" 218 "${VTKm_UT_DEFINES}" 219 OFF # is_mpi_test 220 OFF # use_mpi 221 ${enable_all_backends} 222 ${VTKm_UT_USE_VTKM_JOB_POOL}) 223 endif() 224 225 list(LENGTH per_device_command_line_arguments number_of_devices) 226 foreach(index RANGE ${number_of_devices}) 227 if(index EQUAL number_of_devices) 228 #RANGE is inclusive on both sides, and we want it to be 229 #exclusive on the end ( e.g. for(i=0; i < n; ++i)) 230 break() 231 endif() 232 if(per_device_command_line_arguments STREQUAL "NONE") 233 set(device_command_line_argument) 234 set(upper_backend ${per_device_suffix}) 235 set(timeout ${per_device_timeout}) 236 set(run_serial ${per_device_serial}) 237 else() 238 list(GET per_device_command_line_arguments ${index} device_command_line_argument) 239 list(GET per_device_suffix ${index} upper_backend) 240 list(GET per_device_timeout ${index} timeout) 241 list(GET per_device_serial ${index} run_serial) 242 endif() 243 244 foreach (test ${VTKm_UT_SOURCES}) 245 get_filename_component(tname ${test} NAME_WE) 246 if(VTKm_UT_MPI) 247 if (VTKm_ENABLE_MPI) 248 add_test(NAME ${tname}${upper_backend}_mpi 249 COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 3 ${MPIEXEC_PREFLAGS} 250 $<TARGET_FILE:${test_prog}_mpi> ${tname} ${device_command_line_argument} 251 ${vtkm_default_test_log_level} ${VTKm_UT_TEST_ARGS} ${MPIEXEC_POSTFLAGS} 252 ) 253 set_tests_properties("${tname}${upper_backend}_mpi" PROPERTIES 254 LABELS "${upper_backend};${VTKm_UT_LABEL}" 255 TIMEOUT ${timeout} 256 RUN_SERIAL ${run_serial} 257 FAIL_REGULAR_EXPRESSION "runtime error") 258 endif() # VTKm_ENABLE_MPI 259 if ((NOT VTKm_ENABLE_MPI) OR VTKm_ENABLE_DIY_NOMPI) 260 add_test(NAME ${tname}${upper_backend}_nompi 261 COMMAND ${test_prog}_nompi ${tname} ${device_command_line_argument} 262 ${vtkm_default_test_log_level} ${VTKm_UT_TEST_ARGS} 263 ) 264 set_tests_properties("${tname}${upper_backend}_nompi" PROPERTIES 265 LABELS "${upper_backend};${VTKm_UT_LABEL}" 266 TIMEOUT ${timeout} 267 RUN_SERIAL ${run_serial} 268 FAIL_REGULAR_EXPRESSION "runtime error") 269 270 endif() # VTKm_ENABLE_DIY_NOMPI 271 else() # VTKm_UT_MPI 272 add_test(NAME ${tname}${upper_backend} 273 COMMAND ${test_prog} ${tname} ${device_command_line_argument} 274 ${vtkm_default_test_log_level} ${VTKm_UT_TEST_ARGS} 275 ) 276 set_tests_properties("${tname}${upper_backend}" PROPERTIES 277 LABELS "${upper_backend};${VTKm_UT_LABEL}" 278 TIMEOUT ${timeout} 279 RUN_SERIAL ${run_serial} 280 FAIL_REGULAR_EXPRESSION "runtime error") 281 endif() # VTKm_UT_MPI 282 endforeach() 283 endforeach() 284 285endfunction(vtkm_unit_tests) 286 287# ----------------------------------------------------------------------------- 288# vtkm_parse_test_options(varname options) 289# INTERNAL: Parse options specified for individual tests. 290# 291# Parses the arguments to separate out options specified after the test name 292# separated by a comma e.g. 293# 294# TestName,Option1,Option2 295# 296# For every option in options, this will set _TestName_Option1, 297# _TestName_Option2, etc in the parent scope. 298# 299function(vtkm_parse_test_options varname options) 300 set(names) 301 foreach(arg IN LISTS ARGN) 302 set(test_name ${arg}) 303 set(test_options) 304 if(test_name AND "x${test_name}" MATCHES "^x([^,]*),(.*)$") 305 set(test_name "${CMAKE_MATCH_1}") 306 string(REPLACE "," ";" test_options "${CMAKE_MATCH_2}") 307 endif() 308 foreach(opt IN LISTS test_options) 309 list(FIND options "${opt}" index) 310 if(index EQUAL -1) 311 message(WARNING "Unknown option '${opt}' specified for test '${test_name}'") 312 else() 313 set(_${test_name}_${opt} TRUE PARENT_SCOPE) 314 endif() 315 endforeach() 316 list(APPEND names ${test_name}) 317 endforeach() 318 set(${varname} ${names} PARENT_SCOPE) 319endfunction() 320