public async Task TestServiceConnectionWithErrorApplicationTask() { using (StartVerifiableLog(out var loggerFactory, LogLevel.Warning, expectedErrors: c => true, logChecker: logs => { Assert.Equal(2, logs.Count); Assert.Equal("ApplicationTaskFailed", logs[0].Write.EventId.Name); Assert.Equal("SendLoopStopped", logs[1].Write.EventId.Name); return(true); })) { var ccm = new TestClientConnectionManager(); var ccf = new ClientConnectionFactory(); var protocol = new ServiceProtocol(); TestConnection transportConnection = null; var connectionFactory = new TestConnectionFactory(conn => { transportConnection = conn; return(Task.CompletedTask); }); var services = new ServiceCollection(); var errorTcs = new TaskCompletionSource <Exception>(); var connectionHandler = new ErrorConnectionHandler(errorTcs); services.AddSingleton(connectionHandler); var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler <ErrorConnectionHandler>(); ConnectionDelegate handler = builder.Build(); var connection = new ServiceConnection(protocol, ccm, connectionFactory, loggerFactory, handler, ccf, Guid.NewGuid().ToString("N"), null, null); var connectionTask = connection.StartAsync(); // completed handshake await connection.ConnectionInitializedTask.OrTimeout(); Assert.Equal(ServiceConnectionStatus.Connected, connection.Status); var clientConnectionId = Guid.NewGuid().ToString(); await transportConnection.Application.Output.WriteAsync( protocol.GetMessageBytes(new OpenConnectionMessage(clientConnectionId, new Claim[] { }))); var clientConnection = await ccm.WaitForClientConnectionAsync(clientConnectionId).OrTimeout(); errorTcs.SetException(new InvalidOperationException("error operation")); // Should complete the connection when application throws await ccm.WaitForClientConnectionRemovalAsync(clientConnectionId).OrTimeout(); // Application task should not affect the underlying service connection Assert.Equal(ServiceConnectionStatus.Connected, connection.Status); // complete reading to end the connection transportConnection.Application.Output.Complete(); await connectionTask.OrTimeout(); Assert.Equal(ServiceConnectionStatus.Disconnected, connection.Status); Assert.Empty(ccm.ClientConnections); } }
/// <summary> /// Write a message to server connection. /// </summary> public async Task WriteMessageAsync(TestConnection context, ServiceMessage message) { SharedServiceProtocol.WriteMessage(message, context.Application.Output); await context.Application.Output.FlushAsync(); }
/// <summary> /// Allow sub-class to override. Do something after connect being created. /// </summary> protected virtual Task AfterConnectedAsync(TestConnection connection) { return(Task.CompletedTask); }
/// <summary> /// Allow sub-class to override the handshake behavior /// </summary> protected virtual async Task DoHandshakeAsync(TestConnection connection) { await HandshakeUtils.ReceiveHandshakeRequestAsync(connection.Application.Input); await HandshakeUtils.SendHandshakeResponseAsync(connection.Application.Output); }
private async Task HandshakeAsync(TestConnection connection) { await DoHandshakeAsync(connection); }
public async Task ClientConnectionContextAbortCanSendOutCloseMessage() { using (StartVerifiableLog(out var loggerFactory, LogLevel.Trace, expectedErrors: c => true, logChecker: logs => { return(true); })) { var ccm = new TestClientConnectionManager(); var ccf = new ClientConnectionFactory(); var protocol = new ServiceProtocol(); TestConnection transportConnection = null; var connectionFactory = new TestConnectionFactory(conn => { transportConnection = conn; return(Task.CompletedTask); }); var services = new ServiceCollection(); var lastWill = "This is the last will"; var connectionHandler = new LastWillConnectionHandler(lastWill); services.AddSingleton(connectionHandler); var builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler <LastWillConnectionHandler>(); ConnectionDelegate handler = builder.Build(); var connection = new ServiceConnection(protocol, ccm, connectionFactory, loggerFactory, handler, ccf, "serverId", Guid.NewGuid().ToString("N"), null, null, null, closeTimeOutMilliseconds: 500); var connectionTask = connection.StartAsync(); // completed handshake await connection.ConnectionInitializedTask.OrTimeout(); Assert.Equal(ServiceConnectionStatus.Connected, connection.Status); var clientConnectionId = Guid.NewGuid().ToString(); await transportConnection.Application.Output.WriteAsync( protocol.GetMessageBytes(new OpenConnectionMessage(clientConnectionId, new Claim[] { }))); var clientConnection = await ccm.WaitForClientConnectionAsync(clientConnectionId).OrTimeout(); await clientConnection.LifetimeTask.OrTimeout(); transportConnection.Transport.Output.Complete(); var input = await transportConnection.Application.Input.ReadAsync(); var buffer = input.Buffer; var canParse = protocol.TryParseMessage(ref buffer, out var msg); Assert.True(canParse); var message = msg as ConnectionDataMessage; Assert.NotNull(message); Assert.Equal(clientConnectionId, message.ConnectionId); Assert.Equal(lastWill, Encoding.UTF8.GetString(message.Payload.First.ToArray())); // complete reading to end the connection transportConnection.Application.Output.Complete(); // 1s for application task to timeout await connectionTask.OrTimeout(1000); Assert.Equal(ServiceConnectionStatus.Disconnected, connection.Status); Assert.Empty(ccm.ClientConnections); } }