# Test suite that has been moved from Tarantool repository in
# scope of https://github.com/tarantool/tarantool/issues/4478.

add_custom_target(tarantool-tests-libs
  DEPENDS libluajit
)

macro(BuildTestCLib lib source dependent_tests)
  AddTestLib(${lib} ${source})
  add_dependencies(tarantool-tests-libs ${lib})
  # Remember libraries for each test to be proceeded with after
  # test targets are created.
  foreach(testname ${dependent_tests})
    set(LIBS_${testname}
      "${CMAKE_CURRENT_BINARY_DIR};${LIBS_${testname}}" PARENT_SCOPE
    )
  endforeach()
endmacro()

# FIXME: This is used only due to ancient CMake requirements.
# If we update to CMake >= 3.22, we can use
# ENVIRONMENT_MODIFICATION [1] instead.
# [1]: https://cmake.org/cmake/help/latest/prop_test/ENVIRONMENT_MODIFICATION.html
# This macro appends to the given test's environment variable the
# given value. If the variable doesn't exist, it is created equal
# to the given argument.
macro(AppendTestEnvVar testname var value)
  get_test_property(${testname} ENVIRONMENT old_env)
  foreach(loopvar ${old_env})
    # XXX: `foreach()` unescapes ";" in string, escape them back.
    string(REPLACE ";" "\;" loopvar "${loopvar}")
    if("${loopvar}" MATCHES "^${var}=(.*)")
      set(envvar_found TRUE)
      set(loopvar "${var}=${value}${CMAKE_MATCH_1}")
    endif()
    list(APPEND new_env "${loopvar}")
  endforeach()
  if(NOT "${envvar_found}")
    list(APPEND new_env "${var}=${value}")
  endif()
  set_tests_properties(${testname} PROPERTIES ENVIRONMENT "${new_env}")

  unset(envvar_found)
  unset(old_env)
  unset(new_env)
endmacro()

add_subdirectory(ffi-ccall)
add_subdirectory(fix-bit-shift-generation)
add_subdirectory(gh-4427-ffi-sandwich)
add_subdirectory(gh-6098-fix-side-exit-patching-on-arm64)
add_subdirectory(gh-6189-cur_L)
add_subdirectory(lj-416-xor-before-jcc)
add_subdirectory(lj-522-fix-dlerror-return-null)
add_subdirectory(lj-549-bytecode-loader)
add_subdirectory(lj-551-bytecode-c-broken-macro)
add_subdirectory(lj-601-fix-gc-finderrfunc)
add_subdirectory(lj-727-lightuserdata-itern)
add_subdirectory(lj-802-panic-at-mcode-protfail)
add_subdirectory(lj-flush-on-trace)
add_subdirectory(lj-1004-oom-error-frame)
add_subdirectory(lj-1066-fix-cur_L-after-coroutine-resume)
add_subdirectory(profilers/gh-5813-resolving-of-c-symbols/both)
add_subdirectory(profilers/gh-5813-resolving-of-c-symbols/gnuhash)
add_subdirectory(profilers/gh-5813-resolving-of-c-symbols/hash)
add_subdirectory(profilers/gh-5813-resolving-of-c-symbols/stripped)

# Module for alloc injections to return OOM for allocations.
add_subdirectory(utils)

if(BUILDMODE STREQUAL "dynamic")
  add_subdirectory(fix-argv-handling)
endif()

# JIT, profiler, and bytecode toolchains are located in the <src/>
# directory, <jit/vmdef.lua> is the autogenerated file also
# located in the <src/> directory, but in the scope of the binary
# artifacts tree, and auxiliary tests-related modules are located
# in the current directory (but tests are run in the binary
# directory), so LUA_PATH needs to be updated.
make_lua_path(LUA_PATH
  PATHS
    ${CMAKE_CURRENT_SOURCE_DIR}/?.lua
    ${CMAKE_CURRENT_SOURCE_DIR}/?/init.lua
    ${LUAJIT_SOURCE_DIR}/?.lua
    ${LUAJIT_BINARY_DIR}/?.lua
)

set(LUA_TEST_SUFFIX .test.lua)

# FIXME: This is needed for disabling some flaky tests (like
# profilers), until LuaJIT/LuaJIT#606 will not be resolved.
if(LUAJIT_ENABLE_TABLE_BUMP)
  list(APPEND LUA_TEST_ENV_MORE LUAJIT_TABLE_BUMP=1)
endif()

if(LUAJIT_DISABLE_SYSPROF)
  list(APPEND LUA_TEST_ENV_MORE LUAJIT_DISABLE_SYSPROF=1)
