1#
2#
3# This Cmake testing specification is unfortunately complex, and will
4# likely be hard to maintain, but at the moment I don't know a better
5# way to do it (contributions welcome).  The idea is that we have a set of tests that we'd
6# like to run on staging engines.  Some tests may be applicable to
7# some engines and not to others.  Some tests we want to run multiple
8# times, but with different engine parameters set to test different
9# modes of operation for the engines.
10#
11# The approach here is as follows:
12#   - A test is specified by setting a CMake variable of the form
13#     <testname>_CMD.
14#   - If the test requires a different time out than is usually
15#     specified (30 seconds), then you can also define a variable of
16#     the form <testname>_TIMEOUT to control the timeout.
17#   - If the test requires special properties you can also define a variable of
18#     the form <testname>_PROPERTIES.
19#
20#     BASIC TEST ADDITION
21# Given the existence of the above variables, the cmake function
22# "add_common_test(testname engine)" adds a CTest which runs the given
23# test with a particular ADIOS2 engine, adding the engine's name to
24# the test name to differentiate it from other tests.  For example,
25# given the variable 1x1_CMD, set to
26#  "run_staging_test -nw 1 -nr 1 -v -p TestCommon"
27# and 1x1_PROPERTIES set to "RUN_SERIAL;1" then
28# add_common_test(1x1 SST) ends up doing:
29#
30#  add_test(NAME "Staging.1x1.SST"
31#          COMMAND "run_staging_test -e SST -f Staging.1x1.SST -nw 1 -nr 1")
32#  set_tests_properties(${testname} PROPERTIES TIMEOUT 30 RUN_SERIAL 1)
33#
34#    RUNNING TESTS WITH DIFFERENT ENGINE PARAMETERS
35#
36# One of the design goals here is to enable running the same tests
37# with different engine parameters, *_CMD strings can also contain the
38# string "WENGINE_PARAMS".  This string is treated specially by the
39# function MutateTestSet().  This function is takes a list of tests
40
41# (I.E. things with _CMD strings defined like above) and creates a new
42# set of tests where a specified engine parameter gets added to the in
43# the location of the WENGINE_PARAMS string.  MutateTestSet takes 4 parameters:
44# output_test_list, param_name, param_spec, and input test list.  For example
45# MutateTestSet( COMM_MIN_SST_TESTS "CommMin" "CPCommPattern=Min" "${BASIC_SST_TESTS}" )
46# If BASIC_SST_TESTS contains "1x1" as defined above, MutateTestSet
47# will add the test "1x1.CommMin", by defining the variable
48# 1x1.CommMin_CMD, using the original value of 1x1_CMD buth with
49# "CPCommPattern=Min: added to the WENGINE_PARAMS location (if
50# present).  Any 1x1_TIMEOUT and 1x1_PROPERTIES values will also be
51# propogated to 1x1.CommMin_TIMEOUT and 1x1.CommMin_PROPERTIES.
52# "1x1.CommMin" will also be added to the output test list.
53#
54# Note that MutateTestSet() can be used multiple times to add multiple
55# engine params.  The WENGINE_PARAMS string is retained in the
56# resulting _CMD strings until add_common_test() which removes it.
57#
58
59find_package(PythonInterp REQUIRED)
60
61# Change the STAGING_COMMON_TEST_SUPP_VERBOSE value to ON for debugging output
62#
63set (STAGING_COMMON_TEST_SUPP_VERBOSE OFF)
64
65set (1x1_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1")
66set (1x1.NoPreload_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1 --rarg=PreloadMode=SstPreloadNone,RENGINE_PARAMS")
67set (1x1.SstRUDP_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1 --rarg=DataTransport=WAN,WANDataTransport=enet,RENGINE_PARAMS --warg=DataTransport=WAN,WANDataTransport=enet,WENGINE_PARAMS")
68set (1x1.NoData_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1 --warg=--no_data --rarg=--no_data")
69set (2x2.NoData_CMD "run_test.py.$<CONFIG> -nw 2 -nr 2 --warg=--no_data --rarg=--no_data")
70set (2x2.HalfNoData_CMD "run_test.py.$<CONFIG> -nw 2 -nr 2 --warg=--no_data --warg=--no_data_node --warg=1 --rarg=--no_data --rarg=--no_data_node --rarg=1" )
71set (1x1.ForcePreload_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1 --rarg=PreloadMode=SstPreloadOn,RENGINE_PARAMS")
72set (1x1Bulk_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1 --warg=--nx --warg=10000 --warg=--num_steps --warg=101 --rarg=--num_steps --rarg=101")
73set (1x1LockGeometry_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  --warg=--num_steps --warg=101  --warg=--nx --warg=50 --rarg=--num_steps --rarg=101 --warg=--lock_geometry --rarg=--lock_geometry --rarg=PreloadMode=SstPreloadNone,RENGINE_PARAMS")
74set (2x1_CMD "run_test.py.$<CONFIG> -nw 2 -nr 1")
75set (2x1ZeroDataVar_CMD "run_test.py.$<CONFIG> -nw 2 -nr 1 --warg=--zero_data_var")
76set (2x1ZeroDataR64_CMD "run_test.py.$<CONFIG> -nw 2 -nr 1  -r $<TARGET_FILE:TestCommonReadR64> --warg=--zero_data_var")
77set (2x1.NoPreload_CMD "run_test.py.$<CONFIG> -nw 2 -nr 1 --rarg=PreloadMode=SstPreloadNone,RENGINE_PARAMS")
78set (2x3.ForcePreload_CMD "run_test.py.$<CONFIG> -nw 2 -nr 3 --rarg=PreloadMode=SstPreloadOn,RENGINE_PARAMS")
79set (2x3.SstRUDP_CMD "run_test.py.$<CONFIG> -nw 2 -nr 3 --rarg=DataTransport=WAN,WANDataTransport=enet,RENGINE_PARAMS --warg=DataTransport=WAN,WANDataTransport=enet,WENGINE_PARAMS")
80set (1x2_CMD "run_test.py.$<CONFIG> -nw 1 -nr 2")
81set (3x5_CMD "run_test.py.$<CONFIG> -nw 3 -nr 5")
82set (3x5LockGeometry_CMD "run_test.py.$<CONFIG> -nw 3 -nr 5 --warg=--num_steps --warg=50 --warg=--ms_delay --warg=10 --rarg=--num_steps --rarg=50 --warg=--lock_geometry --rarg=--lock_geometry")
83set (1x1EarlyExit_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1 --warg=--num_steps --warg=50 --rarg=--num_steps --rarg=5 --rarg=--early_exit")
84set (3x5EarlyExit_CMD "run_test.py.$<CONFIG> -nw 3 -nr 5 --warg=--num_steps --warg=50 --rarg=--num_steps --rarg=5 --rarg=--early_exit")
85set (3x5LockGeometry_TIMEOUT 60)
86set (5x3_CMD "run_test.py.$<CONFIG> -nw 5 -nr 3")
87set (1x1.Local_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWriteLocal> -r $<TARGET_FILE:TestCommonReadLocal>")
88set (2x1.Local_CMD "run_test.py.$<CONFIG> -nw 2 -nr 1  -w $<TARGET_FILE:TestCommonWriteLocal> -r $<TARGET_FILE:TestCommonReadLocal>")
89set (1x2.Local_CMD "run_test.py.$<CONFIG> -nw 1 -nr 2  -w $<TARGET_FILE:TestCommonWriteLocal> -r $<TARGET_FILE:TestCommonReadLocal>")
90set (3x5.Local_CMD "run_test.py.$<CONFIG> -nw 3 -nr 5  -w $<TARGET_FILE:TestCommonWriteLocal> -r $<TARGET_FILE:TestCommonReadLocal>")
91set (5x3.Local_CMD "run_test.py.$<CONFIG> -nw 5 -nr 3  -w $<TARGET_FILE:TestCommonWriteLocal> -r $<TARGET_FILE:TestCommonReadLocal>")
92set (1x1.LocalVarying_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWriteLocal> --warg=--nx --warg=20 --warg=--varying_data_size -r $<TARGET_FILE:TestCommonReadLocal> --rarg=--nx --rarg=20 --rarg=--varying_data_size ")
93set (5x3.LocalVarying_CMD "run_test.py.$<CONFIG> -nw 5 -nr 3  -w $<TARGET_FILE:TestCommonWriteLocal> --warg=--nx --warg=20 --warg=--varying_data_size -r $<TARGET_FILE:TestCommonReadLocal> --rarg=--nx --rarg=20 --rarg=--varying_data_size ")
94set (1x1.LocalMultiblock_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWriteLocal> -r $<TARGET_FILE:TestCommonReadLocal> --warg=--local_count --warg=2 --rarg=--local_count --rarg=2")
95set (2x1.LocalMultiblock_CMD "run_test.py.$<CONFIG> -nw 2 -nr 1  -w $<TARGET_FILE:TestCommonWriteLocal> -r $<TARGET_FILE:TestCommonReadLocal> --warg=--local_count --warg=3 --rarg=--local_count --rarg=3")
96set (5x3.LocalMultiblock_CMD "run_test.py.$<CONFIG> -nw 5 -nr 3  -w $<TARGET_FILE:TestCommonWriteLocal> -r $<TARGET_FILE:TestCommonReadLocal> --warg=--local_count --warg=5 --rarg=--local_count --rarg=5")
97set (DelayedReader_3x5_CMD "run_test.py.$<CONFIG> -rd 5 -nw 3 -nr 5")
98set (FtoC.3x5_CMD "run_test.py.$<CONFIG> -nw 3 -nr 5  -w $<TARGET_FILE:TestCommonWrite_f>")
99set (FtoF.3x5_CMD "run_test.py.$<CONFIG> -nw 3 -nr 5  -w $<TARGET_FILE:TestCommonWrite_f> -r $<TARGET_FILE:TestCommonRead_f>")
100set (1x1.SharedNothing_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWriteShared> -r $<TARGET_FILE:TestCommonReadShared> --warg=--write_mode --warg=deferred")
101set (1x1.SharedIO_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWriteShared> -r $<TARGET_FILE:TestCommonReadShared> --warg=--shared_io --rarg=--shared_io --warg=--write_mode --warg=deferred")
102set (1x1.SharedVar_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWriteShared> -r $<TARGET_FILE:TestCommonReadShared> --warg=--shared_var --rarg=--shared_var --warg=--write_mode --warg=deferred")
103set (1x1.SharedNothingSync_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWriteShared> -r $<TARGET_FILE:TestCommonReadShared> --warg=--write_mode --warg=sync")
104set (1x1.SharedIOSync_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWriteShared> -r $<TARGET_FILE:TestCommonReadShared> --warg=--shared_io --rarg=--shared_io --warg=--write_mode --warg=sync")
105set (1x1.SharedVarSync_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWriteShared> -r $<TARGET_FILE:TestCommonReadShared> --warg=--shared_var --rarg=--shared_var --warg=--write_mode --warg=sync")
106
107set (2x1.SharedNothing_CMD "run_test.py.$<CONFIG> -nw 2 -nr 1  -w $<TARGET_FILE:TestCommonWriteShared> -r $<TARGET_FILE:TestCommonReadShared> --warg=--write_mode --warg=deferred")
108set (2x1.SharedIO_CMD "run_test.py.$<CONFIG> -nw 2 -nr 1  -w $<TARGET_FILE:TestCommonWriteShared> -r $<TARGET_FILE:TestCommonReadShared> --warg=--shared_io --rarg=--shared_io --warg=--write_mode --warg=deferred")
109set (2x1.SharedVar_CMD "run_test.py.$<CONFIG> -nw 2 -nr 1  -w $<TARGET_FILE:TestCommonWriteShared> -r $<TARGET_FILE:TestCommonReadShared> --warg=--shared_var --rarg=--shared_var --warg=--write_mode --warg=deferred")
110set (2x1.SharedNothingSync_CMD "run_test.py.$<CONFIG> -nw 2 -nr 1  -w $<TARGET_FILE:TestCommonWriteShared> -r $<TARGET_FILE:TestCommonReadShared> --warg=--write_mode --warg=sync")
111set (2x1.SharedIOSync_CMD "run_test.py.$<CONFIG> -nw 2 -nr 1  -w $<TARGET_FILE:TestCommonWriteShared> -r $<TARGET_FILE:TestCommonReadShared> --warg=--shared_io --rarg=--shared_io --warg=--write_mode --warg=sync")
112set (2x1.SharedVarSync_CMD "run_test.py.$<CONFIG> -nw 2 -nr 1  -w $<TARGET_FILE:TestCommonWriteShared> -r $<TARGET_FILE:TestCommonReadShared> --warg=--shared_var --rarg=--shared_var --warg=--write_mode --warg=sync")
113
114
115# NoReaderNoWait runs a writer with the RendezvousReaderCount = 0 and then never spawns a reader.  The test should run to termination and execute cleanly
116set (NoReaderNoWait_CMD "run_test.py.$<CONFIG> -nw 1 -nr 0 --warg=RendezvousReaderCount=0,QueueLimit=3,QueueFullPolicy=discard,WENGINE_PARAMS")
117
118# TimeoutOnOpen runs a reader but never spawns a writer.  The Open should run to timeout and throw an exception
119set (TimeoutOnOpen_CMD "run_test.py.$<CONFIG> -nw 0 -nr 1 --rarg=--expect_timeout --rarg=OpenTimeoutSecs=10,RENGINE_PARAMS")
120
121# The Modes test checks to see that we can mix and match Put Sync and Deferred modes and still get good data
122set (1x1.Modes_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWriteModes>")
123
124# 1x1.Attrs tests writing and reading of attributes defined before Open
125set (1x1.Attrs_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWriteAttrs> -r $<TARGET_FILE:TestCommonReadAttrs>")
126
127# Basic Fortran tests, Fortran to C, C to Fortran and Fortran to Fortran
128set (FtoC.1x1_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWrite_f>")
129set (CtoF.1x1_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -r $<TARGET_FILE:TestCommonRead_f>")
130set (FtoF.1x1_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1  -w $<TARGET_FILE:TestCommonWrite_f> -r $<TARGET_FILE:TestCommonRead_f>")
131
132# MPI Fortran tests, Fortran to C, C to Fortran and Fortran to Fortran
133set (FtoC.3x5_CMD "run_test.py.$<CONFIG> -nw 3 -nr 5  -w $<TARGET_FILE:TestCommonWrite_f>")
134set (CtoF.3x5_CMD "run_test.py.$<CONFIG> -nw 3 -nr 5  -r $<TARGET_FILE:TestCommonRead_f>")
135set (FtoF.3x5_CMD "run_test.py.$<CONFIG> -nw 3 -nr 5  -w $<TARGET_FILE:TestCommonWrite_f> -r $<TARGET_FILE:TestCommonRead_f>")
136
137# Tests for ZFP compression (where supported by an engine param)
138set (ZFPCompression.1x1_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1 --warg=CompressionMethod=zfp,WENGINE_PARAMS" )
139set (ZFPCompression.3x5_CMD "run_test.py.$<CONFIG> -nw 3 -nr 5 --warg=CompressionMethod=zfp,WENGINE_PARAMS" )
140
141# Test if writer will survive readers departing unexpectedly
142set (KillReadersSerialized.3x2_CMD "run_test.py.$<CONFIG> --test_protocol kill_readers  -nw 3 -nr 2 --max_readers 1 --warg=RendezvousReaderCount=0,WENGINE_PARAMS --rarg=--ignore_time_gap")
143set (KillReadersSerialized.3x2_TIMEOUT "300")
144set (KillReaders3Max.3x6_CMD "run_test.py.$<CONFIG> --test_protocol kill_readers  -nw 3 -nr 2 --max_readers 3 --warg=RendezvousReaderCount=0,WENGINE_PARAMS --rarg=--ignore_time_gap")
145set (KillReaders3Max.3x6_TIMEOUT "300")
146
147set (KillWriter_2x2_CMD "run_test.py.$<CONFIG> --test_protocol kill_writer   -nw 2 -nr 2 --interval 10 --warg=RendezvousReaderCount=1,WENGINE_PARAMS --rarg=--expect_writer_failure --rarg=--num_steps --rarg=1000")
148set (KillWriterTimeout_2x2_CMD "run_test.py.$<CONFIG> --test_protocol kill_writer -nw 2 -nr 2 --interval 10 --warg=RendezvousReaderCount=1,WENGINE_PARAMS --rarg=--expect_writer_failure --rarg=--num_steps --rarg=1000 --rarg=--non_blocking")
149
150set (PreciousTimestep.3x2_CMD "run_test.py.$<CONFIG> --test_protocol kill_readers  -nw 3 -nr 2 --max_readers 2 --warg=FirstTimestepPrecious=True,RendezvousReaderCount=0,WENGINE_PARAMS --rarg=--ignore_time_gap --rarg=--precious_first")
151
152set (PreciousTimestep.3x2_TIMEOUT "300")
153
154set (PreciousTimestepDiscard.3x2_CMD "run_test.py.$<CONFIG> --test_protocol kill_readers  -nw 3 -nr 2 --max_readers 2 --warg=FirstTimestepPrecious=On,RendezvousReaderCount=0,QueueLimit=3,QueueFullPolicy=discard,WENGINE_PARAMS --rarg=--ignore_time_gap --rarg=--precious_first --rarg=--discard --warg=--ms_delay --warg=500")
155set (PreciousTimestepDiscard.3x2_TIMEOUT "300")
156
157# Readers using BeginStep with timeout.  Here we run the writer with a longer delay to make the reader timeout
158set (TimeoutReader.1x1_CMD "run_test.py.$<CONFIG> --test_protocol one_client -nw 1 -nr 1 --rarg=--non_blocking --warg=--ms_delay --warg=2000")
159set (TimeoutReader.1x1_TIMEOUT "60")
160
161# Readers using LatestAvailable   Writer runs faster than reader, so we expect misses
162set (LatestReader.1x1_CMD "run_test.py.$<CONFIG> --test_protocol one_client -nw 1 -nr 1 --warg=--ms_delay --warg=250 --rarg=--latest --rarg=--long_first_delay")
163
164set (LatestReaderHold.1x1_CMD "run_test.py.$<CONFIG> --test_protocol one_client -nw 1 -nr 1 --warg=--ms_delay --warg=250 --rarg=--latest --rarg=--long_first_delay --rarg=--delay_while_holding")
165
166# A faster writer and a queue policy that will cause timesteps to be discarded
167set (DiscardWriter.1x1_CMD "run_test.py.$<CONFIG> --test_protocol one_client -nw 1 -nr 1 --warg=--engine_params --warg=QueueLimit=1,QueueFullPolicy=discard,WENGINE_PARAMS --warg=--ms_delay --warg=250 --rarg=--discard")
168
169# Readers using Advancing attributes
170set (CumulativeAttr.1x1_CMD "run_test.py.$<CONFIG> -nw 1 -nr 1 --warg=--advancing_attributes --rarg=--advancing_attributes")
171
172function(remove_engine_params_placeholder dst_str src_str )
173    string(REGEX REPLACE "([^ 		  ]*),WENGINE_PARAMS" "\\1" src_str "${src_str}")
174    string(REGEX REPLACE "([^ 		  ]*),RENGINE_PARAMS" "\\1" src_str "${src_str}")
175    if ("${src_str}" MATCHES "ENGINE_PARAMS")
176       # empty engine params remains
177       string(REGEX REPLACE "--warg=--engine_params --warg=WENGINE_PARAMS" "" src_str "${src_str}")
178       string(REGEX REPLACE "--rarg=--engine_params --rarg=RENGINE_PARAMS" "" src_str "${src_str}")
179       string(REGEX REPLACE "--warg=ENGINE_PARAMS" "" src_str "${src_str}")
180       string(REGEX REPLACE "--rarg=ENGINE_PARAMS" "" src_str "${src_str}")
181    endif()
182  set(${dst_str} ${src_str} PARENT_SCOPE)
183endfunction()
184
185function(add_engine_param participant dst_string src_string engine_param)
186  if (participant STREQUAL "writer")
187      set(ARG "--warg")
188      set(L "W")
189  elseif (participant STREQUAL "reader")
190      set(ARG "--rarg")
191      set(L "R")
192  else ()
193      message(WARNING "add_engine_param participant value not valid \"${participant}\", assuming writer")
194      set(ARG "--warg")
195      set(L "W")
196  endif ()
197  set (tmp_string "")
198  if ("${src_string}" MATCHES ",${L}ENGINE_PARAMS")
199      string(REGEX REPLACE ",${L}ENGINE_PARAMS" ",${engine_param},${L}ENGINE_PARAMS" tmp_string ${src_string})
200  elseif ("${src_string}" MATCHES "${L}ENGINE_PARAMS")
201      string(REGEX REPLACE "${L}ENGINE_PARAMS" "${engine_param},${L}ENGINE_PARAMS" tmp_string ${src_string})
202  else ()
203       string(APPEND tmp_string "${src_string}" " ${ARG}=${engine_param},${L}ENGINE_PARAMS")
204  endif ()
205
206  set(${dst_string} "${tmp_string}" PARENT_SCOPE)
207endfunction()
208
209function(MutateTestSet out_list name participant param in_list )
210  set (tmp_list "")
211  FOREACH (basename ${in_list})
212    set (modname "${basename}.${name}")
213    if ("${${basename}_CMD}" STREQUAL "")
214       message(SEND_ERROR "Staging-Common MutateTestSet ${basename} has no defined ${basename}_CMD")
215    endif()
216    add_engine_param(${participant} tmp_cmd "${${basename}_CMD}" ${param})
217    set(${modname}_CMD ${tmp_cmd} PARENT_SCOPE)
218    if (NOT "${${basename}_TIMEOUT}" STREQUAL "")
219        set(${modname}_TIMEOUT ${${basename}_TIMEOUT} PARENT_SCOPE)
220    endif()
221    if (NOT "${${basename}_PROPERTIES}" STREQUAL "")
222        set(${modname}_PROPERTIES ${${basename}_PROPERTIES} PARENT_SCOPE)
223    endif()
224    LIST(APPEND tmp_list ${modname})
225  endforeach()
226  if (STAGING_COMMON_TEST_SUPP_VERBOSE)
227    message (STATUS "Setting ${out_list} to ${tmp_list}")
228  endif()
229  set(${out_list} ${tmp_list} PARENT_SCOPE)
230endfunction()
231
232function(add_common_test basename engine)
233    set(testname "Staging.${basename}.${engine}")
234    if ("${${basename}_CMD}" STREQUAL "")
235       message(SEND_ERROR "Staging-Common test ${basename} has no defined ${basename}_CMD")
236    endif()
237    set(command "${PYTHON_EXECUTABLE} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${${basename}_CMD}")
238    remove_engine_params_placeholder(command  "${command}")
239    separate_arguments(command)
240    list(INSERT command 2 "${engine}" "${testname}")
241    if(NOT ADIOS2_RUN_MPI_MPMD_TESTS)
242      list(APPEND command "--disable_mpmd")
243    endif()
244    add_test(NAME ${testname} COMMAND ${command})
245    if(testname MATCHES "([1-9][0-9]*)x([1-9][0-9]*)")
246      math(EXPR nprocs "${CMAKE_MATCH_1} + ${CMAKE_MATCH_2}")
247      set_tests_properties(${testname} PROPERTIES PROCESSORS ${nprocs})
248    endif()
249    if (STAGING_COMMON_TEST_SUPP_VERBOSE)
250	message ( STATUS "Adding test \"${testname}\" COMMAND \"${command}\"")
251    endif()
252    set (timeout "${${basename}_TIMEOUT}")
253    if ("${timeout}" STREQUAL "")
254       set (timeout "30")
255    endif()
256
257    set_tests_properties(${testname} PROPERTIES
258        TIMEOUT ${timeout} ${${basename}_PROPERTIES}
259        RUN_SERIAL TRUE
260    )
261endfunction()
262
263function(from_hex HEX DEC)
264    string(TOUPPER "${HEX}" HEX)
265    set(_res 0)
266    string(LENGTH "${HEX}" _strlen)
267
268    while(_strlen GREATER 0)
269        math(EXPR _res "${_res} * 16")
270        string(SUBSTRING "${HEX}" 0 1 NIBBLE)
271        string(SUBSTRING "${HEX}" 1 -1 HEX)
272        if(NIBBLE STREQUAL "A")
273            math(EXPR _res "${_res} + 10")
274        elseif(NIBBLE STREQUAL "B")
275            math(EXPR _res "${_res} + 11")
276        elseif(NIBBLE STREQUAL "C")
277            math(EXPR _res "${_res} + 12")
278        elseif(NIBBLE STREQUAL "D")
279            math(EXPR _res "${_res} + 13")
280        elseif(NIBBLE STREQUAL "E")
281            math(EXPR _res "${_res} + 14")
282        elseif(NIBBLE STREQUAL "F")
283            math(EXPR _res "${_res} + 15")
284        else()
285            math(EXPR _res "${_res} + ${NIBBLE}")
286        endif()
287
288        string(LENGTH "${HEX}" _strlen)
289    endwhile()
290
291    set(${DEC} ${_res} PARENT_SCOPE)
292endfunction()
293
294