AndroidTestUtilities.cmake 6.6 KB

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