1# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2# file Copyright.txt or https://cmake.org/licensing for details.
3
4#[======================================================================[.rst:
5AndroidTestUtilities
6------------------------
7
8.. versionadded:: 3.7
9
10Create a test that automatically loads specified data onto an Android device.
11
12Introduction
13^^^^^^^^^^^^
14
15Use this module to push data needed for testing an Android device behavior
16onto a connected Android device. The module will accept files and libraries as
17well as separate destinations for each. It will create a test that loads the
18files into a device object store and link to them from the specified
19destination. The files are only uploaded if they are not already in the object
20store.
21
22For example:
23
24.. code-block:: cmake
25
26  include(AndroidTestUtilities)
27  android_add_test_data(
28    example_setup_test
29    FILES <files>...
30    LIBS <libs>...
31    DEVICE_TEST_DIR "/data/local/tests/example"
32    DEVICE_OBJECT_STORE "/sdcard/.ExternalData/SHA"
33    )
34
35
36At build time a test named "example_setup_test" will be created.  Run this test
37on the command line with :manual:`ctest(1)` to load the data onto the Android
38device.
39
40Module Functions
41^^^^^^^^^^^^^^^^
42
43.. command:: android_add_test_data
44
45  .. code-block:: cmake
46
47    android_add_test_data(<test-name>
48      [FILES <files>...] [FILES_DEST <device-dir>]
49      [LIBS <libs>...]   [LIBS_DEST <device-dir>]
50      [DEVICE_OBJECT_STORE <device-dir>]
51      [DEVICE_TEST_DIR <device-dir>]
52      [NO_LINK_REGEX <strings>...]
53      )
54
55  The ``android_add_test_data`` function is used to copy files and libraries
56  needed to run project-specific tests. On the host operating system, this is
57  done at build time. For on-device testing, the files are loaded onto the
58  device by the manufactured test at run time.
59
60  This function accepts the following named parameters:
61
62  ``FILES <files>...``
63    zero or more files needed for testing
64  ``LIBS <libs>...``
65    zero or more libraries needed for testing
66  ``FILES_DEST <device-dir>``
67    absolute path where the data files are expected to be
68  ``LIBS_DEST <device-dir>``
69    absolute path where the libraries are expected to be
70  ``DEVICE_OBJECT_STORE <device-dir>``
71    absolute path to the location where the data is stored on-device
72  ``DEVICE_TEST_DIR <device-dir>``
73    absolute path to the root directory of the on-device test location
74  ``NO_LINK_REGEX <strings>...``
75    list of regex strings matching the names of files that should be
76    copied from the object store to the testing directory
77#]======================================================================]
78
79include(${CMAKE_CURRENT_LIST_DIR}/ExternalData.cmake)
80
81# The parameters to this function should be set to the list of directories,
82# files, and libraries that need to be installed prior to testing.
83function(android_add_test_data test_name)
84  # As the names suggest, oneValueArgs lists the arguments that specify a
85  # single value, while multiValueArgs can contain one or more values.
86  set(keywordArgs)
87  set(oneValueArgs FILES_DEST LIBS_DEST DEVICE_OBJECT_STORE DEVICE_TEST_DIR)
88  set(multiValueArgs FILES LIBS NO_LINK_REGEX)
89
90  # For example, if you called this function with FILES </path/to/file>
91  # then this path would be stored in the variable AST_FILES.
92  # The AST prefix stands for the name of this function (android_add_test_data).
93  cmake_parse_arguments(AST "${keywordArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
94  if(NOT AST_DEVICE_TEST_DIR)
95    message(FATAL_ERROR "-- You must specify the location of the on device test directory.")
96  endif()
97  if(NOT AST_DEVICE_OBJECT_STORE)
98    message(FATAL_ERROR "-- You must specify the location of the on device object store.")
99  endif()
100  if(${AST_DEVICE_TEST_DIR} STREQUAL "/")
101    message(FATAL_ERROR "-- The device test directory cannot be '/'")
102  endif()
103
104  # Copy all test data files into the binary directory, where tests are run.
105  # ExternalData will handle fetching DATA{...} references.
106  string(REPLACE "|" ";" hash_algs "${_ExternalData_REGEX_EXT}")
107  # Convert ExternalData placeholder file names to DATA{} syntax.
108  foreach(alg ${hash_algs})
109    string(REGEX REPLACE "([^ ;]+)\\.${alg}" "DATA{\\1}" AST_FILES "${AST_FILES}")
110  endforeach()
111
112  set(DATA_TARGET_NAME "${test_name}")
113  string(FIND "${AST_FILES}" "DATA{" data_files_found)
114  if(${data_files_found} GREATER "-1")
115    # Use ExternalData if any DATA{} files were found.
116    ExternalData_Expand_Arguments(
117      ${DATA_TARGET_NAME}
118      extern_data_output
119      ${AST_FILES})
120    ExternalData_Add_Target(${DATA_TARGET_NAME})
121  else()
122    add_custom_target(${DATA_TARGET_NAME} ALL)
123    set(extern_data_output ${AST_FILES})
124  endif()
125
126  # For regular files on Linux, just copy them directly.
127  foreach(path ${AST_FILES})
128    foreach(output ${extern_data_output})
129      if(${output} STREQUAL ${path})
130        # Check if a destination was specified.  If not, we copy by default
131        # into this project's binary directory, preserving its relative path.
132        if(AST_${VAR}_DEST)
133          set(DEST ${CMAKE_BINARY_DIR}/${parent_dir}/${AST_${VAR}_DEST})
134        else()
135          get_filename_component(parent_dir ${path} DIRECTORY)
136          set(DEST "${CMAKE_BINARY_DIR}/${parent_dir}")
137        endif()
138        get_filename_component(extern_data_source ${output} REALPATH)
139        get_filename_component(extern_data_basename ${output} NAME)
140        add_custom_command(
141          TARGET ${DATA_TARGET_NAME} POST_BUILD
142          DEPENDS ${extern_data_source}
143          COMMAND ${CMAKE_COMMAND} -E copy_if_different ${extern_data_source} ${DEST}/${extern_data_basename}
144        )
145      endif()
146    endforeach()
147  endforeach()
148
149  if(ANDROID)
150    string(REGEX REPLACE "DATA{([^ ;]+)}" "\\1"  processed_FILES "${AST_FILES}")
151    add_test(
152      NAME ${test_name}
153      COMMAND ${CMAKE_COMMAND}
154      "-Darg_files_dest=${AST_FILES_DEST}"
155      "-Darg_libs_dest=${AST_LIBS_DEST}"
156      "-Darg_dev_test_dir=${AST_DEVICE_TEST_DIR}"
157      "-Darg_dev_obj_store=${AST_DEVICE_OBJECT_STORE}"
158      "-Darg_no_link_regex=${AST_NO_LINK_REGEX}"
159      "-Darg_files=${processed_FILES}"
160      "-Darg_libs=${AST_LIBS}"
161      "-Darg_src_dir=${CMAKE_CURRENT_SOURCE_DIR}"
162      -P ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/AndroidTestUtilities/PushToAndroidDevice.cmake)
163  endif()
164endfunction()
165