-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Expand file tree
/
Copy pathRootTestDriver.cmake
More file actions
295 lines (257 loc) · 8.91 KB
/
RootTestDriver.cmake
File metadata and controls
295 lines (257 loc) · 8.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# Copyright (C) 1995-2019, Rene Brun and Fons Rademakers.
# All rights reserved.
#
# For the licensing terms see $ROOTSYS/LICENSE.
# For the list of contributors see $ROOTSYS/README/CREDITS.
#-------------------------------------------------------------------------------
#
# RootCTestDriver.cmake
#
# CTest testdriver. Takes arguments via -DARG.
#
# Script arguments:
#
# CMD Command to be executed for the test.
# PRE Command to be executed before the test command.
# POST Command to be executed after the test command.
# IN File to be used as input
# OUT File to collect stdout and stderr.
# ENV Environment VAR1=Value1;VAR2=Value2.
# CWD Current working directory.
# SYS Value of ROOTSYS
# DBG Debug flag.
# RC Return code for success.
#
#-------------------------------------------------------------------------------
if(DBG)
message(STATUS "ENV=${ENV}")
endif()
if(CMD)
string(REPLACE "^" ";" _cmd ${CMD})
if(DBG)
message(STATUS "testdriver:CMD=${_cmd}")
endif()
endif()
if(COPY)
string(REPLACE "^" ";" _copy_files ${COPY})
if(DBG)
message(STATUS "files to copy: ${_copy_files}")
endif()
endif()
if(PRE)
string(REPLACE "^" ";" _pre ${PRE})
if(DBG)
message(STATUS "testdriver:PRE=${_pre}")
endif()
endif()
if(POST)
string(REPLACE "^" ";" _post ${POST})
if(DBG)
message(STATUS "testdriver:POST=${_post}")
endif()
endif()
if(CWD)
set(_cwd WORKING_DIRECTORY ${CWD})
if(DBG)
message(STATUS "testdriver:CWD=${CWD}")
endif()
endif()
find_program(diff_cmd diff)
if(DIFFCMD)
string(REPLACE "^" ";" diff_cmd ${DIFFCMD})
endif()
#---Set environment --------------------------------------------------------------------------------
if(ENV)
# CMake treats ';' as a list separator. Since ENV values may legitimately
# contain semicolons (e.g. PATH-like variables), we must escape them here
# so they survive the upcoming list expansion in `foreach()`.
string(REPLACE ";" "\\;" _env "${ENV}")
# Deserialize the ENV string into a CMake list.
# This is the inverse operation of ROOT_ADD_TEST, which serializes the list
# by joining elements with '#'.
string(REPLACE "#" ";" _env "${_env}")
foreach(pair ${_env})
# During list expansion, CMake has already consumed any previous '\;'
# escaping. Re-escape semicolons so the key=value split below treats the
# value as a single string.
string(REPLACE ";" "\\;" pair "${pair}")
# Split KEY=VALUE into a 2-element CMake list: [KEY;VALUE]
string(REGEX REPLACE "^([^=]+)=(.*)$" "\\1;\\2" pair "${pair}")
list(GET pair 0 var)
list(GET pair 1 val)
# As before, quoting is important here so the semicolons are not
# interpreted as list separators.
set(ENV{${var}} "${val}")
if(DBG)
message(STATUS "testdriver[ENV]:${var}==>${val}")
endif()
endforeach()
endif()
if(SYS)
if(WIN32)
cmake_path(CONVERT "${SYS}/bin" TO_NATIVE_PATH_LIST _path)
set(ENV{PATH} "${_path};$ENV{PATH}")
elseif(APPLE)
set(ENV{PATH} ${SYS}/bin:$ENV{PATH})
set(ENV{DYLD_LIBRARY_PATH} ${SYS}/lib:$ENV{DYLD_LIBRARY_PATH})
else()
set(ENV{PATH} ${SYS}/bin:$ENV{PATH})
set(ENV{LD_LIBRARY_PATH} ${SYS}/lib:$ENV{LD_LIBRARY_PATH})
endif()
endif()
#---Copy files to current direcotory----------------------------------------------------------------
if(COPY)
foreach(copyfile ${_copy_files})
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${copyfile} ${CMAKE_CURRENT_BINARY_DIR}
RESULT_VARIABLE _rc)
if(_rc)
message(FATAL_ERROR "Copying file ${copyfile} to ${CMAKE_CURRENT_BINARY_DIR} failed! Error code : ${_rc}")
endif()
endforeach()
endif()
#---Execute pre-command-----------------------------------------------------------------------------
if(PRE)
execute_process(COMMAND ${_pre} ${_cwd} RESULT_VARIABLE _rc)
if(_rc)
message(FATAL_ERROR "pre-command error code : ${_rc}")
endif()
endif()
if(CMD)
#---Execute the actual test ------------------------------------------------------------------------
if(CMD_ENV)
# Only support exactly one variable
set(_cmd ${CMAKE_COMMAND} -E env ${CMD_ENV} ${_cmd})
endif()
if(IN)
set(_input INPUT_FILE ${IN})
endif()
if(OUT)
# log stdout
if(CHECKOUT)
set(_chkout OUTPUT_VARIABLE _outvar)
else()
set(_chkout OUTPUT_VARIABLE _outvar2)
endif()
# log stderr
if(ERRREF)
set(_chkerr ERROR_VARIABLE _errvar) # Check err reference
else()
if(CHECKERR AND CHECKOUT)
set(_chkerr ERROR_VARIABLE _outvar) # Both err and out together
elseif(CHECKERR)
set(_chkerr ERROR_VARIABLE _errvar0) # Only check (no reference) the err and and ignore out
else()
set(_chkerr ERROR_VARIABLE _errvar2) # Only check out eventually
endif()
endif()
execute_process(COMMAND ${_cmd} ${_input} ${_chkout} ${_chkerr} WORKING_DIRECTORY ${CWD} RESULT_VARIABLE _rc)
string(REGEX REPLACE "([.]*)[;][-][e][;]([^;]+)([.]*)" "\\1;-e '\\2\\3'" res "${_cmd}")
string(REPLACE ";" " " res "${res}")
message("-- TEST COMMAND -- ")
message("cd ${CWD}")
message("${res}")
message("-- BEGIN TEST OUTPUT --")
message("${_outvar}${_outvar2}")
message("-- END TEST OUTPUT --")
if(_errvar0 OR _errvar OR _errvar2)
message("-- BEGIN TEST ERROR --")
message("${_errvar0}${_errvar}${_errvar2}")
message("-- END TEST ERROR --")
endif()
file(WRITE ${OUT} "${_outvar}")
if(ERR)
file(WRITE ${ERR} "${_errvar}")
endif()
if(_errvar0)
# Filter messages in stderr that are expected
string(STRIP "${_errvar0}" _errvar0)
string(REPLACE "\n" ";" _lines "${_errvar0}")
list(FILTER _lines EXCLUDE REGEX "^Info in <.+::ACLiC>: creating shared library.+")
list(FILTER _lines EXCLUDE REGEX "^Info in <TROOT>: Implicit object ownership.*") # ROOT 7 demo mode in ROOT 6
string(REPLACE ";" "\n" _errvar0 "${_lines}")
if(_errvar0)
message(FATAL_ERROR "Unexpected error output")
endif()
endif()
if(DEFINED RC AND (NOT "${_rc}" STREQUAL "${RC}"))
message(FATAL_ERROR "got exit code ${_rc} but expected ${RC}")
elseif(NOT DEFINED RC AND _rc)
message(FATAL_ERROR "got exit code ${_rc} but expected 0")
endif()
if(CNVCMD)
string(REPLACE "^" ";" _outcnvcmd "${CNVCMD}^${OUT}")
string(REPLACE "@" "=" _outcnvcmd "${_outcnvcmd}")
execute_process(COMMAND ${_outcnvcmd} ${_chkout} ${_chkerr} RESULT_VARIABLE _rc)
file(WRITE ${OUT} "${_outvar}")
if(_rc)
message(FATAL_ERROR "out conversion error code: ${_rc}")
endif()
endif()
if(CNV)
string(REPLACE "^" ";" _outcnv "sh;${CNV}")
execute_process(COMMAND ${_outcnv} INPUT_FILE "${OUT}" OUTPUT_VARIABLE _outvar RESULT_VARIABLE _rc)
file(WRITE ${OUT} "${_outvar}")
if(_rc)
message(FATAL_ERROR "out conversion error code: ${_rc}")
endif()
if(ERR)
execute_process(COMMAND ${_outcnv} INPUT_FILE "${ERR}" OUTPUT_VARIABLE _errvar RESULT_VARIABLE _rc)
file(WRITE ${ERR} "${_errvar}")
if(_rc)
message(FATAL_ERROR "err conversion error code: ${_rc}")
endif()
endif()
endif()
else()
execute_process(COMMAND ${_cmd} ${_out} ${_err} ${_cwd} RESULT_VARIABLE _rc)
if(_rc STREQUAL "Segmentation fault" OR _rc EQUAL 11)
message(STATUS "Got ${_rc}, retrying again once more... with coredump enabled")
string (REPLACE ";" " " _cmd_str "${_cmd}")
file(WRITE run_with_coredump.sh "
pwd
ulimit -c unlimited
${_cmd_str}
")
execute_process(COMMAND bash run_with_coredump.sh ${_out} ${_err} ${_cwd} RESULT_VARIABLE _rc)
endif()
if(DEFINED RC AND (NOT _rc EQUAL RC))
message(FATAL_ERROR "error code: ${_rc}")
elseif(NOT DEFINED RC AND _rc)
message(FATAL_ERROR "error code: ${_rc}")
endif()
endif()
endif()
#---Execute post-command-----------------------------------------------------------------------------
if(POST)
execute_process(COMMAND ${_post} ${_cwd} OUTPUT_VARIABLE _outvar ERROR_VARIABLE _outvar RESULT_VARIABLE _rc)
if(_outvar)
message("-- BEGIN POST OUTPUT --")
message("${_outvar}")
message("-- END POST OUTPUT --")
endif()
if(_rc)
message(FATAL_ERROR "post-command error code : ${_rc}")
endif()
endif()
if(OUTREF)
execute_process(COMMAND ${diff_cmd} ${OUTREF} ${OUT} OUTPUT_VARIABLE _outvar ERROR_VARIABLE _outvar RESULT_VARIABLE _rc)
if(_outvar)
message("-- BEGIN OUTDIFF OUTPUT --")
message("${_outvar}")
message("-- END OUTDIFF OUTPUT --")
endif()
if(_rc)
message(FATAL_ERROR "compare 'stdout' error: ${_rc}")
endif()
endif()
if(ERRREF)
execute_process(COMMAND ${diff_cmd} ${ERRREF} ${ERR} OUTPUT_VARIABLE _outvar ERROR_VARIABLE _outvar RESULT_VARIABLE _rc)
if(_outvar)
message("-- BEGIN ERRDIFF OUTPUT --")
message("${_outvar}")
message("-- END ERRDIFF OUTPUT --")
endif()
if(_rc)
message(FATAL_ERROR "compare 'stderr' error: ${_rc}")
endif()
endif()