file(GLOB EngineTestsSources
    engine_tests.cpp
    engine/*.cpp)

file(GLOB ContractorTestsSources
    contractor_tests.cpp
    contractor/*.cpp)

file(GLOB ExtractorTestsSources
    extractor_tests.cpp
    extractor/*.cpp)

file(GLOB PartitionTestsSources
    partitioner_tests.cpp
    partitioner/*.cpp)

file(GLOB CustomizerTestsSources
    customizer_tests.cpp
    customizer/*.cpp)

file(GLOB UpdaterTestsSources
    updater_tests.cpp
    updater/*.cpp)

file(GLOB StorageTestsSources
    storage_tests.cpp
    storage/*.cpp)

file(GLOB LibraryTestsSources
    library_tests.cpp
    library/*.cpp)
list(REMOVE_ITEM LibraryTestsSources
    ${CMAKE_CURRENT_SOURCE_DIR}/library/contract.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/library/customize.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/library/extract.cpp
    ${CMAKE_CURRENT_SOURCE_DIR}/library/partition.cpp)

file(GLOB LibraryExtractTestsSources
    library_tests.cpp
    library/extract.cpp)

file(GLOB LibraryContractTestsSources
    library_tests.cpp
    library/contract.cpp)

file(GLOB LibraryCustomizeTestsSources
    library_tests.cpp
    library/customize.cpp)

file(GLOB LibraryPartitionTestsSources
    library_tests.cpp
    library/partition.cpp)

file(GLOB ServerTestsSources
    server_tests.cpp
    server/*.cpp)

file(GLOB UtilTestsSources
    util_tests.cpp
    util/*.cpp)

add_executable(engine-tests EXCLUDE_FROM_ALL
	${EngineTestsSources}
        $<TARGET_OBJECTS:ENGINE> $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:UTIL>)

add_executable(contractor-tests EXCLUDE_FROM_ALL
    ${ContractorTestsSources}
    $<TARGET_OBJECTS:CONTRACTOR> $<TARGET_OBJECTS:UPDATER> $<TARGET_OBJECTS:UTIL>)

add_executable(extractor-tests EXCLUDE_FROM_ALL
	${ExtractorTestsSources}
	$<TARGET_OBJECTS:EXTRACTOR> $<TARGET_OBJECTS:UTIL>)

add_executable(partitioner-tests EXCLUDE_FROM_ALL
	${PartitionTestsSources}
	$<TARGET_OBJECTS:PARTITIONER> $<TARGET_OBJECTS:UTIL>)

add_executable(customizer-tests EXCLUDE_FROM_ALL
    ${CustomizerTestsSources}
    $<TARGET_OBJECTS:CUSTOMIZER> $<TARGET_OBJECTS:UPDATER> $<TARGET_OBJECTS:UTIL>)

add_executable(updater-tests EXCLUDE_FROM_ALL
    ${UpdaterTestsSources}
    $<TARGET_OBJECTS:UPDATER> $<TARGET_OBJECTS:UPDATER> $<TARGET_OBJECTS:UTIL>)

add_executable(storage-tests EXCLUDE_FROM_ALL
    ${StorageTestsSources}
    $<TARGET_OBJECTS:STORAGE> $<TARGET_OBJECTS:UTIL>)

add_executable(library-tests EXCLUDE_FROM_ALL
	${LibraryTestsSources})

add_executable(library-extract-tests EXCLUDE_FROM_ALL
	${LibraryExtractTestsSources})

add_executable(library-contract-tests EXCLUDE_FROM_ALL
	${LibraryContractTestsSources})

add_executable(library-customize-tests EXCLUDE_FROM_ALL
    ${LibraryCustomizeTestsSources})

add_executable(library-partition-tests EXCLUDE_FROM_ALL
    ${LibraryPartitionTestsSources})

add_executable(server-tests EXCLUDE_FROM_ALL
	${ServerTestsSources}
	$<TARGET_OBJECTS:UTIL> $<TARGET_OBJECTS:SERVER>)

add_executable(util-tests EXCLUDE_FROM_ALL
	${UtilTestsSources}
        $<TARGET_OBJECTS:UTIL>)

if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 15)
    # TODO: remove after we stop supporting GCC 15, or when the false positive is fixed in GCC 15.
    set_property(TARGET util-tests PROPERTY INTERPROCEDURAL_OPTIMIZATION FALSE)
endif()

# vcpkg builds boost statically on every platform, so BOOST_TEST_DYN_LINK
# must never be defined — the dyn-link path expects a different
# unit_test_main() signature than the static library exports, and enabling
# it produces undefined references at link time.

set(UPDATER_TEST_DATA_DIR "${CMAKE_SOURCE_DIR}/unit_tests/updater")
set(TEST_DATA_DIR "${CMAKE_SOURCE_DIR}/test/data")

if (NOT WIN32)
  add_custom_target(test-data
    COMMAND make -C ${TEST_DATA_DIR} OSRM_BUILD_DIR=$ENV{OSRM_BUILD_DIR}
    COMMENT "Building test data in ${TEST_DATA_DIR}"
    VERBATIM)
  add_dependencies(test-data osrm-extract osrm-contract osrm-partition osrm-customize)
endif()


target_compile_definitions(extractor-tests PRIVATE OSRM_FIXTURES_DIR="${CMAKE_SOURCE_DIR}/unit_tests/fixtures")
target_compile_definitions(extractor-tests PRIVATE OSRM_PROFILES_DIR="${CMAKE_SOURCE_DIR}/profiles")
target_compile_definitions(library-tests PRIVATE OSRM_TEST_DATA_DIR="${TEST_DATA_DIR}")
target_compile_definitions(library-extract-tests PRIVATE OSRM_TEST_DATA_DIR="${TEST_DATA_DIR}")
target_compile_definitions(library-contract-tests PRIVATE OSRM_TEST_DATA_DIR="${TEST_DATA_DIR}")
target_compile_definitions(library-customize-tests PRIVATE OSRM_TEST_DATA_DIR="${TEST_DATA_DIR}")
target_compile_definitions(library-partition-tests PRIVATE OSRM_TEST_DATA_DIR="${TEST_DATA_DIR}")
target_compile_definitions(updater-tests PRIVATE TEST_DATA_DIR="${UPDATER_TEST_DATA_DIR}")
target_compile_definitions(contractor-tests PRIVATE TEST_DATA_DIR="${TEST_DATA_DIR}")
target_compile_definitions(storage-tests PRIVATE TEST_DATA_DIR="${TEST_DATA_DIR}")

target_include_directories(engine-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(library-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(library-extract-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(library-contract-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(library-customize-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(library-partition-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(util-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(partitioner-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(customizer-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(updater-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(contractor-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(storage-tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

target_link_libraries(engine-tests ${ENGINE_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} LibArchive::LibArchive)
target_link_libraries(extractor-tests osrm_extract ${EXTRACTOR_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(partitioner-tests osrm_partition ${PARTITIONER_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(customizer-tests osrm_customize ${CUSTOMIZER_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(updater-tests osrm_update ${UPDATER_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(library-tests osrm ${ENGINE_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(library-extract-tests osrm_extract ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(library-contract-tests osrm_contract ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(library-customize-tests osrm_customize ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(library-partition-tests osrm_partition ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(server-tests osrm ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
target_link_libraries(util-tests ${UTIL_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} LibArchive::LibArchive)
target_link_libraries(contractor-tests osrm_contract ${CONTRACTOR_LIBRARIES} ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} LibArchive::LibArchive)
target_link_libraries(storage-tests osrm_store ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} LibArchive::LibArchive)

# Register unit test executables with CTest.
# Each test uses a fixture so that ctest automatically builds the executable
# (and test data where needed) before running it.
set(TEST_TARGETS
    engine-tests
    contractor-tests
    extractor-tests
    partitioner-tests
    customizer-tests
    updater-tests
    storage-tests
    library-tests
    library-extract-tests
    library-contract-tests
    library-customize-tests
    library-partition-tests
    server-tests
    util-tests
)

# Tests that need the monaco extraction test data
set(LIBRARY_TEST_TARGETS
    library-tests
    library-extract-tests
    library-contract-tests
    library-customize-tests
    library-partition-tests
)

foreach(t ${TEST_TARGETS})
    # Build step: compile the test executable
    add_test(NAME ${t}-build
        COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${t} --config $<CONFIG>)
    set_tests_properties(${t}-build PROPERTIES FIXTURES_SETUP ${t}-fixture)

    # Run step: execute the test
    add_test(NAME ${t} COMMAND $<TARGET_FILE:${t}>)
    set_tests_properties(${t} PROPERTIES FIXTURES_REQUIRED ${t}-fixture)
endforeach()

# Build test data before running the library tests that need it
if (NOT WIN32)
    add_test(NAME test-data-build
        COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target test-data --config $<CONFIG>)
    set_tests_properties(test-data-build PROPERTIES FIXTURES_SETUP test-data-fixture)

    foreach(t ${LIBRARY_TEST_TARGETS})
        set_tests_properties(${t} PROPERTIES FIXTURES_REQUIRED "${t}-fixture;test-data-fixture")
    endforeach()
endif()

if(BUILD_AS_SUBPROJECT)
  add_custom_target(osrm_tests
	DEPENDS ${TEST_TARGETS})
else()
  add_custom_target(tests
	DEPENDS ${TEST_TARGETS})
endif()

if (NOT WIN32)
  if(BUILD_AS_SUBPROJECT)
    add_dependencies(osrm_tests test-data)
  else()
    add_dependencies(tests test-data)
  endif()

  foreach(t ${LIBRARY_TEST_TARGETS})
    add_dependencies(${t} test-data)
  endforeach()
endif()

# Provide a 'check' target that builds everything then runs ctest.
add_custom_target(check
  DEPENDS ${TEST_TARGETS}
  COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
  COMMENT "Build tests and run ctest"
)
