# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

#[======================================================================[.rst:
AndroidTestUtilities
------------------------

Create a test that automatically loads specified data onto an Android device.

Introduction
^^^^^^^^^^^^

Use this module to push data needed for testing an Android device behavior
onto a connected Android device. The module will accept files and libraries as
well as separate destinations for each. It will create a test that loads the
files into a device object store and link to them from the specified
destination. The files are only uploaded if they are not already in the object
store.

For example:

.. code-block:: cmake

  include(AndroidTestUtilities)
  android_add_test_data(
    example_setup_test
    FILES <files>...
    LIBS <libs>...
    DEVICE_TEST_DIR "/data/local/tests/example"
    DEVICE_OBJECT_STORE "/sdcard/.ExternalData/SHA"
    )


At build time a test named "example_setup_test" will be created.  Run this test
on the command line with :manual:`ctest(1)` to load the data onto the Android
device.

Module Functions
^^^^^^^^^^^^^^^^

.. command:: android_add_test_data

  ::

    android_add_test_data(<test-name>
      [FILES <files>...] [FILES_DEST <device-dir>]
      [LIBS <libs>...]   [LIBS_DEST <device-dir>]
      [DEVICE_OBJECT_STORE <device-dir>]
      [DEVICE_TEST_DIR <device-dir>]
      [NO_LINK_REGEX <strings>...]
      )

  The ``android_add_test_data`` function is used to copy files and libraries
  needed to run project-specific tests. On the host operating system, this is
  done at build time. For on-device testing, the files are loaded onto the
  device by the manufactured test at run time.

  This function accepts the following named parameters:

  ``FILES <files>...``
    zero or more files needed for testing
  ``LIBS <libs>...``
    zero or more libraries needed for testing
  ``FILES_DEST <device-dir>``
    absolute path where the data files are expected to be
  ``LIBS_DEST <device-dir>``
    absolute path where the libraries are expected to be
  ``DEVICE_OBJECT_STORE <device-dir>``
    absolute path to the location where the data is stored on-device
  ``DEVICE_TEST_DIR <device-dir>``
    absolute path to the root directory of the on-device test location
  ``NO_LINK_REGEX <strings>...``
    list of regex strings matching the names of files that should be
    copied from the object store to the testing directory
#]======================================================================]

include(${CMAKE_CURRENT_LIST_DIR}/ExternalData.cmake)

set(_AndroidTestUtilities_SELF_DIR "${CMAKE_CURRENT_LIST_DIR}")

# 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_add_test_data test_name)
  # As the names suggest, oneValueArgs lists the arguments that specify a
  # single value, while multiValueArgs can contain one or more values.
  set(keywordArgs)
  set(oneValueArgs FILES_DEST LIBS_DEST DEVICE_OBJECT_STORE DEVICE_TEST_DIR)
  set(multiValueArgs FILES LIBS NO_LINK_REGEX)

  # For example, if you called this function with FILES </path/to/file>
  # then this path would be stored in the variable AST_FILES.
  # The AST prefix stands for the name of this function (android_add_test_data).
  cmake_parse_arguments(AST "${keywordArgs}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
  if(NOT AST_DEVICE_TEST_DIR)
    message(FATAL_ERROR "-- You must specify the location of the on device test directory.")
  endif()
  if(NOT AST_DEVICE_OBJECT_STORE)
    message(FATAL_ERROR "-- You must specify the location of the on device object store.")
  endif()
  if(${AST_DEVICE_TEST_DIR} STREQUAL "/")
    message(FATAL_ERROR "-- The device test directory cannot be '/'")
  endif()

  # Copy all test data files into the binary directory, where tests are run.
  # ExternalData will handle fetching DATA{...} references.
  string(REPLACE "|" ";" hash_algs "${_ExternalData_REGEX_EXT}")
  # Convert ExternalData placeholder file names to DATA{} syntax.
  foreach(alg ${hash_algs})
    string(REGEX REPLACE "([^ ;]+)\\.${alg}" "DATA{\\1}" AST_FILES "${AST_FILES}")
  endforeach()

  set(DATA_TARGET_NAME "${test_name}")
  ExternalData_Expand_Arguments(
    ${DATA_TARGET_NAME}
    extern_data_output
    ${AST_FILES})
  ExternalData_Add_Target(${DATA_TARGET_NAME})

  # For regular files on Linux, just copy them directly.
  foreach(path ${AST_FILES})
    foreach(output ${extern_data_output})
      if(${output} STREQUAL ${path})
        # Check if a destination was specified.  If not, we copy by default
        # into this project's binary directory, preserving its relative path.
        if(AST_${VAR}_DEST)
          set(DEST ${CMAKE_BINARY_DIR}/${parent_dir}/${AST_${VAR}_DEST})
        else()
          get_filename_component(parent_dir ${path} DIRECTORY)
          set(DEST "${CMAKE_BINARY_DIR}/${parent_dir}")
        endif()
        get_filename_component(extern_data_source ${output} REALPATH)
        get_filename_component(extern_data_basename ${output} NAME)
        add_custom_command(
          TARGET ${DATA_TARGET_NAME} POST_BUILD
          DEPENDS ${extern_data_source}
          COMMAND ${CMAKE_COMMAND} -E copy_if_different ${extern_data_source} ${DEST}/${extern_data_basename}
        )
      endif()
    endforeach()
  endforeach()

  if(ANDROID)
    string(REGEX REPLACE "DATA{([^ ;]+)}" "\\1"  processed_FILES "${AST_FILES}")
    add_test(
      NAME ${test_name}
      COMMAND ${CMAKE_COMMAND}
      "-Darg_files_dest=${AST_FILES_DEST}"
      "-Darg_libs_dest=${AST_LIBS_DEST}"
      "-Darg_dev_test_dir=${AST_DEVICE_TEST_DIR}"
      "-Darg_dev_obj_store=${AST_DEVICE_OBJECT_STORE}"
      "-Darg_no_link_regex=${AST_NO_LINK_REGEX}"
      "-Darg_files=${processed_FILES}"
      "-Darg_libs=${AST_LIBS}"
      "-Darg_src_dir=${CMAKE_CURRENT_SOURCE_DIR}"
      -P ${_AndroidTestUtilities_SELF_DIR}/AndroidTestUtilities/PushToAndroidDevice.cmake)
  endif()
endfunction()
