public async Task ShouldLogDisconnectAndRecover() { var log = new MemoryLog(); var clientDisconnected = 0; var clientConnected = 0; var serverConnected = 0; var config = new ConnectionConfiguration( onDisconnected: (e, exception) => { Interlocked.Increment(ref clientDisconnected); }, onConnected: (e, attempt, elapsed) => { Interlocked.Increment(ref clientConnected); }); var endpoint = TestConfig.ServerEndpoint(); using (var server = new TcpServer(endpoint.Ip.Port, TestConfig.Log) { OnConnected = () => Interlocked.Increment(ref serverConnected) }) using (new Connection(endpoint, config, log: log)) { for (var connectionAttempt = 1; connectionAttempt <= 4; connectionAttempt++) { var currentAttempt = connectionAttempt; await AssertAsync.ThatEventually(() => serverConnected == currentAttempt, () => $"server {serverConnected}, attempt {currentAttempt}"); await server.SendDataAsync(new ArraySegment <byte>(CreateCorrelationMessage(connectionAttempt))); TestConfig.Log.Write(LogLevel.Info, () => LogEvent.Create($"Sent CONNECTION attempt {currentAttempt}")); await AssertAsync.ThatEventually(() => clientConnected == currentAttempt, TimeSpan.FromMilliseconds(200), () => $"client {clientConnected}, attempt {currentAttempt}"); await AssertAsync.ThatEventually(() => log.LogEvents.Count(e => e.Item1 == LogLevel.Info && e.Item2.Message.StartsWith("Received 4 bytes (id ")) == currentAttempt, () => $"attempt {currentAttempt}\n" + log.ToString(LogLevel.Info)); TestConfig.Log.Write(LogLevel.Info, () => LogEvent.Create($"Dropping CONNECTION attempt {currentAttempt}")); server.DropConnection(); await AssertAsync.ThatEventually(() => clientDisconnected == currentAttempt, () => $"client {clientDisconnected}, attempt {currentAttempt}"); Assert.That(log.LogEvents.Count(e => e.Item1 == LogLevel.Info && e.Item2.Message.StartsWith("Disposing transport to")), Is.AtLeast(currentAttempt)); } } }
public async Task ShouldReconnectAfterLosingConnectionAndBeAbleToStartNewRead() { var log = TestConfig.Log; var endpoint = TestConfig.ServerEndpoint(); using (var server = new TcpServer(endpoint.Ip.Port, TestConfig.Log)) { var serverDisconnects = 0; var serverConnects = 0; var clientDisconnects = 0; var clientReads = 0; var clientBytesRead = 0; server.OnConnected = () => Interlocked.Increment(ref serverConnects); server.OnDisconnected = () => Interlocked.Increment(ref serverDisconnects); var config = new ConnectionConfiguration( onDisconnected: (e, exception) => Interlocked.Increment(ref clientDisconnects), onReading: (e, available) => Interlocked.Increment(ref clientReads), onRead: (e, read, elapsed) => Interlocked.Add(ref clientBytesRead, read)); using (var conn = new Connection(endpoint, config, log)) { await AssertAsync.ThatEventually(() => serverConnects > 0, () => $"connects {serverConnects}"); await AssertAsync.ThatEventually(() => clientReads > 0, TimeSpan.FromSeconds(1), () => $"reads {clientReads}"); server.DropConnection(); await AssertAsync.ThatEventually(() => clientDisconnects > 0, TimeSpan.FromSeconds(10), () => $"disconnects {clientDisconnects}"); Assert.That(clientBytesRead, Is.EqualTo(0), "client should not have received any bytes."); await AssertAsync.ThatEventually(() => serverConnects == 2, TimeSpan.FromSeconds(6), () => $"connects {serverConnects}"); await server.SendDataAsync(new ArraySegment <byte>(8.ToBytes())); await server.SendDataAsync(new ArraySegment <byte>(99.ToBytes())); await AssertAsync.ThatEventually(() => clientBytesRead == 8, TimeSpan.FromSeconds(1), () => $"bytes read {clientBytesRead}"); } } }
public async Task ShouldNotFinishPartiallyReadMessage() { var log = new MemoryLog(); var bytesRead = 0; var config = new ConnectionConfiguration(onReadBytes: (e, attempted, actual, elapsed) => Interlocked.Add(ref bytesRead, actual)); var endpoint = TestConfig.ServerEndpoint(); using (var server = new TcpServer(endpoint.Ip.Port, TestConfig.Log)) using (new Connection(endpoint, config, log)) { // send size var size = 200; await server.SendDataAsync(new ArraySegment <byte>(size.ToBytes())); var bytes = new byte[99]; new Random(42).NextBytes(bytes); var offset = 0; var correlationId = 200; foreach (var b in correlationId.ToBytes()) { bytes[offset++] = b; } // send half of payload await server.SendDataAsync(new ArraySegment <byte>(bytes, 0, 99)); await AssertAsync.ThatEventually(() => bytesRead >= bytes.Length, () => $"read {bytesRead}, length {bytes.Length}"); Assert.That(log.LogEvents.Count(e => e.Item1 == LogLevel.Warn && e.Item2.Message.StartsWith($"Unexpected response (id {correlationId}, {size}? bytes) from")), Is.EqualTo(1), log.ToString()); Assert.That(log.LogEvents.Count(e => e.Item1 == LogLevel.Debug && e.Item2.Message.StartsWith($"Received {size} bytes (id {correlationId})")), Is.EqualTo(0)); server.DropConnection(); await AssertAsync.ThatEventually(() => log.LogEvents.Count(e => e.Item1 == LogLevel.Warn && e.Item2.Message.StartsWith("Socket has been re-established, so recovery of the remaining of the current message is uncertain at best")) == 1, log.ToString); } }