1# Add an application level test.
2#
3# An application level test consists of a preprocessing step, running
4# the application itself, and a postprocessing step. In addition, file
5# dependencies can be specified and an overall job weight can be
6# specified. The function should be used as follows:
7#
8# add_application_test(
9#   <test-name>
10#   [SUBTEST <st_num>]
11#   [WEIGHT <n>]
12#   [TIMEOUT <seconds>]
13#   [FILE_DEPENDENCIES file1 [file2 [file3[...]]]]
14#   [PREPROCESS COMMAND <command> [EXIT_CODE <exit-code>]]
15#   [APPLICATION COMMAND <command> [EXIT_CODE <exit-code>]]
16#   [POSTPROCESS COMMAND <command> [EXIT_CODE <exit-code>]]
17#   [LABELS [label1 [label2 [...]]]]
18#   [UNIQUE_DIRECTORY]
19#   [WORKING_DIRECTORY <work-dir>]
20#   [NO_TARGET]
21#   )
22#
23# SUBTEST gives a subtest number which changes added test name to
24# test-name:st_num, but runs in directory test-name
25#
26# The WEIGHT argument specifies the number of processes that will be occupied
27# by the test. The TIMEOUT argument specifies how long the test should be
28# allowed to run in seconds. The FILE_DEPENDENCIES argument specifies any input
29# files the application test requires. These files will be copied to the test
30# execution directory at build time. The PREPROCESS, APPLICATION, and
31# POSTPROCESS arguments specify a preprocessing step, how to run the
32# application itself and any post processing steps that are required. Finally,
33# the LABELS argument specifies any labels to attach to the test.
34#
35# The UNIQUE_DIRECTORY toggle will ensure that the test runs in an
36# isolated subdirectory of the current binary directory, named for the
37# test-name.  The directory will be created.
38#
39# WORKING_DIRECTORY will run the test in the specified directory,
40# which must exist.
41#
42# If specified, the NO_TARGET toggle will create a custom command for
43# this test, but not a custom target (so the caller can group tests
44# into a single custom target)
45
46include(AddFileCopyTarget)
47include(CMakeParseArguments)
48
49get_filename_component(_add_application_test_dir ${CMAKE_CURRENT_LIST_FILE} PATH)
50
51function(add_application_test _test_name)
52  set(_option_args UNIQUE_DIRECTORY NO_TARGET)
53  set(_one_value_keyword_args
54    WEIGHT
55    TIMEOUT
56    SUBTEST
57    WORKING_DIRECTORY)
58  set(_multi_value_keyword_args
59    FILE_DEPENDENCIES
60    CONFIGURE_FILES
61    PREPROCESS
62    APPLICATION
63    POSTPROCESS
64    LABELS)
65
66  cmake_parse_arguments(
67    _application_test
68    "${_option_args}"
69    "${_one_value_keyword_args}"
70    "${_multi_value_keyword_args}"
71    ${ARGN})
72
73  # Setup default values for the arguments.
74  if(NOT _application_test_WEIGHT)
75    set(_application_test_WEIGHT 1)
76  endif()
77  if(NOT _application_test_TIMEOUT)
78    set(_application_test_TIMEOUT 0)
79  endif()
80  if(NOT _application_test_WORKING_DIRECTORY)
81    set(_application_test_WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
82  endif()
83
84  set(_full_test_name ${_test_name})
85  if(DEFINED _application_test_SUBTEST)
86    set(_full_test_name "${_test_name}:${_application_test_SUBTEST}")
87  endif()
88
89  # If an isolated subdirectory was requested, create the unique subdirectory
90  # to contain the test's input files.
91  if(_application_test_UNIQUE_DIRECTORY)
92    set(_application_test_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_test_name}")
93    file(MAKE_DIRECTORY "${_application_test_WORKING_DIRECTORY}")
94  endif()
95
96  # Add targets to copy all of the test dependencies to the working
97  # directory at build time.
98  foreach(_file ${_application_test_FILE_DEPENDENCIES})
99    get_filename_component(_filename ${_file} NAME)
100
101    # Add custom command and optional target
102    if(_application_test_NO_TARGET)
103      add_file_copy_command(
104	${CMAKE_CURRENT_SOURCE_DIR}/${_file}
105	${_application_test_WORKING_DIRECTORY}/${_file}
106	)
107    else()
108      add_file_copy_target(
109	copy_${_full_test_name}_${_filename}
110	${CMAKE_CURRENT_SOURCE_DIR}/${_file}
111	${_application_test_WORKING_DIRECTORY}/${_file})
112    endif()
113
114  endforeach() # file in dependencies
115
116  # Configure any test dependencies to the working directory at configure.
117  foreach(_file ${_application_test_CONFIGURE_FILES})
118    get_filename_component(_filename ${_file} NAME)
119    configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${_file}
120      ${_application_test_WORKING_DIRECTORY}/${_file} @ONLY)
121  endforeach() # file in dependencies
122
123  # Parse each of the PREPROCESS, APPLICATION, POSTPROCESS argument lists.
124  set(_phases PREPROCESS APPLICATION POSTPROCESS)
125  foreach(_phase ${_phases})
126    cmake_parse_arguments(
127      _application_test_${_phase}
128      ""
129      "EXIT_CODE"
130      "COMMAND"
131      "${_application_test_${_phase}}")
132    if(NOT _application_test_${_phase}_EXIT_CODE)
133      set(_application_test_${_phase}_EXIT_CODE 0)
134    endif()
135  endforeach()
136
137  # Configure the driver script.
138  set(_test_driver_file ${_application_test_WORKING_DIRECTORY}/TEST-${_full_test_name}.cmake)
139  configure_file(
140    ${_add_application_test_dir}/ApplicationTest.cmake.in
141    ${_test_driver_file}
142    @ONLY)
143
144  # Add the test that runs the driver.
145  add_test(NAME ${_full_test_name}
146    WORKING_DIRECTORY "${_application_test_WORKING_DIRECTORY}"
147    COMMAND ${CMAKE_COMMAND} -P ${_test_driver_file})
148
149  # Set up the test properties.
150  set_tests_properties(
151    ${_full_test_name}
152    PROPERTIES
153      PROCESSORS ${_application_test_WEIGHT}
154      TIMEOUT ${_application_test_TIMEOUT}
155      LABELS "${_application_test_LABELS}")
156
157
158endfunction()
159