project(lsltests
	VERSION 1.14.1
	LANGUAGES CXX
	DESCRIPTION "Unit tests for liblsl"
	)
cmake_minimum_required (VERSION 3.12)
enable_testing()
include(GNUInstallDirs)

option(LSL_BENCHMARKS "Enable benchmarks in unit tests" OFF)

# Default to system Catch2, but disable for macOS universal builds since
# Homebrew only installs for the host arch.
set(_lsl_prefer_system_catch2_default ON)
list(LENGTH CMAKE_OSX_ARCHITECTURES _lsl_n_osx_archs)
if(_lsl_n_osx_archs GREATER 1)
	set(_lsl_prefer_system_catch2_default OFF)
endif()
option(LSL_TESTS_PREFER_SYSTEM_CATCH2
	"Use system-installed Catch2 if found (auto-disabled for macOS universal builds)"
	${_lsl_prefer_system_catch2_default})
unset(_lsl_prefer_system_catch2_default)
unset(_lsl_n_osx_archs)

if(LSL_TESTS_PREFER_SYSTEM_CATCH2)
	find_package(Catch2 3 CONFIG QUIET)
endif()
if(NOT TARGET Catch2::Catch2)
	include(FetchContent)
	FetchContent_Declare(
			Catch2
			GIT_REPOSITORY https://github.com/catchorg/Catch2.git
			GIT_TAG        v3.4.0 # or a later release
	)
	FetchContent_MakeAvailable(Catch2)
endif()


add_library(catch_main OBJECT catch_main.cpp)
target_compile_features(catch_main PUBLIC cxx_std_14)
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
	target_link_libraries(catch_main PUBLIC log)
endif()
find_package(Threads REQUIRED)
target_link_libraries(catch_main
	PUBLIC
		Threads::Threads
		Catch2::Catch2
)

target_compile_definitions(catch_main PRIVATE LSL_VERSION_INFO="${LSL_VERSION_INFO}")
if(LSL_BENCHMARKS)
	target_compile_definitions(catch_main PUBLIC CATCH_CONFIG_ENABLE_BENCHMARKING)
endif()

add_library(common OBJECT
	common/bytecmp.cpp
	common/bytecmp.hpp
	common/create_streampair.hpp
	common/lsltypes.hpp
)
target_compile_features(common PUBLIC cxx_std_14)
target_include_directories(common PUBLIC
	$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../src>
)
target_link_libraries(common PUBLIC Catch2::Catch2)


add_executable(lsl_test_exported
	ext/DataType.cpp
	ext/discovery.cpp
	ext/move.cpp
	ext/streaminfo.cpp
	ext/time.cpp
)
target_link_libraries(lsl_test_exported PRIVATE lsl common catch_main)


set(LSL_TEST_INTERNAL_SRCS
		int/inireader.cpp
		int/network.cpp
		int/stringfuncs.cpp
		int/streaminfo.cpp
		int/samples.cpp
		int/postproc.cpp
		int/serialization_v100.cpp
		int/tcpserver.cpp
		int/sendbuffer.cpp
)
if(NOT MINGW)
	LIST(APPEND LSL_INTERNAL_SRCS int/loguruthreadnames.cpp)
endif()
message(STATUS ${LSL_TEST_INTERNAL_SRCS})
add_executable(lsl_test_internal ${LSL_TEST_INTERNAL_SRCS})
target_link_libraries(lsl_test_internal PRIVATE lslobj lslboost common catch_main)
# Internal tests need pugixml headers (lslobj links pugixml privately)
if(LSL_PUGIXML_IS_FETCHED)
    target_include_directories(lsl_test_internal PRIVATE ${pugixml_SOURCE_DIR}/src)
else()
    target_link_libraries(lsl_test_internal PRIVATE pugixml::pugixml)
endif()
# Pretend that lsl_test_internal is part of a shared lib so that it can use the __export symbols lslobj. REQ by MinGW.
target_compile_definitions(lsl_test_internal PRIVATE LIBLSL_EXPORTS)

# runtime_config test needs a fresh api_config singleton, so it lives in its own executable.
add_executable(lsl_test_runtime_config int/runtime_config.cpp)
target_link_libraries(lsl_test_runtime_config PRIVATE lslobj lslboost common catch_main)
target_compile_definitions(lsl_test_runtime_config PRIVATE LIBLSL_EXPORTS)

if(LSL_BENCHMARKS)
	# to get somewhat reproducible performance numbers:
	# /usr/bin/time -v testing/lsl_test_exported --benchmark-samples 100  bounce
	# [unix only]     |   binary                |    nr. of samples      | test name
	target_sources(lsl_test_exported PRIVATE
		ext/bench_bounce.cpp
		ext/bench_common.cpp
		ext/bench_pushpull.cpp
	)
	target_sources(lsl_test_internal PRIVATE
		int/bench_sleep.cpp
		int/bench_timesync.cpp
	)
endif()

set(LSL_TESTS lsl_test_exported lsl_test_internal lsl_test_runtime_config)
foreach(lsltest ${LSL_TESTS})
	add_test(NAME ${lsltest} COMMAND ${lsltest} --wait-for-keypress never)
	if(LSL_INSTALL)
		install(TARGETS ${lsltest} RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
	endif()

#	# Uncomment me if debugging tests on Windows. Commented because it does not work well on CI runners.
#	if(WIN32)
#		# Copy dependencies into build directory to enable debugging builds in Windows.
#		add_custom_command(TARGET ${lsltest}
#			POST_BUILD
#			COMMAND
#				${CMAKE_COMMAND} -E copy_if_different
#					$<TARGET_RUNTIME_DLLS:${lsltest}>
#					$<TARGET_FILE_DIR:${lsltest}>
#			COMMAND_EXPAND_LISTS
#		)
#	endif(WIN32)
endforeach()

if(LSL_INSTALL)
	install(DIRECTORY lslcfgs DESTINATION "${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}")
endif()
