#
# Copyright (c) 2015-2021 CNRS INRIA
# Copyright (c) 2015 Wandercraft, 86 rue de Paris 91400 Orsay, France.
#

# --- MACROS ------------------------------------------------------------------
# --- MACROS ------------------------------------------------------------------
# --- MACROS ------------------------------------------------------------------

MACRO(ADD_TEST_CFLAGS target flag)
  SET_PROPERTY(TARGET "test-cpp-${target}" APPEND_STRING PROPERTY COMPILE_FLAGS " ${flag}")
ENDMACRO(ADD_TEST_CFLAGS)

MACRO(ADD_PINOCCHIO_UNIT_TEST NAME)
  SET(options HEADER_ONLY)
  SET(oneValueArgs)
  SET(multiValueArgs PACKAGES)
  CMAKE_PARSE_ARGUMENTS(unit_test "${options}" "${oneValueArgs}"
    "${multiValueArgs}" ${ARGN} )

  SET(PKGS ${unit_test_PACKAGES})

  SET(TEST_NAME "test-cpp-${NAME}")
  ADD_UNIT_TEST(${TEST_NAME} ${NAME}.cpp)
  SET_TARGET_PROPERTIES(${TEST_NAME} PROPERTIES LINKER_LANGUAGE CXX)
  TARGET_INCLUDE_DIRECTORIES(${TEST_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

  ADD_TEST_CFLAGS(${NAME} "-DBOOST_TEST_DYN_LINK")
  SET(MODULE_NAME "${NAME}Test")
  STRING(REGEX REPLACE "-" "_" MODULE_NAME ${MODULE_NAME})
  ADD_TEST_CFLAGS(${NAME} "-DBOOST_TEST_MODULE=${MODULE_NAME}")
  ADD_TEST_CFLAGS(${NAME} "-DPINOCCHIO_MODEL_DIR=\\\\\"${PINOCCHIO_MODEL_DIR}\\\\\"")
  IF(WIN32)
    ADD_TEST_CFLAGS(${NAME} "-DNOMINMAX -D_USE_MATH_DEFINES")
  ENDIF(WIN32)

  IF(NOT unit_test_HEADER_ONLY)
    TARGET_LINK_LIBRARIES(${TEST_NAME} PUBLIC ${PROJECT_NAME})
  ENDIF(NOT unit_test_HEADER_ONLY)
  MODERNIZE_TARGET_LINK_LIBRARIES(${TEST_NAME} SCOPE PRIVATE
    TARGETS Boost::unit_test_framework
    LIBRARIES ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
ENDMACRO(ADD_PINOCCHIO_UNIT_TEST)

MACRO(ADD_OPTIONAL_COMPILE_DEPENDENCY PKG_CONFIG_STRING)
  _GET_PKG_CONFIG_DEBUG_STRING("${PKG_CONFIG_STRING}" ${ARGN})
  ADD_DEPENDENCY(0 1 ${PKG_CONFIG_STRING} "${PKG_CONFIG_DEBUG_STRING}")
ENDMACRO()

MACRO(ADD_PINOCCHIO_PARALLEL_UNIT_TEST NAME)
  IF(BUILD_WITH_OPENMP_SUPPORT)
    ADD_PINOCCHIO_UNIT_TEST(${ARGV})
    SET(TEST_NAME "test-cpp-${NAME}")
    TARGET_LINK_LIBRARIES(${TEST_NAME} PRIVATE OpenMP::OpenMP_CXX)
  ENDIF()
ENDMACRO()

# Find Boost.UnitTestFramework
FIND_PACKAGE(Boost COMPONENTS unit_test_framework)

# Header only
ADD_PINOCCHIO_UNIT_TEST(macros HEADER_ONLY)

# Math components
ADD_PINOCCHIO_UNIT_TEST(eigen-basic-op)
ADD_PINOCCHIO_UNIT_TEST(eigen-tensor)
ADD_PINOCCHIO_UNIT_TEST(sincos)
ADD_PINOCCHIO_UNIT_TEST(quaternion)
ADD_PINOCCHIO_UNIT_TEST(rpy)
ADD_PINOCCHIO_UNIT_TEST(rotation)
ADD_PINOCCHIO_UNIT_TEST(vector)

# Pinocchio features
ADD_PINOCCHIO_UNIT_TEST(spatial)
ADD_PINOCCHIO_UNIT_TEST(symmetric)
ADD_PINOCCHIO_UNIT_TEST(aba)
ADD_PINOCCHIO_PARALLEL_UNIT_TEST(parallel-aba)
ADD_PINOCCHIO_UNIT_TEST(rnea)
ADD_PINOCCHIO_PARALLEL_UNIT_TEST(parallel-rnea)
ADD_PINOCCHIO_UNIT_TEST(crba)
ADD_PINOCCHIO_UNIT_TEST(centroidal)
ADD_PINOCCHIO_UNIT_TEST(com)
ADD_PINOCCHIO_UNIT_TEST(joint-jacobian)
ADD_PINOCCHIO_UNIT_TEST(cholesky)
ADD_PINOCCHIO_UNIT_TEST(contact-dynamics)
ADD_PINOCCHIO_UNIT_TEST(sample-models)
ADD_PINOCCHIO_UNIT_TEST(kinematics)

IF(urdfdom_FOUND)
  ADD_PINOCCHIO_UNIT_TEST(urdf)

  ADD_PINOCCHIO_UNIT_TEST(value)
  IF(hpp-fcl_FOUND)
    ADD_PINOCCHIO_UNIT_TEST(geom)
    ADD_PINOCCHIO_PARALLEL_UNIT_TEST(parallel-geometry)
    ADD_PINOCCHIO_UNIT_TEST(srdf)
  ENDIF(hpp-fcl_FOUND)
ENDIF(urdfdom_FOUND)

IF(BUILD_WITH_LIBPYTHON)
  ADD_PINOCCHIO_UNIT_TEST(python_parser PACKAGES eigenpy)
  TARGET_INCLUDE_DIRECTORIES(test-cpp-python_parser SYSTEM PUBLIC ${PYTHON_INCLUDE_DIRS})

  IF(BUILD_WITH_OPENMP_SUPPORT AND NOT LINK_PYTHON_INTERFACE_TO_OPENMP)
    TARGET_LINK_LIBRARIES(test-cpp-python_parser PRIVATE ${OpenMP_CXX_LIBRARIES})
  ENDIF()

  TARGET_LINK_LIBRARIES(test-cpp-python_parser PUBLIC ${PYWRAP})
  TARGET_LINK_LIBRARIES(test-cpp-python_parser PUBLIC ${PYTHON_LIBRARIES})
  SET(ENV_VARIABLES "PYTHONPATH=${CMAKE_BINARY_DIR}/bindings/python:$ENV{PYTHONPATH}")
  IF(WIN32)
    GET_FILENAME_COMPONENT(PYTHONHOME ${PYTHON_EXECUTABLE} PATH)
    LIST(APPEND ENV_VARIABLES "PYTHONHOME=${PYTHONHOME}")
    UNSET(PYTHONHOME)
  ENDIF(WIN32)
  IF(APPLE)
    LIST(APPEND ENV_VARIABLES "LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}")
    LIST(APPEND ENV_VARIABLES "DYLD_LIBRARY_PATH=$ENV{DYLD_LIBRARY_PATH}")
  ENDIF(APPLE)
  SET_PROPERTY(TEST test-cpp-python_parser PROPERTY ENVIRONMENT ${ENV_VARIABLES})
  ADD_SUBDIRECTORY(python)
ENDIF(BUILD_WITH_LIBPYTHON)

# Test over the joints
ADD_PINOCCHIO_UNIT_TEST(all-joints)
ADD_PINOCCHIO_UNIT_TEST(joint-revolute)
ADD_PINOCCHIO_UNIT_TEST(joint-prismatic)
ADD_PINOCCHIO_UNIT_TEST(joint-planar)
ADD_PINOCCHIO_UNIT_TEST(joint-free-flyer)
ADD_PINOCCHIO_UNIT_TEST(joint-spherical)
ADD_PINOCCHIO_UNIT_TEST(joint-translation)
ADD_PINOCCHIO_UNIT_TEST(joint-generic)
ADD_PINOCCHIO_UNIT_TEST(joint-composite)
ADD_PINOCCHIO_UNIT_TEST(joint-mimic)

ADD_PINOCCHIO_UNIT_TEST(model)
ADD_PINOCCHIO_UNIT_TEST(data)
ADD_PINOCCHIO_UNIT_TEST(constraint)
ADD_PINOCCHIO_UNIT_TEST(compute-all-terms)
ADD_PINOCCHIO_UNIT_TEST(energy)
ADD_PINOCCHIO_UNIT_TEST(frames)
IF(NOT MSVC AND NOT MSVC_VERSION)
  ADD_PINOCCHIO_UNIT_TEST(joint-configurations)
ENDIF()
ADD_PINOCCHIO_UNIT_TEST(explog)
ADD_PINOCCHIO_UNIT_TEST(finite-differences)
ADD_PINOCCHIO_UNIT_TEST(visitor)
ADD_PINOCCHIO_UNIT_TEST(algo-check)

ADD_PINOCCHIO_UNIT_TEST(liegroups)
ADD_PINOCCHIO_UNIT_TEST(cartesian-product-liegroups)
ADD_PINOCCHIO_UNIT_TEST(regressor)
ADD_PINOCCHIO_UNIT_TEST(version)
ADD_PINOCCHIO_UNIT_TEST(copy)
MAKE_DIRECTORY("${CMAKE_CURRENT_BINARY_DIR}/serialization-data")
ADD_PINOCCHIO_UNIT_TEST(serialization)
ADD_TEST_CFLAGS(serialization "-DTEST_SERIALIZATION_FOLDER=\\\\\"${CMAKE_CURRENT_BINARY_DIR}/serialization-data\\\\\"")

# Derivatives algo
ADD_PINOCCHIO_UNIT_TEST(kinematics-derivatives)
ADD_PINOCCHIO_UNIT_TEST(frames-derivatives)
ADD_PINOCCHIO_UNIT_TEST(rnea-derivatives)
ADD_PINOCCHIO_UNIT_TEST(rnea-second-order-derivatives)
ADD_PINOCCHIO_UNIT_TEST(aba-derivatives)
ADD_PINOCCHIO_UNIT_TEST(centroidal-derivatives)
ADD_PINOCCHIO_UNIT_TEST(center-of-mass-derivatives)
ADD_PINOCCHIO_UNIT_TEST(contact-dynamics-derivatives)

# Multiprecision arithmetic
IF(BUILD_ADVANCED_TESTING)
  ADD_PINOCCHIO_UNIT_TEST(multiprecision)
  SET_PROPERTY(TARGET test-cpp-multiprecision PROPERTY CXX_STANDARD 11)

  ADD_OPTIONAL_COMPILE_DEPENDENCY(gmp)
  ADD_OPTIONAL_COMPILE_DEPENDENCY(mpfr)

  IF(MPFR_FOUND)
    ADD_PINOCCHIO_UNIT_TEST(multiprecision-mpfr)
    PKG_CONFIG_USE_DEPENDENCY(test-cpp-multiprecision-mpfr gmp)
    PKG_CONFIG_USE_DEPENDENCY(test-cpp-multiprecision-mpfr mpfr)
    SET_PROPERTY(TARGET test-cpp-multiprecision-mpfr PROPERTY CXX_STANDARD 11)
  ENDIF(MPFR_FOUND)
ENDIF(BUILD_ADVANCED_TESTING)

# Automatic differentiation
MACRO(ADD_CPPAD_UNIT_TEST name)
  INCLUDE_DIRECTORIES(SYSTEM ${cppad_INCLUDE_DIR})
  ADD_PINOCCHIO_UNIT_TEST(${name} PACKAGES cppad)
  ADD_DEPENDENCIES(test-cppad test-cpp-${name})
  TARGET_LINK_LIBRARIES(test-cpp-${name} PUBLIC ${cppad_LIBRARY})
ENDMACRO()

MACRO(ADD_CPPADCG_UNIT_TEST name)
  INCLUDE_DIRECTORIES(SYSTEM ${cppad_INCLUDE_DIR})
  INCLUDE_DIRECTORIES(SYSTEM ${cppadcodegen_INCLUDE_DIR})
  ADD_PINOCCHIO_UNIT_TEST(${name} PACKAGES cppadcg)
  ADD_DEPENDENCIES(test-cppadcg test-cpp-${name})
  SET_PROPERTY(TARGET test-cpp-${name} PROPERTY CXX_STANDARD 11)
  TARGET_LINK_LIBRARIES(test-cpp-${name} PUBLIC ${cppad_LIBRARY} ${CMAKE_DL_LIBS})
ENDMACRO()

IF(BUILD_WITH_AUTODIFF_SUPPORT)
  ADD_CUSTOM_TARGET(test-cppad)
  SET_TARGET_PROPERTIES(test-cppad PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD True)

  ADD_CPPAD_UNIT_TEST(cppad-basic)
  ADD_CPPAD_UNIT_TEST(cppad-spatial)
  ADD_CPPAD_UNIT_TEST(cppad-joints)
  ADD_CPPAD_UNIT_TEST(cppad-algo)
  ADD_CPPAD_UNIT_TEST(cppad-algo-derivatives)
  ADD_CPPAD_UNIT_TEST(cppad-joint-configurations)

  IF(BUILD_WITH_CODEGEN_SUPPORT)
    ADD_CUSTOM_TARGET(test-cppadcg)
    SET_TARGET_PROPERTIES(test-cppadcg PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD True)

    ADD_CPPADCG_UNIT_TEST(cppadcg-basic)
    ADD_CPPADCG_UNIT_TEST(cppadcg-algo)
    ADD_CPPADCG_UNIT_TEST(cppadcg-joint-configurations)
  ENDIF(BUILD_WITH_CODEGEN_SUPPORT)

ENDIF(BUILD_WITH_AUTODIFF_SUPPORT)

MACRO(ADD_CASADI_UNIT_TEST name)
  ADD_PINOCCHIO_UNIT_TEST(${name} PACKAGES casadi)
  SET_PROPERTY(TARGET test-cpp-${name} PROPERTY CXX_STANDARD 11)
  TARGET_LINK_LIBRARIES(test-cpp-${name} PUBLIC casadi)
  ADD_DEPENDENCIES(test-casadi test-cpp-${name})
ENDMACRO()

IF(BUILD_WITH_CASADI_SUPPORT)
  ADD_CUSTOM_TARGET(test-casadi)
  SET_TARGET_PROPERTIES(test-casadi PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD True)

  ADD_CASADI_UNIT_TEST(casadi-basic)
  ADD_CASADI_UNIT_TEST(casadi-spatial)
  ADD_CASADI_UNIT_TEST(casadi-joints)
  ADD_CASADI_UNIT_TEST(casadi-algo)
  ADD_CASADI_UNIT_TEST(casadi-algo-derivatives)
ENDIF(BUILD_WITH_CASADI_SUPPORT)
