# ---------------------------------------------------------------
# First search cmocka and automatically download if necessary
# ---------------------------------------------------------------
find_package(cmocka QUIET)

if(NOT cmocka_FOUND)
  message(
    STATUS
      "[arraylist] cmocka was not fount in the system — downloading with FetchContent..."
  )

  include(FetchContent)
  FetchContent_Declare(
    cmocka
    GIT_REPOSITORY https://git.cryptomilk.org/projects/cmocka.git
    GIT_TAG cmocka-1.1.7
    GIT_SHALLOW TRUE)

  set(WITH_STATIC_LIB
      ON
      CACHE BOOL "" FORCE)
  set(WITH_SHARED_LIB
      OFF
      CACHE BOOL "" FORCE)
  set(WITH_CMOCKERY_SUPPORT
      OFF
      CACHE BOOL "" FORCE)
  set(WITH_EXAMPLES
      OFF
      CACHE BOOL "" FORCE)
  set(UNIT_TESTING
      OFF
      CACHE BOOL "" FORCE)
  set(PICKY_DEVELOPER
      OFF
      CACHE BOOL "" FORCE)

  FetchContent_MakeAvailable(cmocka)

  # cmocka can export its target as "cmocka" or "cmocka-static" create alias if
  # it doesnt exist
  if(NOT TARGET cmocka::cmocka)
    if(TARGET cmocka-static)
      add_library(cmocka::cmocka ALIAS cmocka-static)
    elseif(TARGET cmocka)
      add_library(cmocka::cmocka ALIAS cmocka)
    else()
      message(
        WARNING
          "[arraylist] cmocka::cmocka target could not be tested — skipping tests"
      )
      return()
    endif()
  endif()
endif()

# ---------------------------------------------------------------
# Verifiy ASAN support
# ---------------------------------------------------------------
set(ARRAYLIST_USE_ASAN OFF)

if(ARRAYLIST_ENABLE_SANITIZERS)
  if(MSVC)
    if(MSVC_VERSION GREATER_EQUAL 1928)
      set(ARRAYLIST_USE_ASAN ON)
    else()
      message(
        STATUS
          "[arraylist] MSVC < 16.9 doesnt support ASAN — sanitizers deactivated."
      )
    endif()
  elseif(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang" AND NOT WIN32)
    include(CheckCCompilerFlag)
    check_c_compiler_flag(-fsanitize=address ARRAYLIST_COMPILER_HAS_ASAN)
    if(ARRAYLIST_COMPILER_HAS_ASAN)
      set(ARRAYLIST_USE_ASAN ON)
    else()
      message(
        STATUS
          "[arraylist] Compiler doesnt support -fsanitize=address — sanitizers deactivated."
      )
    endif()
  else()
    message(
      STATUS
        "[arraylist] Platform/compiler doesnt support ASAN — sanitizers deactivated."
    )
  endif()

  if(ARRAYLIST_USE_ASAN)
    message(STATUS "[arraylist] ASAN Enabled for tests")
  endif()
endif()

# ---------------------------------------------------------------
# Test execuatable
# ---------------------------------------------------------------
add_executable(test_arraylist test_arraylist.c)

target_link_libraries(test_arraylist PRIVATE arraylist cmocka::cmocka)

# Same as lib
target_compile_features(test_arraylist PRIVATE c_std_11)

# Apply asan
if(ARRAYLIST_USE_ASAN)
  if(MSVC)
    target_compile_options(test_arraylist PRIVATE /fsanitize=address)
  else()
    target_compile_options(test_arraylist PRIVATE -fsanitize=address
                                                  -fno-omit-frame-pointer)
    target_link_options(test_arraylist PRIVATE -fsanitize=address)
  endif()
endif()

# ---------------------------------------------------------------
# Register with CTests
# ---------------------------------------------------------------
add_test(NAME arraylist_tests COMMAND test_arraylist)

set_tests_properties(arraylist_tests PROPERTIES TIMEOUT 30)
