# 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}")
  string(FIND "${AST_FILES}" "DATA{" data_files_found)
  if(${data_files_found} GREATER "-1")
    # Use ExternalData if any DATA{} files were found.
    ExternalData_Expand_Arguments(
      ${DATA_TARGET_NAME}
      extern_data_output
      ${AST_FILES})
    ExternalData_Add_Target(${DATA_TARGET_NAME})
  else()
    add_custom_target(${DATA_TARGET_NAME} ALL)
    set(extern_data_output ${AST_FILES})
  endif()

  # 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()
