public async Task ServiceConnectionWithTransportLayerClosedShouldCleanupEndlessConnectClientConnections()
        {
            using (StartVerifiableLog(out var loggerFactory, LogLevel.Debug, expectedErrors: c => true, logChecker:
                                      logs =>
            {
                var errorLogs = logs.Where(s => s.Write.LogLevel == LogLevel.Error).ToList();
                Assert.Single(errorLogs);
                Assert.Equal("ApplicationTaskTimedOut", errorLogs[0].Write.EventId.Name);

                return(true);
            }))
            {
                var hubConfig = Utility.GetActualHubConfig(loggerFactory);
                var appName   = "app1";
                var hub       = "EndlessConnect";
                var scm       = new TestServiceConnectionHandler();
                hubConfig.Resolver.Register(typeof(IServiceConnectionManager), () => scm);
                var ccm = new ClientConnectionManager(hubConfig, loggerFactory);
                hubConfig.Resolver.Register(typeof(IClientConnectionManager), () => ccm);
                DispatcherHelper.PrepareAndGetDispatcher(new TestAppBuilder(), hubConfig,
                                                         new ServiceOptions {
                    ConnectionString = ConnectionString
                }, appName, loggerFactory);
                using (var proxy = new TestServiceConnectionProxy(ccm, loggerFactory))
                {
                    // start the server connection
                    var connectionTask = proxy.StartAsync();
                    await proxy.ConnectionInitializedTask.OrTimeout();

                    var clientConnection = Guid.NewGuid().ToString("N");

                    var connectTask = scm.WaitForTransportOutputMessageAsync(typeof(GroupBroadcastDataMessage))
                                      .OrTimeout();
                    // Application layer sends OpenConnectionMessage
                    var openConnectionMessage = new OpenConnectionMessage(clientConnection, new Claim[0], null,
                                                                          $"?transport=webSockets&connectionToken=conn1&connectionData=%5B%7B%22name%22%3A%22{hub}%22%7D%5D");
                    await proxy.WriteMessageAsync(openConnectionMessage);

                    var connectMessage = (await connectTask)as GroupBroadcastDataMessage;
                    Assert.NotNull(connectMessage);
                    Assert.Equal($"hg-{hub}.note", connectMessage.GroupName);

                    var message = connectMessage.Payloads["json"]
                                  .GetJsonMessageFromSingleFramePayload <HubResponseItem>();

                    Assert.Equal("Connected", message.A[0]);

                    // close transport layer
                    proxy.TestConnectionContext.Application.Output.Complete();

                    // wait for application task to timeout
                    await proxy.WaitForConnectionClose.OrTimeout(10000);

                    Assert.Equal(ServiceConnectionStatus.Disconnected, proxy.Status);

                    // cleaned up clearly
                    Assert.Empty(ccm.ClientConnections);
                }
            }
        }
        public async Task ServiceConnectionWithTransportLayerClosedShouldCleanupEndlessInvokeClientConnections()
        {
            using (StartVerifiableLog(out var loggerFactory, LogLevel.Debug, expectedErrors: c => true))
            {
                var hubConfig = Utility.GetActualHubConfig(loggerFactory);
                var appName   = "app1";
                var hub       = "EndlessInvoke";
                var scm       = new TestServiceConnectionHandler();
                hubConfig.Resolver.Register(typeof(IServiceConnectionManager), () => scm);
                var ccm = new ClientConnectionManager(hubConfig, loggerFactory);
                hubConfig.Resolver.Register(typeof(IClientConnectionManager), () => ccm);
                DispatcherHelper.PrepareAndGetDispatcher(new TestAppBuilder(), hubConfig,
                                                         new ServiceOptions {
                    ConnectionString = ConnectionString
                }, appName, loggerFactory);
                using (var proxy = new TestServiceConnectionProxy(ccm, loggerFactory))
                {
                    // start the server connection
                    var connectionTask = proxy.StartAsync();
                    await proxy.ConnectionInitializedTask.OrTimeout();

                    var clientConnection = Guid.NewGuid().ToString("N");

                    var connectTask = scm.WaitForTransportOutputMessageAsync(typeof(GroupBroadcastDataMessage))
                                      .OrTimeout();
                    // Application layer sends OpenConnectionMessage
                    var openConnectionMessage = new OpenConnectionMessage(clientConnection, new Claim[0], null,
                                                                          $"?transport=webSockets&connectionToken=conn1&connectionData=%5B%7B%22name%22%3A%22{hub}%22%7D%5D");
                    await proxy.WriteMessageAsync(openConnectionMessage);

                    var connectMessage = (await connectTask)as GroupBroadcastDataMessage;
                    Assert.NotNull(connectMessage);
                    Assert.Equal($"hg-{hub}.note", connectMessage.GroupName);

                    var message = connectMessage.Payloads["json"]
                                  .GetJsonMessageFromSingleFramePayload <HubResponseItem>();

                    Assert.Equal("Connected", message.A[0]);

                    // group message goes into the manager
                    // make sure the tcs is called before writing message
                    var gbTask = scm.WaitForTransportOutputMessageAsync(typeof(GroupBroadcastDataMessage)).OrTimeout();

                    await proxy.WriteMessageAsync(new ConnectionDataMessage(clientConnection, Encoding.UTF8.GetBytes($"{{\"H\":\"{hub}\",\"M\":\"JoinGroup\",\"A\":[\"user1\",\"group1\"],\"I\":1}}")));

                    var broadcastMessage = (await gbTask)as GroupBroadcastDataMessage;
                    Assert.NotNull(broadcastMessage);
                    Assert.Equal($"hg-{hub}.group1", broadcastMessage.GroupName);

                    // close transport layer
                    proxy.TestConnectionContext.Application.Output.Complete();

                    await connectionTask.OrTimeout();

                    await proxy.WaitForConnectionClose.OrTimeout();

                    Assert.Equal(ServiceConnectionStatus.Disconnected, proxy.Status);

                    // cleaned up clearly
                    Assert.Empty(ccm.ClientConnections);
                }
            }
        }