endif()

if(LUAJIT_DISABLE_MEMPROF)
  list(APPEND LUA_TEST_ENV_MORE LUAJIT_DISABLE_MEMPROF=1)
endif()

# Needed to skip some long tests or tests using signals.
# See also https://github.com/tarantool/tarantool/issues/10803.
if(LUAJIT_USE_VALGRIND)
  list(APPEND LUA_TEST_ENV_MORE LUAJIT_TEST_USE_VALGRIND=1)
endif()

# Needed to skip the <fix-argv-handling.test.lua> for a
# non-dynamic build.
if(BUILDMODE STREQUAL "dynamic")
  list(APPEND LUA_TEST_ENV_MORE LUAJIT_BUILDMODE=dynamic)
endif()

set(TEST_SUITE_NAME "tarantool-tests")

# XXX: The call produces both test and target
# <tarantool-tests-deps> as a side effect.
add_test_suite_target(tarantool-tests
  LABELS ${TEST_SUITE_NAME}
  DEPENDS ${LUAJIT_TEST_DEPS} tarantool-tests-libs
)

file(GLOB_RECURSE tests ${CMAKE_CURRENT_SOURCE_DIR} "*${LUA_TEST_SUFFIX}")
foreach(test_path ${tests})
  file(RELATIVE_PATH test_name ${CMAKE_CURRENT_SOURCE_DIR} ${test_path})
  set(test_title "test/${TEST_SUITE_NAME}/${test_name}")
  add_test(NAME ${test_title}
    COMMAND ${LUAJIT_TEST_COMMAND} ${test_path}
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
  )
  set_tests_properties(${test_title} PROPERTIES
    # LUA_CPATH and LD_LIBRARY_PATH variables and also
    # dependencies list with libraries are set in scope of
    # BuildTestLib macro.
    ENVIRONMENT "LUA_PATH=${LUA_PATH};${LUA_TEST_ENV_MORE}"
    LABELS ${TEST_SUITE_NAME}
    DEPENDS tarantool-tests-deps
  )

  # The part of the profilers toolchain is located in the <tools/>
  # directory, so LUA_PATH needs to be updated.
  if(test_name MATCHES "^profilers")
    AppendTestEnvVar(${test_title}
      LUA_PATH "${PROJECT_SOURCE_DIR}/tools/?.lua\;"
    )
  endif()

  if(LIBS_${test_name})
    foreach(path ${LIBS_${test_name}})
      # Add the directory where the library is built to the list
      # with entries for the LUA_CPATH environment variable, so
      # LuaJIT can find and load it.
      AppendTestEnvVar(${test_title}
        LUA_CPATH "${path}/?${CMAKE_SHARED_LIBRARY_SUFFIX}\;"
      )
      # Also, add this directory to the LD_LIBRARY_PATH environment
      # variable so FFI machinery can find and load it.
      # XXX: Be noticed that we shouldn't use `"` here to wrap the
      # variable's content. If we do this, the variable value will
      # contain `"` at the beginning and the end, so this `"` at the
      # beginning will be treated as the directory for the entry.
      # XXX: Since the auxiliary libraries are built as dynamically
      # loaded modules on MacOS instead of shared libraries as it is
      # done on Linux and BSD, another environment variable should
      # be used to guide <ffi.load> while searching the extension.
      if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
        AppendTestEnvVar(${test_title} DYLD_LIBRARY_PATH ${path}:)
      else()
        AppendTestEnvVar(${test_title} LD_LIBRARY_PATH ${path}:)
      endif()
    endforeach()

    unset(LIBS_${test_name})
  endif()
endforeach()

# Some tests use `LD_PRELOAD` to mock system calls (like
# <lj-802-panic-at-mcode-protfail.test.lua> overwrites
# `mprotect()`). When compiling with ASan support under GCC, it is
# required that the ASan library go first in the `LD_PRELOAD`
# list. Set it manually. The test will append it to the executed
# process.
if(LUAJIT_USE_ASAN AND CMAKE_C_COMPILER_ID STREQUAL "GNU")
  LibRealPath(LIB_ASAN libasan.so)
  AppendTestEnvVar(
    "test/${TEST_SUITE_NAME}/lj-522-fix-dlerror-return-null.test.lua"
    LD_PRELOAD ${LIB_ASAN}
  )
  AppendTestEnvVar(
    "test/${TEST_SUITE_NAME}/lj-802-panic-at-mcode-protfail.test.lua"
    LD_PRELOAD ${LIB_ASAN}
  )
endif()
