public async Task TestServiceConnectionWithNormalApplicationTask() { using (StartVerifiableLog(out var loggerFactory, LogLevel.Debug)) { 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 builder = new ConnectionBuilder(services.BuildServiceProvider()); builder.UseConnectionHandler <TestConnectionHandler>(); ConnectionDelegate handler = builder.Build(); var connection = new ServiceConnection(protocol, ccm, connectionFactory, loggerFactory, handler, ccf, "serverId", 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(); await transportConnection.Application.Output.WriteAsync( protocol.GetMessageBytes(new CloseConnectionMessage(clientConnectionId))); // Normal end with close message await ccm.WaitForClientConnectionRemovalAsync(clientConnectionId).OrTimeout(); // another connection comes in clientConnectionId = Guid.NewGuid().ToString(); await transportConnection.Application.Output.WriteAsync( protocol.GetMessageBytes(new OpenConnectionMessage(clientConnectionId, new Claim[] { }))); clientConnection = await ccm.WaitForClientConnectionAsync(clientConnectionId).OrTimeout(); // complete reading to end the connection transportConnection.Application.Output.Complete(); await connectionTask.OrTimeout(); Assert.Equal(ServiceConnectionStatus.Disconnected, connection.Status); Assert.Empty(ccm.ClientConnections); } }
public async Task TestServiceConnectionWithErrorApplicationTask() { using (StartVerifiableLog(out var loggerFactory, LogLevel.Warning, expectedErrors: c => true, logChecker: logs => { Assert.Equal(2, logs.Count); Assert.Equal("SendLoopStopped", logs[0].Write.EventId.Name); Assert.Equal("ApplicationTaskFailed", 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, "serverId", 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")); await clientConnection.LifetimeTask.OrTimeout(); // 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); } }