add_executable(hgraph_web_tests
    test_types.cpp
)
add_executable(hgraph_web_service_tests
    test_service.cpp
)
add_executable(hgraph_web_route_table_tests
    test_route_table.cpp
)
add_executable(hgraph_web_transport_tests
    test_service_transport.cpp
)
add_executable(hgraph_web_h2_engine_tests
    test_h2_engine.cpp
)
add_executable(hgraph_web_loopback_tests
    test_loopback.cpp
)
add_executable(hgraph_web_client_loopback_tests
    test_client_loopback.cpp
)
add_executable(hgraph_web_h2_loopback_tests
    test_h2_loopback.cpp
)
# Not a ctest target: a standalone server the h2spec conformance binary
# drives from CI (RFC 0024, h2 acceptance criteria).
add_executable(hgraph_web_h2spec_server
    h2spec_server.cpp
)
add_executable(hgraph_web_transport_perf
    transport_perf.cpp
)
target_compile_features(hgraph_web_transport_perf PRIVATE cxx_std_23)
target_link_libraries(hgraph_web_transport_perf PRIVATE hgraph::web)
target_include_directories(hgraph_web_transport_perf
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src)
if(MSVC)
    target_compile_options(hgraph_web_transport_perf PRIVATE /W4 /permissive-)
else()
    target_compile_options(hgraph_web_transport_perf PRIVATE -Wall -Wextra -Wpedantic)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    # This benchmark replaces global new/delete to count allocations. GCC can
    # pair an inlined replacement new with the replacement delete and report
    # a spurious mismatched-new-delete warning.
    target_compile_options(hgraph_web_transport_perf PRIVATE -Wno-mismatched-new-delete)
endif()
if(HGRAPH_ENABLE_TSAN AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
    target_compile_options(hgraph_web_h2spec_server PRIVATE -Wno-error=tsan)
    target_compile_options(hgraph_web_transport_perf PRIVATE -Wno-error=tsan)
endif()
target_compile_features(hgraph_web_h2spec_server PRIVATE cxx_std_23)
target_link_libraries(hgraph_web_h2spec_server PRIVATE hgraph::web)
# The loopback oracle is an independent Beast synchronous client, so this
# test target reaches the (otherwise PRIVATE) header-only Boost targets.
target_link_libraries(hgraph_web_loopback_tests
    PRIVATE ${HGRAPH_WEB_BOOST_TARGETS})
# The route table is an implementation detail of the extension, so its header
# is reached the same way the extension's own sources reach it.
target_include_directories(hgraph_web_route_table_tests
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src)
# The transport accounting is likewise src-internal; its teardown contract is
# unit-tested directly (late reserved completions after stop reject, not throw).
target_include_directories(hgraph_web_transport_tests
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src)
# The H2 engine test converses with the engine through a genuine nghttp2
# client session, so it links the same nghttp2 the extension uses.
target_include_directories(hgraph_web_h2_engine_tests
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../src)
target_include_directories(hgraph_web_h2_engine_tests SYSTEM PRIVATE
    $<TARGET_PROPERTY:${HGRAPH_WEB_NGHTTP2_TARGET},INTERFACE_INCLUDE_DIRECTORIES>)
target_compile_definitions(hgraph_web_h2_engine_tests PRIVATE
    $<TARGET_PROPERTY:${HGRAPH_WEB_NGHTTP2_TARGET},INTERFACE_COMPILE_DEFINITIONS>)
# The h2 loopback also carries a small independent nghttp2/TLS client for
# rejection/window-restoration behavior that the public call shape cannot
# express (an open stream plus DATA followed by request trailers).
target_include_directories(hgraph_web_h2_loopback_tests SYSTEM PRIVATE
    $<TARGET_PROPERTY:${HGRAPH_WEB_NGHTTP2_TARGET},INTERFACE_INCLUDE_DIRECTORIES>)
target_compile_definitions(hgraph_web_h2_loopback_tests PRIVATE
    $<TARGET_PROPERTY:${HGRAPH_WEB_NGHTTP2_TARGET},INTERFACE_COMPILE_DEFINITIONS>)
target_link_libraries(hgraph_web_h2_loopback_tests
    PRIVATE OpenSSL::SSL OpenSSL::Crypto ${HGRAPH_WEB_BOOST_TARGETS})

# A static hgraph_web propagates its private nghttp2 dependency as link-only;
# a shared hgraph_web consumes it internally, so tests that call nghttp2
# directly must add their own link-only dependency.
if(HGRAPH_WEB_LIBRARY_TYPE STREQUAL "SHARED_LIBRARY")
    target_link_libraries(hgraph_web_h2_engine_tests
        PRIVATE $<LINK_ONLY:${HGRAPH_WEB_NGHTTP2_TARGET}>)
    target_link_libraries(hgraph_web_h2_loopback_tests
        PRIVATE $<LINK_ONLY:${HGRAPH_WEB_NGHTTP2_TARGET}>)
endif()

foreach(target hgraph_web_tests hgraph_web_service_tests hgraph_web_route_table_tests hgraph_web_transport_tests hgraph_web_h2_engine_tests hgraph_web_loopback_tests hgraph_web_client_loopback_tests hgraph_web_h2_loopback_tests)
    target_compile_features(${target} PRIVATE cxx_std_23)
    target_link_libraries(${target} PRIVATE hgraph::web)

    if(MSVC)
        target_compile_options(${target} PRIVATE /W4 /permissive-)
    else()
        target_compile_options(${target} PRIVATE -Wall -Wextra -Wpedantic)
    endif()

    if(HGRAPH_ENABLE_TSAN AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
        target_compile_options(${target} PRIVATE -Wno-error=tsan)
    endif()

    add_test(NAME ${target} COMMAND ${target})
    if(COMMAND hgraph_configure_test_runtime_paths)
        hgraph_configure_test_runtime_paths(${target})
    endif()
endforeach()
