add_library(libSceNet SHARED EXCLUDE_FROM_ALL Export.cpp)
target_include_directories(libSceNet PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(libSceNet PRIVATE libSceNetCtl)
configure_windows_unwind(libSceNet)

if(BUILD_TESTING)
    add_test_executable(net_ipv6only_patched_tests tests/Ipv6OnlyPatched.cpp
        ${LIBS_INCLUDE_DIR}/nid/src/NidCompute.cpp
        ${LIBS_INCLUDE_DIR}/nid/src/Sha1.cpp)
    target_include_directories(net_ipv6only_patched_tests PRIVATE ${LIBS_INCLUDE_DIR} ${LIBS_INCLUDE_DIR}/nid/include)
    target_link_libraries(net_ipv6only_patched_tests PRIVATE ${CMAKE_DL_LIBS})
    add_dependencies(net_ipv6only_patched_tests libs)
    if(MINGW)
        target_compile_options(net_ipv6only_patched_tests PRIVATE -fasynchronous-unwind-tables)
        target_link_options(net_ipv6only_patched_tests PRIVATE -static -static-libgcc -static-libstdc++)
    endif()
    add_test(NAME net_ipv6only_patched COMMAND net_ipv6only_patched_tests ${PATCHED_DIR})
    set_tests_properties(net_ipv6only_patched PROPERTIES TIMEOUT 20 SKIP_RETURN_CODE 77)
    add_test_executable(net_ipv6only_tests tests/Ipv6Only.cpp)
    target_include_directories(net_ipv6only_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(net_ipv6only_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(net_ipv6only_tests)
    add_test(NAME net_ipv6only COMMAND net_ipv6only_tests)
    set_tests_properties(net_ipv6only PROPERTIES TIMEOUT 20 SKIP_RETURN_CODE 77)
    if(WIN32)
        target_link_libraries(net_ipv6only_tests PRIVATE ws2_32)
        set_tests_properties(net_ipv6only PROPERTIES ENVIRONMENT_MODIFICATION
            "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
    endif()
    add_test_executable(guest_net_socket_state_tests ${LIBS_INCLUDE_DIR}/tests/GuestNetSocketState.cpp)
    target_include_directories(guest_net_socket_state_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(guest_net_socket_state_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(guest_net_socket_state_tests)
    add_test(NAME guest_net_socket_state COMMAND guest_net_socket_state_tests)
    set_tests_properties(guest_net_socket_state PROPERTIES TIMEOUT 20)
    if(WIN32)
        set_tests_properties(guest_net_socket_state PROPERTIES ENVIRONMENT_MODIFICATION
            "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
    endif()
    add_test_executable(guest_net_protocol_tests ${LIBS_INCLUDE_DIR}/tests/GuestNetProtocol.cpp)
    target_include_directories(guest_net_protocol_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(guest_net_protocol_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(guest_net_protocol_tests)
    add_test(NAME guest_net_protocol COMMAND guest_net_protocol_tests)
    set_tests_properties(guest_net_protocol PROPERTIES TIMEOUT 20)
    if(WIN32)
        set_tests_properties(guest_net_protocol PROPERTIES ENVIRONMENT_MODIFICATION
            "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
    endif()
    add_test_executable(net_dontwait_tests ${LIBS_INCLUDE_DIR}/tests/NetDontWait.cpp)
    target_include_directories(net_dontwait_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(net_dontwait_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(net_dontwait_tests)
    add_test_executable(guest_net_buffer_validation_tests ${LIBS_INCLUDE_DIR}/tests/GuestNetBufferValidation.cpp)
    target_include_directories(guest_net_buffer_validation_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(guest_net_buffer_validation_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(guest_net_buffer_validation_tests)
    add_test(NAME guest_net_buffer_validation COMMAND guest_net_buffer_validation_tests)
    set_tests_properties(guest_net_buffer_validation PROPERTIES TIMEOUT 20)
    if(WIN32)
        target_link_libraries(guest_net_buffer_validation_tests PRIVATE ws2_32)
        set_tests_properties(guest_net_buffer_validation PROPERTIES ENVIRONMENT_MODIFICATION
            "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
    endif()
    foreach(api IN ITEMS send sendto sendmsg recv recvfrom recvmsg duplex blocking)
        add_test(NAME net_dontwait_${api} COMMAND net_dontwait_tests ${api})
        set_tests_properties(net_dontwait_${api} PROPERTIES TIMEOUT 20)
        if(WIN32)
            set_tests_properties(net_dontwait_${api} PROPERTIES ENVIRONMENT_MODIFICATION
                "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
        endif()
    endforeach()
    add_test_executable(guest_net_boolean_readback_tests ${LIBS_INCLUDE_DIR}/tests/GuestNetBooleanReadback.cpp)
    target_include_directories(guest_net_boolean_readback_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(guest_net_boolean_readback_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(guest_net_boolean_readback_tests)
    add_test(NAME guest_net_boolean_readback COMMAND guest_net_boolean_readback_tests)
    set_tests_properties(guest_net_boolean_readback PROPERTIES TIMEOUT 20)
    if(WIN32)
        target_link_libraries(guest_net_boolean_readback_tests PRIVATE ws2_32)
        set_tests_properties(guest_net_boolean_readback PROPERTIES ENVIRONMENT_MODIFICATION
            "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
    endif()
    add_test_executable(net_blocking_send_tests ${LIBS_INCLUDE_DIR}/tests/NetBlockingSend.cpp)
    target_include_directories(net_blocking_send_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(net_blocking_send_tests PRIVATE libkernel libc libSceNetCtl)
    configure_windows_unwind(net_blocking_send_tests)
    if(WIN32)
        target_link_libraries(net_blocking_send_tests PRIVATE ws2_32)
    endif()
    foreach(api IN ITEMS send sendto sendmsg)
        add_test(NAME net_dontwait_blocking_${api} COMMAND net_blocking_send_tests ${api})
        set_tests_properties(net_dontwait_blocking_${api} PROPERTIES TIMEOUT 20)
        if(WIN32)
            set_tests_properties(net_dontwait_blocking_${api} PROPERTIES ENVIRONMENT_MODIFICATION
                "PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
        endif()
    endforeach()
    add_test_executable(guest_net_keepalive_tests ${LIBS_INCLUDE_DIR}/tests/GuestNetKeepalive.cpp)
    target_include_directories(guest_net_keepalive_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(guest_net_keepalive_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(guest_net_keepalive_tests)
    add_test(NAME guest_sce_net_keepalive COMMAND guest_net_keepalive_tests)
    set_tests_properties(guest_sce_net_keepalive PROPERTIES TIMEOUT 20)
    if(WIN32)
        target_link_libraries(guest_net_keepalive_tests PRIVATE ws2_32)
        set_tests_properties(guest_sce_net_keepalive PROPERTIES ENVIRONMENT_MODIFICATION
            "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
    endif()
    add_test_executable(guest_datagram_receive_tests ${LIBS_INCLUDE_DIR}/tests/GuestDatagramReceive.cpp)
    target_include_directories(guest_datagram_receive_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(guest_datagram_receive_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(guest_datagram_receive_tests)
    foreach(api IN ITEMS recv recvfrom sceNetRecv sceNetRecvfrom)
        add_test(NAME guest_datagram_${api} COMMAND guest_datagram_receive_tests ${api})
        set_tests_properties(guest_datagram_${api} PROPERTIES TIMEOUT 20)
        if(WIN32)
            set_tests_properties(guest_datagram_${api} PROPERTIES ENVIRONMENT_MODIFICATION
                "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
        endif()
    endforeach()
    add_test_executable(guest_net_dns_info_tests ${LIBS_INCLUDE_DIR}/tests/GuestNetDnsInfo.cpp)
    target_include_directories(guest_net_dns_info_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(guest_net_dns_info_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(guest_net_dns_info_tests)
    add_test(NAME guest_net_dns_info COMMAND guest_net_dns_info_tests)
    set_tests_properties(guest_net_dns_info PROPERTIES TIMEOUT 20)
    if(WIN32)
        set_tests_properties(guest_net_dns_info PROPERTIES ENVIRONMENT_MODIFICATION
            "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
    endif()
    add_test_executable(guest_refused_connect_tests ${LIBS_INCLUDE_DIR}/tests/GuestRefusedConnect.cpp)
    target_include_directories(guest_refused_connect_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(guest_refused_connect_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(guest_refused_connect_tests)
    add_test(NAME guest_refused_connect COMMAND guest_refused_connect_tests)
    set_tests_properties(guest_refused_connect PROPERTIES TIMEOUT 20)
    if(WIN32)
        set_tests_properties(guest_refused_connect PROPERTIES ENVIRONMENT_MODIFICATION
            "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
    endif()
    add_test_executable(guest_net_oob_inline_tests ${LIBS_INCLUDE_DIR}/tests/GuestNetOobInline.cpp)
    target_include_directories(guest_net_oob_inline_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(guest_net_oob_inline_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(guest_net_oob_inline_tests)
    add_test(NAME guest_net_oob_inline COMMAND guest_net_oob_inline_tests)
    set_tests_properties(guest_net_oob_inline PROPERTIES TIMEOUT 20)
    if(WIN32)
        target_link_libraries(guest_net_oob_inline_tests PRIVATE ws2_32)
        set_tests_properties(guest_net_oob_inline PROPERTIES ENVIRONMENT_MODIFICATION
            "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
    endif()
    if(WIN32)
        add_test_executable(guest_socket_host_write_tests ${LIBS_INCLUDE_DIR}/tests/GuestSocketHostWrite.cpp)
        target_include_directories(guest_socket_host_write_tests PRIVATE ${LIBS_INCLUDE_DIR})
        target_link_libraries(guest_socket_host_write_tests PRIVATE libSceNet libkernel libc)
        configure_windows_unwind(guest_socket_host_write_tests)
        foreach(api IN ITEMS recv recvfrom read sceKernelRead sceNetRecv sceNetRecvfrom sceNetRecvmsg)
            add_test(NAME guest_socket_host_write_${api}_udp COMMAND guest_socket_host_write_tests ${api})
            add_test(NAME guest_socket_host_write_${api}_tcp COMMAND guest_socket_host_write_tests ${api} tcp)
            set_tests_properties(guest_socket_host_write_${api}_udp guest_socket_host_write_${api}_tcp
                PROPERTIES TIMEOUT 20 ENVIRONMENT_MODIFICATION
                "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
        endforeach()
    endif()
    if(WIN32)
        add_test_executable(net_empty_stream_tests ${LIBS_INCLUDE_DIR}/tests/NetEmptyStream.cpp)
        target_include_directories(net_empty_stream_tests PRIVATE ${LIBS_INCLUDE_DIR})
        target_link_libraries(net_empty_stream_tests PRIVATE libSceNet libkernel libc)
        configure_windows_unwind(net_empty_stream_tests)
        foreach(api IN ITEMS recv recvfrom recvmsg)
            foreach(mode IN ITEMS empty dontwait peek nonblocking queued nullbuf errors datagram)
                add_test(NAME net_empty_stream_${api}_${mode} COMMAND net_empty_stream_tests ${api} ${mode})
                set_tests_properties(net_empty_stream_${api}_${mode} PROPERTIES TIMEOUT 20
                    ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
            endforeach()
        endforeach()
    endif()
    add_test_executable(guest_sce_net_tests ${LIBS_INCLUDE_DIR}/tests/GuestSceNet.cpp)
    target_include_directories(guest_sce_net_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(guest_sce_net_tests PRIVATE libSceNet libSceNetCtl libkernel libc)
    configure_windows_unwind(guest_sce_net_tests)
    add_test(NAME guest_sce_net COMMAND guest_sce_net_tests)
    add_test_executable(guest_net_thread_tests ${LIBS_INCLUDE_DIR}/tests/GuestNetThread.cpp)
    target_include_directories(guest_net_thread_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(guest_net_thread_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(guest_net_thread_tests)
    add_test(NAME guest_net_thread COMMAND guest_net_thread_tests)
    set_tests_properties(guest_net_thread PROPERTIES TIMEOUT 20)
    set_tests_properties(guest_sce_net PROPERTIES TIMEOUT 20 SKIP_RETURN_CODE 77)
    if(WIN32)
        target_link_libraries(guest_sce_net_tests PRIVATE ws2_32)
        set_tests_properties(guest_sce_net guest_net_thread PROPERTIES ENVIRONMENT_MODIFICATION
            "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
    endif()
    add_test_executable(guest_net_nodelay_readback_tests ${LIBS_INCLUDE_DIR}/tests/GuestNetNodelayReadback.cpp)
    target_include_directories(guest_net_nodelay_readback_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(guest_net_nodelay_readback_tests PRIVATE libSceNet libkernel libc)
    configure_windows_unwind(guest_net_nodelay_readback_tests)
    add_test(NAME guest_net_nodelay_readback COMMAND guest_net_nodelay_readback_tests)
    set_tests_properties(guest_net_nodelay_readback PROPERTIES TIMEOUT 20)
    if(WIN32)
        target_link_libraries(guest_net_nodelay_readback_tests PRIVATE ws2_32)
        set_tests_properties(guest_net_nodelay_readback PROPERTIES ENVIRONMENT_MODIFICATION
            "PATH=path_list_prepend:$<TARGET_FILE_DIR:libSceNet>")
    endif()
    add_test_executable(net_epoll_lifetime_tests ${LIBS_INCLUDE_DIR}/tests/NetEpollLifetime.cpp)
    target_include_directories(net_epoll_lifetime_tests PRIVATE ${LIBS_INCLUDE_DIR})
    target_link_libraries(net_epoll_lifetime_tests PRIVATE libkernel libc libSceNetCtl)
    configure_windows_unwind(net_epoll_lifetime_tests)
    if(WIN32)
        target_link_libraries(net_epoll_lifetime_tests PRIVATE ws2_32)
    endif()
    foreach(operation IN ITEMS reuse control close delete modify replace abort destroy)
        add_test(NAME net_epoll_lifetime_${operation} COMMAND net_epoll_lifetime_tests ${operation})
        set_tests_properties(net_epoll_lifetime_${operation} PROPERTIES TIMEOUT 20)
        if(WIN32)
            set_tests_properties(net_epoll_lifetime_${operation} PROPERTIES ENVIRONMENT_MODIFICATION
                "PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
        endif()
    endforeach()
endif()
