@@ -140,35 +140,28 @@ function(split_json_array json_array_var out_var)
140140 set (${out_var} "${array_elements} " PARENT_SCOPE )
141141endfunction ()
142142
143- # TBD: Further possible optimization is that most arguments for per-test
144- # `prepare_command` call are constant across one invocation of
145- # `catch_discover_tests`, and thus need checking and escaping only
146- # once, instead of for each test.
147- # This would provide nice speed-up of the actual command preparation,
148- # but it will make the script much harder to read, and it is utterly
149- # dwarfed by the quadratic scaling of parsing JSON arrays in CMake.
150143
151-
152- # Prepare command with escaped (bracketed) arguments and return it via `_Command` out variable.
144+ # Prepare (a part of) command with bracketed arguments and return it via `out_var`.
153145#
154- # To avoid quadratic performance when concatenating all commands together,
155- # the actual concatenation must be done by the caller, by appending it
156- # into a string of all other commands.
157- function (prepare_command NAME )
146+ # This allows the registration script to escape parts of the test script
147+ # only once, instead of escaping the unchanged arguments over and over again.
148+ function (prepare_command_fragment out_var )
158149 set (_args "" )
159- # use ARGV* instead of ARGN, because ARGN splits arrays into multiple arguments
160150 math (EXPR _last_arg ${ARGC} -1 )
161- foreach (_n RANGE 1 ${_last_arg} )
162- set (_arg "${ARGV${_n} }" )
163- if (_arg MATCHES "[^-./:a-zA-Z0-9_]" )
164- set (_args "${_args} [==[${_arg} ]==]" ) # form a bracket_argument
165- else ()
166- set (_args "${_args} ${_arg} " )
167- endif ()
168- endforeach ()
169- set (_Command "${NAME} (${_args} )\n " PARENT_SCOPE )
151+ if (_last_arg GREATER_EQUAL 1)
152+ foreach (_n RANGE 1 ${_last_arg} )
153+ set (_arg "${ARGV${_n} }" )
154+ if (_arg MATCHES "[^-./:a-zA-Z0-9_]" )
155+ set (_args "${_args} [==[${_arg} ]==]" ) # form a bracket_argument
156+ else ()
157+ set (_args "${_args} ${_arg} " )
158+ endif ()
159+ endforeach ()
160+ endif ()
161+ set (${out_var} "${_args} " PARENT_SCOPE )
170162endfunction ()
171163
164+
172165# Generates random filename in the temp folder.
173166# Temp folder is retrieved by checking env vars from various platforms.
174167function (make_temp_file_path OUT_VARIABLE FALLBACK_PATH )
@@ -395,6 +388,41 @@ function(catch_discover_tests_impl)
395388 # so that each test name can be appended file without further processing.
396389 set (test_names "set(${_TEST_LIST} " )
397390
391+ # Most of the commands/arguments in the CTest script are identical
392+ # for every test registered with one `catch_discover_tests` call.
393+ # To avoid repeating the work in escaping them, we escape them before
394+ # the per-test loop and reuse the escaped fragments.
395+ #
396+ # `add_test` calls are
397+ # add_test(<name><exec><exe><escaped_name><extra_args><reporter><out_dir>)
398+ # Of these, <exec>,<exe>,<extra_args>, and <reporter> are the same between
399+ # all tests.
400+ prepare_command_fragment (_exec_exe_fragment
401+ ${_TEST_EXECUTOR}
402+ "${_TEST_EXECUTABLE} "
403+ )
404+ prepare_command_fragment (_args_reporter_fragment
405+ ${extra_args}
406+ "${reporter_arg} "
407+ )
408+
409+ # `set_tests_properties` calls are
410+ # set_tests_properties(<name> PROPERTIES WORKING_DIRECTORY <dir> <properties>)
411+ # set_tests_properties(<name> PROPERTIES ENVIRONMENT_MODIFICATION <env_mod>)
412+ # Of these, only the <name> changes between tests.
413+ prepare_command_fragment (_properties_fragment
414+ PROPERTIES
415+ WORKING_DIRECTORY "${_TEST_WORKING_DIR} "
416+ ${properties}
417+ )
418+ # Env modification is optional, so we prepare it in a separate command
419+ if (environment_modifications)
420+ prepare_command_fragment (_env_modification_fragment
421+ PROPERTIES
422+ ENVIRONMENT_MODIFICATION "${environment_modifications} "
423+ )
424+ endif ()
425+
398426 # Each element in the tests is JSON-string representing one test object.
399427 # We have to parse it and then turn it into CTest script commands.
400428 foreach (single_test IN LISTS tests)
@@ -431,24 +459,15 @@ function(catch_discover_tests_impl)
431459 set (output_dir_arg "--out ${output_dir} /${output_prefix}${escaped_name_clean}${output_suffix} " )
432460 endif ()
433461
434- # ...and add to script
435- prepare_command (add_test
436- "${prefix}${plain_name}${suffix} "
437- ${_TEST_EXECUTOR}
438- "${_TEST_EXECUTABLE} "
439- "${escaped_name} "
440- ${extra_args}
441- "${reporter_arg} "
442- "${output_dir_arg} "
443- )
444- string (APPEND script "${_Command} " )
445- prepare_command (set_tests_properties
446- "${prefix}${plain_name}${suffix} "
447- PROPERTIES
448- WORKING_DIRECTORY "${_TEST_WORKING_DIR} "
449- ${properties}
450- )
451- string (APPEND script "${_Command} " )
462+ set (full_name "${prefix}${plain_name}${suffix} " )
463+ prepare_command_fragment (_full_name_fragment "${full_name} " )
464+ prepare_command_fragment (_escaped_name_fragment "${escaped_name} " )
465+ prepare_command_fragment (_outdir_fragment "${output_dir_arg} " )
466+
467+ string (APPEND script
468+ "add_test(${_full_name_fragment}${_exec_exe_fragment}${_escaped_name_fragment}${_args_reporter_fragment}${_outdir_fragment} )\n " )
469+ string (APPEND script
470+ "set_tests_properties(${_full_name_fragment}${_properties_fragment} )\n " )
452471
453472 if (add_tags)
454473 string (JSON num_tags LENGTH "${test_tags} " )
@@ -468,21 +487,16 @@ function(catch_discover_tests_impl)
468487 list (APPEND tag_list "${a_tag} " )
469488 endforeach ()
470489
471- prepare_command (set_tests_properties
472- "${prefix}${plain_name}${suffix} "
490+ prepare_command_fragment (_labels_fragment
473491 PROPERTIES
474492 LABELS "${tag_list} "
475493 )
476- string (APPEND script "${_Command} " )
494+ string (APPEND script "set_tests_properties( ${_full_name_fragment}${_labels_fragment} ) \n " )
477495 endif ()
478496 endif (add_tags )
479497
480498 if (environment_modifications)
481- prepare_command (set_tests_properties
482- "${prefix}${plain_name}${suffix} "
483- PROPERTIES
484- ENVIRONMENT_MODIFICATION "${environment_modifications} " )
485- string (APPEND script "${_Command} " )
499+ string (APPEND script "set_tests_properties(${_full_name_fragment}${_env_modification_fragment} )\n " )
486500 endif ()
487501
488502 # The test name has to be escaped using the same rules as prepare_command
0 commit comments