CMake: Use test wrapper to run android tests
Refactor test adding procedure. It's expected that for each new
platform we prepare test executable and arguments first and then
pass them to common test adding section.
Rename '_qt_internal_wrap_test' to 'qt_internal_create_command_script'
Rework paramerters handling of 'qt_internal_create_command_script',
make them named.
Add 'qt_internal_create_test_script' to add tests and wrap them using
'qt_internal_create_command_script'.
Amends f19266bd02
Fixes: QTBUG-88053
Pick-to: 6.0
Change-Id: I812f4a295005bf3a85cdcb5b8c41180f8249dc96
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
parent
6198ba217f
commit
d5bafc80cd
@ -125,10 +125,10 @@ define_property(TARGET
|
||||
"This variable points to the path of the deployment settings JSON file, which holds properties required by androiddeployqt to package the Android app."
|
||||
)
|
||||
|
||||
# Add a test for Android which will be run by the android test runner tool
|
||||
function(qt_internal_android_add_test target)
|
||||
# Returns test execution arguments for Android targets
|
||||
function(qt_internal_android_test_arguments target out_test_runner out_test_arguments)
|
||||
set(${out_test_runner} "${QT_HOST_PATH}/bin/androidtestrunner" PARENT_SCOPE)
|
||||
set(deployment_tool "${QT_HOST_PATH}/bin/androiddeployqt")
|
||||
set(test_runner "${QT_HOST_PATH}/bin/androidtestrunner")
|
||||
|
||||
get_target_property(deployment_file ${target} QT_ANDROID_DEPLOYMENT_SETTINGS_FILE)
|
||||
if (NOT deployment_file)
|
||||
@ -138,13 +138,13 @@ function(qt_internal_android_add_test target)
|
||||
set(target_binary_dir "$<TARGET_PROPERTY:${target},BINARY_DIR>")
|
||||
set(apk_dir "${target_binary_dir}/android-build")
|
||||
|
||||
add_test(NAME "${target}"
|
||||
COMMAND "${test_runner}"
|
||||
--path "${apk_dir}"
|
||||
--adb "${ANDROID_SDK_ROOT}/platform-tools/adb"
|
||||
--skip-install-root
|
||||
--make "${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${target}_make_apk"
|
||||
--apk "${apk_dir}/${target}.apk"
|
||||
--verbose
|
||||
set(${out_test_arguments}
|
||||
"--path" "${apk_dir}"
|
||||
"--adb" "${ANDROID_SDK_ROOT}/platform-tools/adb"
|
||||
"--skip-install-root"
|
||||
"--make" "${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${target}_make_apk"
|
||||
"--apk" "${apk_dir}/${target}.apk"
|
||||
"--verbose"
|
||||
PARENT_SCOPE
|
||||
)
|
||||
endfunction()
|
||||
|
@ -296,7 +296,8 @@ function(qt_internal_add_test name)
|
||||
string(REPLACE ";" "\;" plugin_paths_joined "${plugin_paths_joined}")
|
||||
|
||||
if (ANDROID)
|
||||
qt_internal_android_add_test("${name}")
|
||||
qt_internal_android_test_arguments("${name}" test_executable extra_test_args)
|
||||
set(test_working_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
else()
|
||||
if(arg_QMLTEST AND NOT arg_SOURCES)
|
||||
set(test_working_dir "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
@ -316,21 +317,32 @@ function(qt_internal_add_test name)
|
||||
#TODO: Should we replace this by TESTARGS environment variable?
|
||||
list(APPEND extra_test_args "-o" "${name}.xml,xml" "-o" "-,txt")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(arg_NO_WRAPPER OR QT_NO_TEST_WRAPPERS)
|
||||
add_test(NAME "${name}" COMMAND ${test_executable} ${extra_test_args}
|
||||
WORKING_DIRECTORY "${test_working_dir}")
|
||||
set_property(TEST "${name}" APPEND PROPERTY
|
||||
ENVIRONMENT "PATH=${test_env_path}"
|
||||
"QT_TEST_RUNNING_IN_CTEST=1"
|
||||
"QT_PLUGIN_PATH=${plugin_paths_joined}"
|
||||
)
|
||||
else()
|
||||
_qt_internal_wrap_test("${name}" "${test_executable}" "${extra_test_args}" "${test_working_dir}"
|
||||
set(test_wrapper_file "${CMAKE_CURRENT_BINARY_DIR}/${name}Wrapper$<CONFIG>.cmake")
|
||||
qt_internal_create_test_script(NAME "${name}"
|
||||
COMMAND "${test_executable}"
|
||||
ARGS "${extra_test_args}"
|
||||
WORKING_DIRECTORY "${test_working_dir}"
|
||||
OUTPUT_FILE "${test_wrapper_file}"
|
||||
ENVIRONMENT "QT_TEST_RUNNING_IN_CTEST" 1
|
||||
"PATH" "${test_env_path}"
|
||||
"QT_PLUGIN_PATH" "${plugin_paths_joined}")
|
||||
"QT_PLUGIN_PATH" "${plugin_paths_joined}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if (arg_QT_TEST_SERVER_LIST)
|
||||
if(arg_QT_TEST_SERVER_LIST AND NOT ANDROID)
|
||||
qt_internal_setup_docker_test_fixture(${name} ${arg_QT_TEST_SERVER_LIST})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_tests_properties("${name}" PROPERTIES RUN_SERIAL "${arg_RUN_SERIAL}" LABELS "${label}")
|
||||
if (arg_TIMEOUT)
|
||||
@ -338,7 +350,6 @@ function(qt_internal_add_test name)
|
||||
endif()
|
||||
|
||||
# Add a ${target}/check makefile target, to more easily test one test.
|
||||
if(TEST "${name}")
|
||||
add_custom_target("${name}_check"
|
||||
VERBATIM
|
||||
COMMENT "Running ${CMAKE_CTEST_COMMAND} -V -R \"^${name}$\""
|
||||
@ -347,15 +358,6 @@ function(qt_internal_add_test name)
|
||||
if(TARGET "${name}")
|
||||
add_dependencies("${name}_check" "${name}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ANDROID OR arg_NO_WRAPPER OR QT_NO_TEST_WRAPPERS)
|
||||
set_property(TEST "${name}" APPEND PROPERTY ENVIRONMENT
|
||||
"PATH=${test_env_path}"
|
||||
"QT_TEST_RUNNING_IN_CTEST=1"
|
||||
"QT_PLUGIN_PATH=${plugin_paths_joined}"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(ANDROID OR IOS OR WINRT)
|
||||
set(builtin_testdata TRUE)
|
||||
@ -414,10 +416,115 @@ function(qt_internal_add_test name)
|
||||
|
||||
endfunction()
|
||||
|
||||
# This function wraps test with cmake script, that makes possible standalone run with external
|
||||
# This function adds test with specified NAME and wraps given test COMMAND with standalone cmake
|
||||
# script.
|
||||
#
|
||||
# NAME must be compatible with add_test function, since it's propagated as is.
|
||||
# COMMAND might be either target or path to executable. When test is called either by ctest or
|
||||
# directly by 'cmake -P path/to/scriptWrapper.cmake', COMMAND will be executed in specified
|
||||
# WORKING_DIRECTORY with arguments specified in ARGS.
|
||||
#
|
||||
# See also qt_internal_create_command_script for details.
|
||||
function(qt_internal_create_test_script)
|
||||
#This style of parsing keeps ';' in ENVIRONMENT variables
|
||||
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||
""
|
||||
"NAME;COMMAND;OUTPUT_FILE;WORKING_DIRECTORY"
|
||||
"ARGS;ENVIRONMENT;PRE_RUN;POST_RUN"
|
||||
)
|
||||
|
||||
if(NOT arg_COMMAND)
|
||||
message(FATAL_ERROR "qt_internal_create_test_script: Test COMMAND is not specified")
|
||||
endif()
|
||||
|
||||
if(NOT arg_NAME)
|
||||
message(FATAL_ERROR "qt_internal_create_test_script: Test NAME is not specified")
|
||||
endif()
|
||||
|
||||
if(NOT arg_OUTPUT_FILE)
|
||||
message(FATAL_ERROR "qt_internal_create_test_script: Test Wrapper OUTPUT_FILE\
|
||||
is not specified")
|
||||
endif()
|
||||
|
||||
if(arg_PRE_RUN)
|
||||
message(WARNING "qt_internal_create_test_script: PRE_RUN is not acceptable argument\
|
||||
for this function. Will be ignored")
|
||||
endif()
|
||||
|
||||
if(arg_POST_RUN)
|
||||
message(WARNING "qt_internal_create_test_script: POST_RUN is not acceptable argument\
|
||||
for this function. Will be ignored")
|
||||
endif()
|
||||
|
||||
if(arg_ARGS)
|
||||
set(command_args ${arg_ARGS})# Avoid "${arg_ARGS}" usage and let cmake expand string to
|
||||
# semicolon-separated list
|
||||
qt_internal_wrap_command_arguments(command_args)
|
||||
endif()
|
||||
|
||||
if(TARGET ${arg_COMMAND})
|
||||
set(executable_file "$<TARGET_FILE:${arg_COMMAND}>")
|
||||
else()
|
||||
set(executable_file "${arg_COMMAND}")
|
||||
endif()
|
||||
|
||||
add_test(NAME "${arg_NAME}" COMMAND "${CMAKE_COMMAND}" "-P" "${arg_OUTPUT_FILE}"
|
||||
WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}")
|
||||
|
||||
# If crosscompiling is enabled, we should avoid run cmake in emulator environment.
|
||||
# Prepend emulator to test command in generated cmake script instead. Keep in mind that
|
||||
# CROSSCOMPILING_EMULATOR don't check if actual cross compilation is configured,
|
||||
# emulator is prepended independently.
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
get_test_property(${arg_NAME} CROSSCOMPILING_EMULATOR crosscompiling_emulator)
|
||||
if(NOT crosscompiling_emulator)
|
||||
set(crosscompiling_emulator "")
|
||||
else()
|
||||
qt_internal_wrap_command_arguments(crosscompiling_emulator)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
qt_internal_create_command_script(COMMAND "${crosscompiling_emulator} \${env_test_runner} \
|
||||
\"${executable_file}\" \${env_test_args} ${command_args}"
|
||||
OUTPUT_FILE "${arg_OUTPUT_FILE}"
|
||||
WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}"
|
||||
ENVIRONMENT ${arg_ENVIRONMENT}
|
||||
PRE_RUN "separate_arguments(env_test_args NATIVE_COMMAND \
|
||||
\"\$ENV{TESTARGS}\")"
|
||||
"separate_arguments(env_test_runner NATIVE_COMMAND \
|
||||
\"\$ENV{TESTRUNNER}\")"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# This function wraps COMMAND with cmake script, that makes possible standalone run with external
|
||||
# arguments.
|
||||
function(_qt_internal_wrap_test name test_executable extra_test_args test_working_dir)
|
||||
cmake_parse_arguments(PARSE_ARGV 4 arg "" "" "ENVIRONMENT")
|
||||
#
|
||||
# Generated wrapper will be written to OUTPUT_FILE.
|
||||
# If WORKING_DIRECTORY is not set COMMAND will be executed in CMAKE_CURRENT_BINARY_DIR.
|
||||
# Variables from ENVIRONMENT will be set before COMMAND execution.
|
||||
# PRE_RUN and POST_RUN arguments may contain extra cmake code that supposed to be executed before
|
||||
# and after COMMAND, respectively. Both arguments accept a list of cmake script language
|
||||
# constructions. Each item of the list will be concantinated into single string with '\n' sepatator.
|
||||
function(qt_internal_create_command_script)
|
||||
#This style of parsing keeps ';' in ENVIRONMENT variables
|
||||
cmake_parse_arguments(PARSE_ARGV 0 arg
|
||||
""
|
||||
"OUTPUT_FILE;WORKING_DIRECTORY"
|
||||
"COMMAND;ENVIRONMENT;PRE_RUN;POST_RUN"
|
||||
)
|
||||
|
||||
if(NOT arg_COMMAND)
|
||||
message(FATAL_ERROR "qt_internal_create_command_script: COMMAND is not specified")
|
||||
endif()
|
||||
|
||||
if(NOT arg_OUTPUT_FILE)
|
||||
message(FATAL_ERROR "qt_internal_create_command_script: Wrapper OUTPUT_FILE\
|
||||
is not specified")
|
||||
endif()
|
||||
|
||||
if(NOT arg_WORKING_DIRECTORY)
|
||||
set(arg_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
endif()
|
||||
|
||||
set(environment_extras)
|
||||
set(skipNext false)
|
||||
@ -450,53 +557,36 @@ function(_qt_internal_wrap_test name test_executable extra_test_args test_workin
|
||||
#Escaping environment variables before expand them by file GENERATE
|
||||
string(REPLACE "\\" "\\\\" environment_extras "${environment_extras}")
|
||||
|
||||
set(test_wrapper_name "${CMAKE_CURRENT_BINARY_DIR}/${name}Wrapper$<CONFIG>.cmake")
|
||||
add_test(NAME "${name}" COMMAND "${CMAKE_COMMAND}" "-P" "${test_wrapper_name}"
|
||||
WORKING_DIRECTORY "${test_working_dir}")
|
||||
|
||||
if(TARGET ${test_executable})
|
||||
set(test_executable_file "$<TARGET_FILE:${test_executable}>")
|
||||
else()
|
||||
set(test_executable_file "${test_executable}")
|
||||
endif()
|
||||
|
||||
# If crosscompiling is enabled, we should avoid run cmake in emulator environment.
|
||||
# Prepend emulator to test command in generated cmake script instead. Keep in mind that
|
||||
# CROSSCOMPILING_EMULATOR don't check if actual cross compilation is configured,
|
||||
# emulator is prepended independently.
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
get_test_property(${name} CROSSCOMPILING_EMULATOR crosscompiling_emulator)
|
||||
if(NOT crosscompiling_emulator)
|
||||
set(crosscompiling_emulator "")
|
||||
else()
|
||||
qt_internal_wrap_command_arguments(crosscompiling_emulator)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
# It's necessary to call actual test inside 'cmd.exe', because 'execute_process' uses
|
||||
# SW_HIDE to avoid showing a console window, it affects other GUI as well.
|
||||
# See https://gitlab.kitware.com/cmake/cmake/-/issues/17690 for details.
|
||||
set(extra_test_runner "cmd /c")
|
||||
set(extra_runner "cmd /c")
|
||||
endif()
|
||||
|
||||
qt_internal_wrap_command_arguments(extra_test_args)
|
||||
if(arg_PRE_RUN)
|
||||
string(JOIN "\n" pre_run ${arg_PRE_RUN})
|
||||
endif()
|
||||
|
||||
file(GENERATE OUTPUT "${test_wrapper_name}" CONTENT
|
||||
if(arg_POST_RUN)
|
||||
string(JOIN "\n" post_run ${arg_POST_RUN})
|
||||
endif()
|
||||
|
||||
file(GENERATE OUTPUT "${arg_OUTPUT_FILE}" CONTENT
|
||||
"#!${CMAKE_COMMAND} -P
|
||||
# Qt generated test wrapper for ${name}
|
||||
# Qt generated command wrapper
|
||||
|
||||
${environment_extras}
|
||||
separate_arguments(test_args NATIVE_COMMAND \"\$ENV{TESTARGS}\")
|
||||
separate_arguments(test_runner NATIVE_COMMAND \"\$ENV{TESTRUNNER}\")
|
||||
execute_process(COMMAND ${crosscompiling_emulator} ${extra_test_runner} \${test_runner} \
|
||||
\"${test_executable_file}\" \${test_args} ${extra_test_args} \
|
||||
WORKING_DIRECTORY \"${test_working_dir}\" \
|
||||
RESULT_VARIABLE result)
|
||||
${pre_run}
|
||||
execute_process(COMMAND ${extra_runner} ${arg_COMMAND}
|
||||
WORKING_DIRECTORY \"${arg_WORKING_DIRECTORY}\"
|
||||
RESULT_VARIABLE result
|
||||
)
|
||||
${post_run}
|
||||
if(NOT result EQUAL 0)
|
||||
message(FATAL_ERROR)
|
||||
endif()"
|
||||
)
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# This function creates an executable for use as a helper program with tests. Some
|
||||
|
Loading…
Reference in New Issue
Block a user