From 5c4e8be20a38ad47db4748c2213bd4aed8a8f2cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6nke=20Ludwig?= Date: Tue, 17 Mar 2020 14:23:17 +0100 Subject: [PATCH] Add tests for TCP shutdown procedure and connection state handling. --- source/eventcore/socket.d | 9 ++-- tests/0-tcp.d | 104 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 3 deletions(-) diff --git a/source/eventcore/socket.d b/source/eventcore/socket.d index 0dc573f..5f4dfe3 100644 --- a/source/eventcore/socket.d +++ b/source/eventcore/socket.d @@ -64,7 +64,7 @@ void read(alias callback)(ref StreamSocket socket, ubyte[] buffer, IOMode mode) } eventDriver.sockets.read(socket.m_fd, buffer, mode, &cb); } -void cancelRead(ref StreamSocket socket) { eventDriver.sockets.cancelRead(socket.m_fd); } +void cancelRead(ref StreamSocket socket) @safe nothrow { eventDriver.sockets.cancelRead(socket.m_fd); } void waitForData(alias callback)(ref StreamSocket socket) { void cb(StreamSocketFD, IOStatus status, size_t nbytes) @safe nothrow { @@ -79,8 +79,11 @@ void write(alias callback)(ref StreamSocket socket, const(ubyte)[] buffer, IOMod } eventDriver.sockets.write(socket.m_fd, buffer, mode, &cb); } -void cancelWrite(ref StreamSocket socket) { eventDriver.sockets.cancelWrite(socket.m_fd); } -void shutdown(ref StreamSocket socket, bool shut_read = true, bool shut_write = true) { eventDriver.sockets.shutdown(socket.m_fd, shut_read, shut_write); } +void cancelWrite(ref StreamSocket socket) @safe nothrow { eventDriver.sockets.cancelWrite(socket.m_fd); } +void shutdown(ref StreamSocket socket, bool shut_read = true, bool shut_write = true) +@safe nothrow { + eventDriver.sockets.shutdown(socket.m_fd, shut_read, shut_write); +} struct StreamListenSocket { diff --git a/tests/0-tcp.d b/tests/0-tcp.d index ebda137..685f267 100644 --- a/tests/0-tcp.d +++ b/tests/0-tcp.d @@ -15,6 +15,15 @@ bool s_done; void main() { + testBasicExchange(); + testShutdown(); +} + +void testBasicExchange() +{ + print("Basic test:"); + print(""); + // watchdog timer in case of starvation/deadlocks auto tm = eventDriver.timers.create(); eventDriver.timers.set(tm, 10000.msecs, 0.msecs); @@ -92,3 +101,98 @@ void main() assert(s_done); s_done = false; } + +void testShutdown() +{ + static ubyte[10] srbuf, crbuf; + + print(""); + print("Shutdown test:"); + print(""); + + // watchdog timer in case of starvation/deadlocks + auto tm = eventDriver.timers.create(); + eventDriver.timers.set(tm, 10000.msecs, 0.msecs); + eventDriver.timers.wait(tm, (tm) { assert(false, "Test hung."); }); + + auto baddr = new InternetAddress(0x7F000001, 40001); + auto server = listenStream(baddr); + + StreamSocket client; + StreamSocket incoming; + + server.waitForConnections!((sock, addr) { + incoming = sock; + assert(incoming.state == ConnectionState.connected); + + print("Server read"); + ubyte[10] buf; + incoming.read!((rstatus, bytes) { + print("Server read done %s", bytes); + assert(rstatus == IOStatus.disconnected); + assert(bytes == 4); + assert(srbuf[0 .. 4] == [1, 2, 3, 4]); + assert(incoming.state == ConnectionState.passiveClose); + + print("Server write 4 bytes"); + incoming.write!((wstatus, bytes) { + print("Server write done"); + assert(wstatus == IOStatus.ok); + assert(bytes == 4); + print("Shutdown server write"); + incoming.shutdown(false, true); + assert(incoming.state == ConnectionState.closed); + print("Attempt server write after shutdown"); + incoming.write!((wstatus, bytes) { + print("Attempted server write done"); + assert(wstatus == IOStatus.disconnected); + assert(bytes == 0); + })([1], IOMode.all); + })([5, 6, 7, 8], IOMode.all); + })(srbuf, IOMode.all); + }); + + print("Connect..."); + connectStream!((sock, status) { + client = sock; + assert(client.state == ConnectionState.connected); + + print("Client write 4 bytes"); + client.write!((wstatus, bytes) { + print("Client write done"); + assert(wstatus == IOStatus.ok); + assert(bytes == 4); + print("Shutdown client write"); + client.shutdown(false, true); + assert(client.state == ConnectionState.activeClose); + print("Attempt client write after shutdown"); + client.write!((wstatus, bytes) { + print("Attempted client write done"); + assert(wstatus == IOStatus.disconnected); + assert(bytes == 0); + + print("Client read"); + client.read!((rstatus, bytes) { + print("Client read done"); + assert(rstatus == IOStatus.disconnected); + assert(bytes == 4); + assert(crbuf[0 .. 4] == [5, 6, 7, 8]); + assert(client.state == ConnectionState.closed); + + destroy(client); + destroy(incoming); + destroy(server); + s_done = true; + eventDriver.timers.stop(tm); + })(crbuf, IOMode.all); + })([1], IOMode.all); + })([1, 2, 3, 4], IOMode.all); + })(baddr); + + ExitReason er; + do er = eventDriver.core.processEvents(Duration.max); + while (er == ExitReason.idle); + assert(er == ExitReason.outOfWaiters); + assert(s_done); + s_done = false; +}