1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[=======================================================================[.rst:
5CTest
6-----
7
8Configure a project for testing with CTest/CDash
9
10Include this module in the top CMakeLists.txt file of a project to
11enable testing with CTest and dashboard submissions to CDash::
12
13  project(MyProject)
14  ...
15  include(CTest)
16
17The module automatically creates a ``BUILD_TESTING`` option that selects
18whether to enable testing support (``ON`` by default).  After including
19the module, use code like::
20
21  if(BUILD_TESTING)
22    # ... CMake code to create tests ...
23  endif()
24
25to creating tests when testing is enabled.
26
27To enable submissions to a CDash server, create a ``CTestConfig.cmake``
28file at the top of the project with content such as::
29
30  set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
31  set(CTEST_SUBMIT_URL "http://my.cdash.org/submit.php?project=MyProject")
32
33(the CDash server can provide the file to a project administrator who
34configures ``MyProject``).  Settings in the config file are shared by
35both this ``CTest`` module and the :manual:`ctest(1)` command-line
36:ref:`Dashboard Client` mode (``ctest -S``).
37
38While building a project for submission to CDash, CTest scans the
39build output for errors and warnings and reports them with surrounding
40context from the build log.  This generic approach works for all build
41tools, but does not give details about the command invocation that
42produced a given problem.  One may get more detailed reports by setting
43the :variable:`CTEST_USE_LAUNCHERS` variable::
44
45  set(CTEST_USE_LAUNCHERS 1)
46
47in the ``CTestConfig.cmake`` file.
48#]=======================================================================]
49
50option(BUILD_TESTING "Build the testing tree." ON)
51
52# function to turn generator name into a version string
53# like vs9 or vs10
54function(GET_VS_VERSION_STRING generator var)
55  string(REGEX REPLACE "Visual Studio ([0-9][0-9]?)($|.*)" "\\1"
56    NUMBER "${generator}")
57    set(ver_string "vs${NUMBER}")
58  set(${var} ${ver_string} PARENT_SCOPE)
59endfunction()
60
61include(CTestUseLaunchers)
62
63if(BUILD_TESTING)
64  # Setup some auxiliary macros
65  macro(SET_IF_NOT_SET var val)
66    if(NOT DEFINED "${var}")
67      set("${var}" "${val}")
68    endif()
69  endmacro()
70
71  macro(SET_IF_SET var val)
72    if(NOT "${val}" STREQUAL "")
73      set("${var}" "${val}")
74    endif()
75  endmacro()
76
77  macro(SET_IF_SET_AND_NOT_SET var val)
78    if(NOT "${val}" STREQUAL "")
79      SET_IF_NOT_SET("${var}" "${val}")
80    endif()
81  endmacro()
82
83  # Make sure testing is enabled
84  enable_testing()
85
86  if(EXISTS "${PROJECT_SOURCE_DIR}/CTestConfig.cmake")
87    include("${PROJECT_SOURCE_DIR}/CTestConfig.cmake")
88    SET_IF_SET_AND_NOT_SET(NIGHTLY_START_TIME "${CTEST_NIGHTLY_START_TIME}")
89    SET_IF_SET_AND_NOT_SET(SUBMIT_URL "${CTEST_SUBMIT_URL}")
90    SET_IF_SET_AND_NOT_SET(DROP_METHOD "${CTEST_DROP_METHOD}")
91    SET_IF_SET_AND_NOT_SET(DROP_SITE "${CTEST_DROP_SITE}")
92    SET_IF_SET_AND_NOT_SET(DROP_SITE_USER "${CTEST_DROP_SITE_USER}")
93    SET_IF_SET_AND_NOT_SET(DROP_SITE_PASSWORD "${CTEST_DROP_SITE_PASWORD}")
94    SET_IF_SET_AND_NOT_SET(DROP_SITE_MODE "${CTEST_DROP_SITE_MODE}")
95    SET_IF_SET_AND_NOT_SET(DROP_LOCATION "${CTEST_DROP_LOCATION}")
96    SET_IF_SET_AND_NOT_SET(TRIGGER_SITE "${CTEST_TRIGGER_SITE}")
97    SET_IF_SET_AND_NOT_SET(UPDATE_TYPE "${CTEST_UPDATE_TYPE}")
98  endif()
99
100  # the project can have a DartConfig.cmake file
101  if(EXISTS "${PROJECT_SOURCE_DIR}/DartConfig.cmake")
102    include("${PROJECT_SOURCE_DIR}/DartConfig.cmake")
103  else()
104    # Dashboard is opened for submissions for a 24 hour period starting at
105    # the specified NIGHTLY_START_TIME. Time is specified in 24 hour format.
106    SET_IF_NOT_SET (NIGHTLY_START_TIME "00:00:00 EDT")
107    SET_IF_NOT_SET(DROP_METHOD "http")
108    SET_IF_NOT_SET (COMPRESS_SUBMISSION ON)
109  endif()
110  SET_IF_NOT_SET (NIGHTLY_START_TIME "00:00:00 EDT")
111
112  if(NOT SUBMIT_URL)
113    set(SUBMIT_URL "${DROP_METHOD}://")
114    if(DROP_SITE_USER)
115      string(APPEND SUBMIT_URL "${DROP_SITE_USER}")
116      if(DROP_SITE_PASSWORD)
117        string(APPEND SUBMIT_URL ":${DROP_SITE_PASSWORD}")
118      endif()
119      string(APPEND SUBMIT_URL "@")
120    endif()
121    string(APPEND SUBMIT_URL "${DROP_SITE}${DROP_LOCATION}")
122  endif()
123
124  if(NOT UPDATE_TYPE)
125    if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/CVS")
126      set(UPDATE_TYPE cvs)
127    elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.svn")
128      set(UPDATE_TYPE svn)
129    elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.bzr")
130      set(UPDATE_TYPE bzr)
131    elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.hg")
132      set(UPDATE_TYPE hg)
133    elseif(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/.git")
134      set(UPDATE_TYPE git)
135    endif()
136  endif()
137
138  string(TOLOWER "${UPDATE_TYPE}" _update_type)
139  if("${_update_type}" STREQUAL "cvs")
140    find_program(CVSCOMMAND cvs )
141    set(CVS_UPDATE_OPTIONS "-d -A -P" CACHE STRING
142      "Options passed to the cvs update command.")
143    set(UPDATE_COMMAND "${CVSCOMMAND}")
144    set(UPDATE_OPTIONS "${CVS_UPDATE_OPTIONS}")
145  elseif("${_update_type}" STREQUAL "svn")
146    find_program(SVNCOMMAND svn)
147    set(UPDATE_COMMAND "${SVNCOMMAND}")
148    set(UPDATE_OPTIONS "${SVN_UPDATE_OPTIONS}")
149  elseif("${_update_type}" STREQUAL "bzr")
150    find_program(BZRCOMMAND bzr)
151    set(UPDATE_COMMAND "${BZRCOMMAND}")
152    set(UPDATE_OPTIONS "${BZR_UPDATE_OPTIONS}")
153  elseif("${_update_type}" STREQUAL "hg")
154    find_program(HGCOMMAND hg)
155    set(UPDATE_COMMAND "${HGCOMMAND}")
156    set(UPDATE_OPTIONS "${HG_UPDATE_OPTIONS}")
157  elseif("${_update_type}" STREQUAL "git")
158    find_program(GITCOMMAND git)
159    set(UPDATE_COMMAND "${GITCOMMAND}")
160    set(UPDATE_OPTIONS "${GIT_UPDATE_OPTIONS}")
161  elseif("${_update_type}" STREQUAL "p4")
162    find_program(P4COMMAND p4)
163    set(UPDATE_COMMAND "${P4COMMAND}")
164    set(UPDATE_OPTIONS "${P4_UPDATE_OPTIONS}")
165  endif()
166
167  set(DART_TESTING_TIMEOUT 1500 CACHE STRING
168    "Maximum time allowed before CTest will kill the test.")
169
170  set(CTEST_SUBMIT_RETRY_DELAY 5 CACHE STRING
171    "How long to wait between timed-out CTest submissions.")
172  set(CTEST_SUBMIT_RETRY_COUNT 3 CACHE STRING
173    "How many times to retry timed-out CTest submissions.")
174
175  find_program(MEMORYCHECK_COMMAND
176    NAMES purify valgrind boundscheck drmemory cuda-memcheck compute-sanitizer
177    PATHS
178    "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Rational Software\\Purify\\Setup;InstallFolder]"
179    DOC "Path to the memory checking command, used for memory error detection."
180    )
181  set(MEMORYCHECK_SUPPRESSIONS_FILE "" CACHE FILEPATH
182    "File that contains suppressions for the memory checker")
183  find_program(COVERAGE_COMMAND gcov DOC
184    "Path to the coverage program that CTest uses for performing coverage inspection"
185    )
186  set(COVERAGE_EXTRA_FLAGS "-l" CACHE STRING
187    "Extra command line flags to pass to the coverage tool")
188
189  # set the site name
190  if(COMMAND cmake_host_system_information)
191    cmake_host_system_information(RESULT _ctest_hostname QUERY HOSTNAME)
192    set(SITE "${_ctest_hostname}" CACHE STRING "Name of the computer/site where compile is being run")
193    unset(_ctest_hostname)
194  else()
195    # This code path is needed for CMake itself during bootstrap.
196    site_name(SITE)
197  endif()
198  # set the build name
199  if(NOT BUILDNAME)
200    set(DART_COMPILER "${CMAKE_CXX_COMPILER}")
201    if(NOT DART_COMPILER)
202      set(DART_COMPILER "${CMAKE_C_COMPILER}")
203    endif()
204    if(NOT DART_COMPILER)
205      set(DART_COMPILER "unknown")
206    endif()
207    if(WIN32)
208      set(DART_NAME_COMPONENT "NAME_WE")
209    else()
210      set(DART_NAME_COMPONENT "NAME")
211    endif()
212    if(NOT BUILD_NAME_SYSTEM_NAME)
213      set(BUILD_NAME_SYSTEM_NAME "${CMAKE_SYSTEM_NAME}")
214    endif()
215    if(WIN32)
216      set(BUILD_NAME_SYSTEM_NAME "Win32")
217    endif()
218    if(UNIX OR BORLAND)
219      get_filename_component(DART_COMPILER_NAME
220        "${DART_COMPILER}" ${DART_NAME_COMPONENT})
221    else()
222      get_filename_component(DART_COMPILER_NAME
223        "${CMAKE_MAKE_PROGRAM}" ${DART_NAME_COMPONENT})
224    endif()
225    if(DART_COMPILER_NAME MATCHES "devenv")
226      GET_VS_VERSION_STRING("${CMAKE_GENERATOR}" DART_COMPILER_NAME)
227    endif()
228    set(BUILDNAME "${BUILD_NAME_SYSTEM_NAME}-${DART_COMPILER_NAME}")
229  endif()
230
231  # the build command
232  build_command(MAKECOMMAND_DEFAULT_VALUE
233    CONFIGURATION "\${CTEST_CONFIGURATION_TYPE}")
234  set(MAKECOMMAND ${MAKECOMMAND_DEFAULT_VALUE}
235    CACHE STRING "Command to build the project")
236
237  # the default build configuration the ctest build handler will use
238  # if there is no -C arg given to ctest:
239  set(DEFAULT_CTEST_CONFIGURATION_TYPE "$ENV{CMAKE_CONFIG_TYPE}")
240  if(DEFAULT_CTEST_CONFIGURATION_TYPE STREQUAL "")
241    set(DEFAULT_CTEST_CONFIGURATION_TYPE "Release")
242  endif()
243
244  mark_as_advanced(
245    BZRCOMMAND
246    COVERAGE_COMMAND
247    COVERAGE_EXTRA_FLAGS
248    CTEST_SUBMIT_RETRY_DELAY
249    CTEST_SUBMIT_RETRY_COUNT
250    CVSCOMMAND
251    CVS_UPDATE_OPTIONS
252    DART_TESTING_TIMEOUT
253    GITCOMMAND
254    P4COMMAND
255    HGCOMMAND
256    MAKECOMMAND
257    MEMORYCHECK_COMMAND
258    MEMORYCHECK_SUPPRESSIONS_FILE
259    SITE
260    SVNCOMMAND
261    )
262  if(NOT RUN_FROM_DART)
263    set(RUN_FROM_CTEST_OR_DART 1)
264    include(CTestTargets)
265    set(RUN_FROM_CTEST_OR_DART)
266  endif()
267endif()
268