diff options
Diffstat (limited to 'Modules/AndroidTestUtilities/PushToAndroidDevice.cmake')
-rw-r--r-- | Modules/AndroidTestUtilities/PushToAndroidDevice.cmake | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake b/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake new file mode 100644 index 0000000..f5f2564 --- /dev/null +++ b/Modules/AndroidTestUtilities/PushToAndroidDevice.cmake @@ -0,0 +1,174 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +# This function handles pushing all of the test files needed to the device. +# It places the data files in the object store and makes links to them from +# the appropriate directories. +# +# This function accepts the following named parameters: +# DIRS : one or more directories needed for testing. +# FILES : one or more files needed for testing. +# LIBS : one or more libraries needed for testing. +# DIRS_DEST : specify where the directories should be installed. +# FILES_DEST : specify where the files should be installed. +# LIBS_DEST : specify where the libraries should be installed. +# DEV_OBJ_STORE : specify where the actual data files should be placed. +# DEV_TEST_DIR : specify the root file for the module test directory. +# The DEV_OBJ_STORE and DEV_TEST_DIR variables are required. + +# The parameters to this function should be set to the list of directories, +# files, and libraries that need to be installed prior to testing. +function(android_push_test_files_to_device) + + # The functions in the module need the adb executable. + find_program(adb_executable adb) + if(NOT adb_executable) + message(FATAL_ERROR "could not find adb") + endif() + + function(execute_adb_command) + execute_process(COMMAND ${adb_executable} ${ARGN} RESULT_VARIABLE res_var OUTPUT_VARIABLE out_var ERROR_VARIABLE err_var) + set(out_var ${out_var} PARENT_SCOPE) + if(res_var) + string(REGEX REPLACE ";" " " com "${ARGN}") + message(FATAL_ERROR "Error occured during adb command: adb ${com}\nError: ${err_var}.") + endif() + endfunction() + + # Checks to make sure that a given file exists on the device. If it does, + # if(file_exists) will return true. + macro(check_device_file_exists device_file file_exists) + set(${file_exists} "") + execute_adb_command(shell ls ${device_file}) + if(NOT out_var) # when a directory exists but is empty the output is empty + set(${file_exists} "YES") + else() + string(FIND ${out_var} "No such file or directory" no_file_exists) + if(${no_file_exists} STREQUAL "-1") # -1 means the file exists + set(${file_exists} "YES") + endif() + endif() + endmacro() + + # Checks to see if a filename matches a regex. + function(filename_regex filename reg_ex) + string(REGEX MATCH ${reg_ex} filename_match ${filename}) + set(filename_match ${filename_match} PARENT_SCOPE) + endfunction() + + # If a file with given name exists in the CMAKE_BINARY_DIR then use that file. + # Otherwise use the file with root in CMAKE_CURRENT_SOURCE_DIR. + macro(set_absolute_path relative_path absolute_path) + set(${absolute_path} ${arg_src_dir}/${relative_path}) + if(EXISTS ${CMAKE_BINARY_DIR}/${relative_path}) + set(${absolute_path} ${CMAKE_BINARY_DIR}/${relative_path}) + endif() + if(NOT EXISTS ${${absolute_path}}) + if(EXISTS ${relative_path}) + set(${absolute_path} ${relative_path}) + else() + message(FATAL_ERROR "Cannot find file for specified path: ${relative_path}") + endif() + endif() + endmacro() + + # This function pushes the data into the device object store and + # creates a link to that data file in a specified location. + # + # This function requires the following un-named parameters: + # data_path : absolute path to data to load into dev obj store. + # dev_object_store : absolute path to the device object store directory. + # link_origin : absolute path to the origin of the link to the dev obj store data file. + function(push_and_link data_path dev_object_store link_origin) + FILE(SHA1 ${data_path} hash_val) + set(obj_store_dst ${dev_object_store}/${hash_val}) + check_device_file_exists(${obj_store_dst} obj_store_file_exists) + # TODO: Verify that the object store file is indeed hashed correctly. Could use md5. + if(NOT obj_store_file_exists) + execute_adb_command(push ${data_path} ${obj_store_dst}) + endif() + check_device_file_exists(${link_origin} link_exists) + if(link_exists) + execute_adb_command(shell rm -f ${link_origin}) + endif() + foreach(ex ${arg_no_link_regex}) + filename_regex(${data_path} ${ex}) + LIST(APPEND match_ex ${filename_match}) + endforeach() + if(match_ex) + execute_adb_command(shell cp ${obj_store_dst} ${link_origin}) + else() + execute_adb_command(shell ln -s ${obj_store_dst} ${link_origin}) + endif() + endfunction() + + #---------------------------------------------------------------------------- + #--------------------Beginning of actual function---------------------------- + #---------------------------------------------------------------------------- + set(oneValueArgs FILES_DEST LIBS_DEST DEV_TEST_DIR DEV_OBJ_STORE) + set(multiValueArgs FILES LIBS) + cmake_parse_arguments(_ptd "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + # Setup of object store and test dir. + check_device_file_exists(${_ptd_DEV_OBJ_STORE} dev_obj_store_exists) + if(NOT dev_obj_store_exists) + execute_adb_command(shell mkdir -p ${_ptd_DEV_OBJ_STORE}) + endif() + check_device_file_exists(${_ptd_DEV_TEST_DIR} test_dir_exists) + if(test_dir_exists) + # This is protected in the SetupProjectTests module. + execute_adb_command(shell echo rm -r ${_ptd_DEV_TEST_DIR} | su) + endif() + execute_adb_command(shell mkdir -p ${_ptd_DEV_TEST_DIR}) + + # Looping over the various types of test data possible. + foreach(TYPE ${multiValueArgs}) + if(_ptd_${TYPE}) + + # determine if the data type destination has been explicitly specified. + if(_ptd_${TYPE}_DEST) + set(dest ${_ptd_${TYPE}_DEST}) + else() + if(${TYPE} STREQUAL LIBS) + set(dest ${_ptd_DEV_TEST_DIR}/lib) + else() + set(dest ${_ptd_DEV_TEST_DIR}) + endif() + endif() + execute_adb_command(shell mkdir -p ${dest}) + + # Loop over the files passed in + foreach(relative_path ${_ptd_${TYPE}}) + # The absolute path can be through the source directory or the build directory. + # If the file/dir exists in the build directory that version is chosen. + set_absolute_path(${relative_path} absolute_path) + # Need to transfer all data files in the data directories to the device + # except those explicitly ignored. + if(${TYPE} STREQUAL FILES) + get_filename_component(file_dir ${relative_path} DIRECTORY) + # dest was determined earlier, relative_path is a dir, file is path from relative path to a data + set(cur_dest ${dest}/${relative_path}) + set(on_dev_dir ${dest}/${file_dir}) + execute_adb_command(shell mkdir -p ${on_dev_dir}) + if(IS_SYMLINK ${absolute_path}) + get_filename_component(real_data_origin ${absolute_path} REALPATH) + push_and_link(${real_data_origin} ${_ptd_DEV_OBJ_STORE} ${cur_dest}) + else() + push_and_link(${absolute_path} ${_ptd_DEV_OBJ_STORE} ${cur_dest}) + endif() + else() # LIBS + execute_adb_command(push ${absolute_path} ${dest}) + endif() + endforeach() + endif() + endforeach() +endfunction() + +android_push_test_files_to_device( + FILES_DEST ${arg_files_dest} + LIBS_DEST ${arg_libs_dest} + DEV_TEST_DIR ${arg_dev_test_dir} + DEV_OBJ_STORE ${arg_dev_obj_store} + FILES ${arg_files} + LIBS ${arg_libs} + ) |