Esempio n. 1
0
        public void NamedPipeActivityTest()
        {
            const string pipeName = "test.pipe";
            var          logger   = XUnitLogger.CreateLogger(_testOutput);

            // Arrange
            var activity = new Activity
            {
                Id   = Guid.NewGuid().ToString("N"),
                Type = ActivityTypes.Message,
                From = new ChannelAccount {
                    Id = "testUser"
                },
                Conversation = new ConversationAccount {
                    Id = Guid.NewGuid().ToString("N")
                },
                Recipient = new ChannelAccount {
                    Id = "testBot"
                },
                ServiceUrl = "unknown",
                ChannelId  = "test",
                Text       = "hi"
            };

            var bot = new StreamingTestBot((turnContext, cancellationToken) =>
            {
                var activityClone  = JsonConvert.DeserializeObject <Activity>(JsonConvert.SerializeObject(turnContext.Activity));
                activityClone.Text = $"Echo: {turnContext.Activity.Text}";

                return(turnContext.SendActivityAsync(activityClone, cancellationToken));
            });

            var verifiedResponse     = false;
            var clientRequestHandler = new Mock <RequestHandler>();

            clientRequestHandler
            .Setup(h => h.ProcessRequestAsync(It.IsAny <ReceiveRequest>(), It.IsAny <ILogger <RequestHandler> >(), It.IsAny <object>(), It.IsAny <CancellationToken>()))
            .Returns <ReceiveRequest, ILogger <RequestHandler>, object, CancellationToken>((request, anonLogger, context, cancellationToken) =>
            {
                var body     = request.ReadBodyAsString();
                var response = JsonConvert.DeserializeObject <Activity>(body, SerializationSettings.DefaultDeserializationSettings);

                Assert.NotNull(response);
                Assert.Equal("Echo: hi", response.Text);
                verifiedResponse = true;

                return(Task.FromResult(StreamingResponse.OK()));
            });

            // Act
            var server        = new CloudAdapter(new StreamingTestBotFrameworkAuthentication(), logger);
            var serverRunning = server.ConnectNamedPipeAsync(pipeName, bot, "testAppId", "testAudience", "testCallerId");
            var client        = new NamedPipeClient(pipeName, ".", clientRequestHandler.Object, logger: logger);
            var clientRunning = client.ConnectAsync();

            SimulateMultiTurnConversation(1, new[] { activity }, client, logger);

            // Assert
            Assert.True(verifiedResponse);
        }
        public void ServerTransportCanSendMessages()
        {
            var logger = XUnitLogger.CreateLogger(_testOutput);

            using (var connection = new TestWebSocketConnectionFeature())
            {
                var server          = connection.AcceptAsync().GetAwaiter().GetResult();
                var client          = connection.Client;
                var receiverRunning = ReceiveAsync(client);

                var fromTransport = new Pipe(PipeOptions.Default);
                var toTransport   = new Pipe(PipeOptions.Default);

                var webSocketManager = new Mock <WebSocketManager>();
                webSocketManager.Setup(m => m.AcceptWebSocketAsync()).Returns(Task.FromResult(server));
                var httpContext = new Mock <HttpContext>();
                httpContext.Setup(c => c.WebSockets).Returns(webSocketManager.Object);

                var sut = new WebSocketTransport(httpContext.Object.WebSockets.AcceptWebSocketAsync().GetAwaiter().GetResult(), new DuplexPipe(toTransport.Reader, fromTransport.Writer), logger);
                var serverTransportRunning = sut.ConnectAsync(CancellationToken.None);

                var messages = new List <byte[]> {
                    Encoding.UTF8.GetBytes("foo")
                };
                WriteAsync(toTransport.Writer, messages).Wait();
                toTransport.Writer.CompleteAsync().GetAwaiter().GetResult();

                serverTransportRunning.Wait();

                var output = receiverRunning.GetAwaiter().GetResult();

                Assert.Equal("foo", Encoding.UTF8.GetString(output[0]));
            }
        }
        public void ClientTransportCanSendMessages()
        {
            var logger = XUnitLogger.CreateLogger(_testOutput);

            using (var connection = new TestWebSocketConnectionFeature())
            {
                var server          = connection.AcceptAsync().GetAwaiter().GetResult();
                var client          = connection.Client;
                var receiverRunning = ReceiveAsync(server);

                var fromTransport = new Pipe(PipeOptions.Default);
                var toTransport   = new Pipe(PipeOptions.Default);

                var sut = new WebSocketTransport(client, new DuplexPipe(toTransport.Reader, fromTransport.Writer), logger);
                var clientTransportRunning = sut.ConnectAsync(CancellationToken.None);

                var messages = new List <byte[]> {
                    Encoding.UTF8.GetBytes("foo")
                };
                WriteAsync(toTransport.Writer, messages).Wait();
                toTransport.Writer.CompleteAsync().GetAwaiter().GetResult();

                clientTransportRunning.Wait();

                var output = receiverRunning.GetAwaiter().GetResult();

                Assert.Equal("foo", Encoding.UTF8.GetString(output[0]));
            }
        }
        public async Task ServerTransportCanReceiveMessages()
        {
            var logger = XUnitLogger.CreateLogger(_testOutput);

            using (var connection = new TestWebSocketConnectionFeature())
            {
                var server = connection.AcceptAsync();
                var client = connection.Client;

                var fromTransport   = new Pipe(PipeOptions.Default);
                var toTransport     = new Pipe(PipeOptions.Default);
                var listenerRunning = ListenAsync(fromTransport.Reader);

                var webSocketManager = new Mock <WebSocketManager>();
                webSocketManager.Setup(m => m.AcceptWebSocketAsync()).Returns(server);
                var httpContext = new Mock <HttpContext>();
                httpContext.Setup(c => c.WebSockets).Returns(webSocketManager.Object);

                var sut = new WebSocketTransport(httpContext.Object.WebSockets.AcceptWebSocketAsync().GetAwaiter().GetResult(), new DuplexPipe(toTransport.Reader, fromTransport.Writer), logger);
                var serverTransportRunning = sut.ConnectAsync(CancellationToken.None);

                var messages = new List <byte[]> {
                    Encoding.UTF8.GetBytes("foo"), Encoding.UTF8.GetBytes("bar")
                };
                SendBinaryAsync(client, messages).Wait();
                client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Done sending.", CancellationToken.None).Wait();

                serverTransportRunning.Wait();

                var output = await listenerRunning;

                Assert.Equal("foo", Encoding.UTF8.GetString(output[0]));
                Assert.Equal("bar", Encoding.UTF8.GetString(output[1]));
            }
        }
Esempio n. 5
0
        public void ClientTransportCanReceiveMessages()
        {
            var logger = XUnitLogger.CreateLogger(_testOutput);

            using (var connection = new TestWebSocketConnectionFeature())
            {
                var server = connection.AcceptAsync().GetAwaiter().GetResult();
                var client = connection.Client;

                var fromTransport   = new Pipe(PipeOptions.Default);
                var toTransport     = new Pipe(PipeOptions.Default);
                var listenerRunning = ListenAsync(fromTransport.Reader);

                var sut = new WebSocketTransport(new DuplexPipe(toTransport.Reader, fromTransport.Writer), logger);
                var clientTransportRunning = sut.ProcessSocketAsync(client, CancellationToken.None);

                var messages = new List <byte[]> {
                    Encoding.UTF8.GetBytes("foo")
                };
                SendBinaryAsync(server, messages).Wait();
                server.CloseAsync(WebSocketCloseStatus.NormalClosure, "Done sending.", CancellationToken.None).Wait();

                clientTransportRunning.Wait();

                var output = listenerRunning.GetAwaiter().GetResult();

                Assert.Equal("foo", Encoding.UTF8.GetString(output[0]));
            }
        }
Esempio n. 6
0
        public async Task Integration_KeepAlive()
        {
            // TODO: Transform this test into a theory and do multi-message, multi-thread, multi-client, etc.
            var logger = XUnitLogger.CreateLogger(_outputHelper);
            var cts    = new CancellationTokenSource();

            using (var webSocketFeature = new TestWebSocketConnectionFeature())
            {
                // Bot / server setup
                var botRequestHandler = new Mock <RequestHandler>();

                botRequestHandler
                .Setup(r => r.ProcessRequestAsync(It.IsAny <ReceiveRequest>(), null, null, CancellationToken.None))
                .ReturnsAsync(() => new StreamingResponse()
                {
                    StatusCode = 200
                });

                var socket = await webSocketFeature.AcceptAsync().ConfigureAwait(false);

                var connection = new WebSocketStreamingConnection(socket, logger);
                var serverTask = connection.ListenAsync(botRequestHandler.Object, cts.Token);

                // Client / channel setup
                var clientRequestHandler = new Mock <RequestHandler>();

                clientRequestHandler
                .Setup(r => r.ProcessRequestAsync(It.IsAny <ReceiveRequest>(), null, null, CancellationToken.None))
                .ReturnsAsync(() => new StreamingResponse()
                {
                    StatusCode = 200
                });

                var client = new WebSocketClient(webSocketFeature.Client, "wss://test", clientRequestHandler.Object, logger: logger, closeTimeOut: TimeSpan.FromSeconds(10), keepAlive: TimeSpan.FromMilliseconds(200));

                var clientTask = client.ConnectInternalAsync(CancellationToken.None);

                // Send request bot (server) -> channel (client)
                const string path = "api/version";
                const string botToClientPayload = "Hello human, I'm Bender!";
                var          request            = StreamingRequest.CreatePost(path, new StringContent(botToClientPayload));

                var responseFromClient = await connection.SendStreamingRequestAsync(request).ConfigureAwait(false);

                Assert.Equal(200, responseFromClient.StatusCode);

                const string clientToBotPayload = "Hello bot, I'm Calculon!";
                var          clientRequest      = StreamingRequest.CreatePost(path, new StringContent(clientToBotPayload));

                // Send request bot channel (client) -> (server)
                var clientToBotResult = await client.SendAsync(clientRequest).ConfigureAwait(false);

                Assert.Equal(200, clientToBotResult.StatusCode);

                await Task.Delay(TimeSpan.FromSeconds(3)).ConfigureAwait(false);

                Assert.True(client.IsConnected);
            }
        }
Esempio n. 7
0
        public async Task Integration_Interop_LegacyClient()
        {
            // TODO: Transform this test into a theory and do multi-message, multi-thread, multi-client, etc.
            var logger = XUnitLogger.CreateLogger(_outputHelper);

            using (var webSocketFeature = new TestWebSocketConnectionFeature())
            {
                // Bot / server setup
                var botRequestHandler = new Mock <RequestHandler>();

                botRequestHandler
                .Setup(r => r.ProcessRequestAsync(It.IsAny <ReceiveRequest>(), null, null, CancellationToken.None))
                .ReturnsAsync(() => new StreamingResponse()
                {
                    StatusCode = 200
                });

                var socket = await webSocketFeature.AcceptAsync().ConfigureAwait(false);

                var connection = new WebSocketStreamingConnection(socket, logger);
                var serverTask = Task.Run(() => connection.ListenAsync(botRequestHandler.Object));

                // Client / channel setup
                var clientRequestHandler = new Mock <RequestHandler>();

                clientRequestHandler
                .Setup(r => r.ProcessRequestAsync(It.IsAny <ReceiveRequest>(), null, null, CancellationToken.None))
                .ReturnsAsync(() => new StreamingResponse()
                {
                    StatusCode = 200
                });

                using (var client = new Microsoft.Bot.Streaming.Transport.WebSockets.WebSocketClient("wss://test", clientRequestHandler.Object))
                {
                    await client.ConnectInternalAsync(webSocketFeature.Client).ConfigureAwait(false);

                    // Send request bot (server) -> channel (client)
                    const string path = "api/version";
                    const string botToClientPayload = "Hello human, I'm Bender!";
                    var          request            = StreamingRequest.CreatePost(path, new StringContent(botToClientPayload));

                    var responseFromClient = await connection.SendStreamingRequestAsync(request).ConfigureAwait(false);

                    Assert.Equal(200, responseFromClient.StatusCode);

                    const string clientToBotPayload = "Hello bot, I'm Calculon!";
                    var          clientRequest      = StreamingRequest.CreatePost(path, new StringContent(clientToBotPayload));

                    // Send request bot channel (client) -> (server)
                    var clientToBotResult = await client.SendAsync(clientRequest).ConfigureAwait(false);

                    Assert.Equal(200, clientToBotResult.StatusCode);
                    client.Disconnect();
                }

                await serverTask.ConfigureAwait(false);
            }
        }
        private void RunStreamingCrashTest(Action <WebSocket, TestWebSocketConnectionFeature.WebSocketChannel, WebSocketClient, CancellationTokenSource, CancellationTokenSource> induceCrash)
        {
            var logger = XUnitLogger.CreateLogger(_testOutput);

            var serverCts = new CancellationTokenSource();
            var clientCts = new CancellationTokenSource();

            using (var connection = new TestWebSocketConnectionFeature())
            {
                var webSocket       = connection.AcceptAsync().Result;
                var clientWebSocket = connection.Client;

                var bot = new StreamingTestBot((turnContext, cancellationToken) => Task.CompletedTask);

                var server        = new CloudAdapter(new StreamingTestBotFrameworkAuthentication(), logger);
                var serverRunning = server.ProcessAsync(CreateWebSocketUpgradeRequest(webSocket), new Mock <HttpResponse>().Object, bot, serverCts.Token);

                var clientRequestHandler = new Mock <RequestHandler>();
                clientRequestHandler
                .Setup(h => h.ProcessRequestAsync(It.IsAny <ReceiveRequest>(), It.IsAny <ILogger <RequestHandler> >(), It.IsAny <object>(), It.IsAny <CancellationToken>()))
                .Returns(Task.FromResult(StreamingResponse.OK()));
                using (var client = new WebSocketClient("wss://test", clientRequestHandler.Object, logger: logger))
                {
                    var clientRunning = client.ConnectInternalAsync(clientWebSocket, clientCts.Token);

                    var activity = new Activity
                    {
                        Id   = Guid.NewGuid().ToString("N"),
                        Type = ActivityTypes.Message,
                        From = new ChannelAccount {
                            Id = "testUser"
                        },
                        Conversation = new ConversationAccount {
                            Id = Guid.NewGuid().ToString("N")
                        },
                        Recipient = new ChannelAccount {
                            Id = "testBot"
                        },
                        ServiceUrl = "wss://InvalidServiceUrl/api/messages",
                        ChannelId  = "test",
                        Text       = "hi"
                    };

                    var content  = new StringContent(JsonConvert.SerializeObject(activity), Encoding.UTF8, "application/json");
                    var response = client.SendAsync(StreamingRequest.CreatePost("/api/messages", content)).Result;
                    Assert.Equal(200, response.StatusCode);

                    induceCrash(webSocket, clientWebSocket, client, serverCts, clientCts);

                    clientRunning.Wait();
                    Assert.True(clientRunning.IsCompletedSuccessfully);
                }

                serverRunning.Wait();
                Assert.True(serverRunning.IsCompletedSuccessfully);
            }
        }
        [InlineData(false, true)]  // new client, legacy server
        public void SimpleActivityTest(bool useLegacyClient, bool useLegacyServer)
        {
            var logger = XUnitLogger.CreateLogger(_testOutput);

            // Arrange
            var activities = new[]
            {
                new Activity
                {
                    Id   = Guid.NewGuid().ToString("N"),
                    Type = ActivityTypes.Message,
                    From = new ChannelAccount {
                        Id = "testUser"
                    },
                    Conversation = new ConversationAccount {
                        Id = Guid.NewGuid().ToString("N")
                    },
                    Recipient = new ChannelAccount {
                        Id = "testBot"
                    },
                    ServiceUrl = "wss://InvalidServiceUrl/api/messages",
                    ChannelId  = "test",
                    Text       = "hi"
                }
            };

            var verifiedResponses = activities.ToDictionary(a => a.Id, a => false);

            var bot = new StreamingTestBot((turnContext, cancellationToken) =>
            {
                var activityClone  = JsonConvert.DeserializeObject <Activity>(JsonConvert.SerializeObject(turnContext.Activity));
                activityClone.Text = $"Echo: {turnContext.Activity.Text}";

                return(turnContext.SendActivityAsync(activityClone, cancellationToken));
            });

            var server = CreateTestStreamingTransportServer(useLegacyServer, logger);

            var clientRequestHandler = new Mock <RequestHandler>();

            clientRequestHandler
            .Setup(h => h.ProcessRequestAsync(It.IsAny <ReceiveRequest>(), It.IsAny <ILogger <RequestHandler> >(), It.IsAny <object>(), It.IsAny <CancellationToken>()))
            .Returns <ReceiveRequest, ILogger <RequestHandler>, object, CancellationToken>((request, anonLogger, context, cancellationToken) =>
            {
                var body     = request.ReadBodyAsString();
                var response = JsonConvert.DeserializeObject <Activity>(body, SerializationSettings.DefaultDeserializationSettings);

                Assert.NotNull(response);
                Assert.Equal("Echo: hi", response.Text);

                verifiedResponses[response.ReplyToId] = true;

                return(Task.FromResult(StreamingResponse.OK()));
            });

            // Act
            RunActivityStreamingTest(activities, bot, server, clientRequestHandler.Object, logger, useLegacyClient);

            // Assert
            Assert.True(verifiedResponses.Values.All(verifiedResponse => verifiedResponse));
        }
        [InlineData(3, 100, 32, false, false)] // new client, new server
        public void ConcurrencyTest(int connectionCount, int messageCount, int threadCount, bool useLegacyClient, bool useLegacyServer)
        {
            var logger = XUnitLogger.CreateLogger(_testOutput);

            var activities = new[]
            {
                new Activity
                {
                    Id   = Guid.NewGuid().ToString("N"),
                    Type = ActivityTypes.Message,
                    From = new ChannelAccount {
                        Id = "testUser"
                    },
                    Conversation = new ConversationAccount {
                        Id = Guid.NewGuid().ToString("N")
                    },
                    Recipient = new ChannelAccount {
                        Id = "testBot"
                    },
                    ServiceUrl  = "wss://InvalidServiceUrl/api/messages",
                    ChannelId   = "test",
                    Text        = "hi",
                    Attachments = new List <Attachment>
                    {
                        new Attachment
                        {
                            Name        = @"Resources\architecture-resize.png",
                            ContentType = "image/png",
                            ContentUrl  = $"data:image/png;base64,{Convert.ToBase64String(File.ReadAllBytes(Path.Combine(Environment.CurrentDirectory, @"Resources", "architecture-resize.png")))}",
                        }
                    }
                }
            };

            var bot = new StreamingTestBot((turnContext, cancellationToken) =>
            {
                var response         = MessageFactory.Text("Echo: hi");
                response.Attachments = new List <Attachment>
                {
                    new Attachment
                    {
                        Name        = @"Resources\architecture-resize.png",
                        ContentType = "image/png",
                        ContentUrl  = $"data:image/png;base64,{Convert.ToBase64String(File.ReadAllBytes(Path.Combine(Environment.CurrentDirectory, @"Resources", "architecture-resize.png")))}",
                    }
                };
                return(turnContext.SendActivityAsync(response, cancellationToken));
            });

            var server = CreateTestStreamingTransportServer(useLegacyServer, logger);

            var clientRequestHandler = new Mock <RequestHandler>();

            clientRequestHandler
            .Setup(h => h.ProcessRequestAsync(It.IsAny <ReceiveRequest>(), It.IsAny <ILogger <RequestHandler> >(), It.IsAny <object>(), It.IsAny <CancellationToken>()))
            .Returns <ReceiveRequest, ILogger <RequestHandler>, object, CancellationToken>((request, anonLogger, context, cancellationToken) =>
            {
                try
                {
                    var body     = request.ReadBodyAsString();
                    var response = JsonConvert.DeserializeObject <Activity>(body, SerializationSettings.DefaultDeserializationSettings);
                    Assert.NotNull(response);

                    Assert.Equal($"Echo: {activities.FirstOrDefault(a => a.Id == response.ReplyToId)?.Text}", response.Text);
                    Assert.Equal(1, response.Attachments.Count);

                    return(Task.FromResult(StreamingResponse.OK()));
                }
                catch (Exception e)
                {
                    return(Task.FromResult(StreamingResponse.InternalServerError(new StringContent(e.ToString()))));
                }
            });

            var connections = new Task[connectionCount];

            for (var i = 0; i < connectionCount; i++)
            {
                connections[i] = Task.Factory.StartNew(() =>
                                                       RunActivityStreamingTest(activities, bot, server, clientRequestHandler.Object, logger, useLegacyClient, messageCount, threadCount));
            }

            Task.WhenAll(connections).Wait();
        }
        [InlineData(false, true)]  // new client, legacy server
        public void ActivityWithAttachmentsTest(bool useLegacyClient, bool useLegacyServer)
        {
            var logger = XUnitLogger.CreateLogger(_testOutput);

            // Arrange
            var activities = new[]
            {
                new Activity
                {
                    Id   = Guid.NewGuid().ToString("N"),
                    Type = ActivityTypes.Message,
                    From = new ChannelAccount {
                        Id = "testUser"
                    },
                    Conversation = new ConversationAccount {
                        Id = Guid.NewGuid().ToString("N")
                    },
                    Recipient = new ChannelAccount {
                        Id = "testBot"
                    },
                    ServiceUrl = "wss://InvalidServiceUrl/api/messages",
                    ChannelId  = "test",
                    Text       = "1"
                },
                new Activity
                {
                    Id   = Guid.NewGuid().ToString("N"),
                    Type = ActivityTypes.Message,
                    From = new ChannelAccount {
                        Id = "testUser"
                    },
                    Conversation = new ConversationAccount {
                        Id = Guid.NewGuid().ToString("N")
                    },
                    Recipient = new ChannelAccount {
                        Id = "testBot"
                    },
                    ServiceUrl  = "wss://InvalidServiceUrl/api/messages",
                    ChannelId   = "test",
                    Text        = "2",
                    Attachments = new List <Attachment>
                    {
                        new Attachment
                        {
                            Name        = @"Resources\architecture-resize.png",
                            ContentType = "image/png",
                            ContentUrl  = $"data:image/png;base64,{Convert.ToBase64String(File.ReadAllBytes(Path.Combine(Environment.CurrentDirectory, @"Resources", "architecture-resize.png")))}",
                        }
                    }
                }
            };

            var verifiedResponses = activities.ToDictionary(a => a.Id, a => false);

            var bot = new StreamingTestBot((turnContext, cancellationToken) =>
            {
                switch (turnContext.Activity.Text)
                {
                case "1":
                    var response1         = MessageFactory.Text("Echo: 1");
                    response1.Attachments = new List <Attachment>
                    {
                        new Attachment
                        {
                            Name        = @"Resources\architecture-resize.png",
                            ContentType = "image/png",
                            ContentUrl  = $"data:image/png;base64,{Convert.ToBase64String(File.ReadAllBytes(Path.Combine(Environment.CurrentDirectory, @"Resources", "architecture-resize.png")))}",
                        }
                    };
                    return(turnContext.SendActivityAsync(response1, cancellationToken));

                case "2":
                    var response2 = MessageFactory.Text("Echo: 2");
                    return(turnContext.SendActivityAsync(response2, cancellationToken));

                default:
                    throw new ApplicationException("Unknown Activity!");
                }
            });

            var server = CreateTestStreamingTransportServer(useLegacyServer, logger);

            var clientRequestHandler = new Mock <RequestHandler>();

            clientRequestHandler
            .Setup(h => h.ProcessRequestAsync(It.IsAny <ReceiveRequest>(), It.IsAny <ILogger <RequestHandler> >(), It.IsAny <object>(), It.IsAny <CancellationToken>()))
            .Returns <ReceiveRequest, ILogger <RequestHandler>, object, CancellationToken>((request, anonLogger, context, cancellationToken) =>
            {
                try
                {
                    var body     = request.ReadBodyAsString();
                    var response = JsonConvert.DeserializeObject <Activity>(body, SerializationSettings.DefaultDeserializationSettings);

                    Assert.NotNull(response);
                    Assert.Equal($"Echo: {activities.FirstOrDefault(a => a.Id == response.ReplyToId)?.Text}", response.Text);

                    verifiedResponses[response.ReplyToId] = true;

                    return(Task.FromResult(StreamingResponse.OK()));
                }
                catch (Exception e)
                {
                    return(Task.FromResult(StreamingResponse.InternalServerError(new StringContent(e.ToString()))));
                }
            });

            // Act
            RunActivityStreamingTest(activities, bot, server, clientRequestHandler.Object, logger, useLegacyClient);

            // Assert
            Assert.True(verifiedResponses.Values.All(verifiedResponse => verifiedResponse));
        }
Esempio n. 12
0
        public async Task Integration_Interop_LegacyClient_MiniLoad(int threadCount, int messageCount)
        {
            var logger = XUnitLogger.CreateLogger(_outputHelper);

            using (var webSocketFeature = new TestWebSocketConnectionFeature())
            {
                var botRequestHandler = new Mock <RequestHandler>();

                botRequestHandler
                .Setup(r => r.ProcessRequestAsync(It.IsAny <ReceiveRequest>(), null, null, CancellationToken.None))
                .ReturnsAsync(() => new StreamingResponse()
                {
                    StatusCode = 200
                });

                var socket = await webSocketFeature.AcceptAsync().ConfigureAwait(false);

                var connection = new WebSocketStreamingConnection(socket, logger);
                var serverTask = Task.Run(() => connection.ListenAsync(botRequestHandler.Object));
                await Task.Delay(TimeSpan.FromSeconds(1));

                var clients = new List <Microsoft.Bot.Streaming.Transport.WebSockets.WebSocketClient>();

                var clientRequestHandler = new Mock <RequestHandler>();

                clientRequestHandler
                .Setup(r => r.ProcessRequestAsync(It.IsAny <ReceiveRequest>(), null, null, CancellationToken.None))
                .ReturnsAsync(() => new StreamingResponse()
                {
                    StatusCode = 200
                });

                using (var client = new Microsoft.Bot.Streaming.Transport.WebSockets.WebSocketClient(
                           "wss://test",
                           clientRequestHandler.Object))
                {
                    await client.ConnectInternalAsync(webSocketFeature.Client).ConfigureAwait(false);

                    clients.Add(client);

                    // Send request bot (server) -> channel (client)
                    const string path = "api/version";
                    const string botToClientPayload = "Hello human, I'm Bender!";

                    Func <int, Task> testFlow = async(i) =>
                    {
                        var request = StreamingRequest.CreatePost(path, new StringContent(botToClientPayload));

                        var stopwatch          = Stopwatch.StartNew();
                        var responseFromClient =
                            await connection.SendStreamingRequestAsync(request).ConfigureAwait(false);

                        stopwatch.Stop();

                        Assert.Equal(200, responseFromClient.StatusCode);
                        logger.LogInformation(
                            $"Server->Client {i} latency: {stopwatch.ElapsedMilliseconds}. Status code: {responseFromClient.StatusCode}");

                        const string clientToBotPayload = "Hello bot, I'm Calculon!";
                        var          clientRequest      = StreamingRequest.CreatePost(path, new StringContent(clientToBotPayload));

                        stopwatch = Stopwatch.StartNew();

                        // Send request bot channel (client) -> (server)
                        var clientToBotResult = await client.SendAsync(clientRequest).ConfigureAwait(false);

                        stopwatch.Stop();

                        Assert.Equal(200, clientToBotResult.StatusCode);

                        logger.LogInformation(
                            $"Client->Server {i} latency: {stopwatch.ElapsedMilliseconds}. Status code: {responseFromClient.StatusCode}");
                    };

                    await testFlow(-1).ConfigureAwait(false);

                    var tasks = new List <Task>();

                    using (var throttler = new SemaphoreSlim(threadCount))
                    {
                        for (int j = 0; j < messageCount; j++)
                        {
                            await throttler.WaitAsync().ConfigureAwait(false);

                            // using Task.Run(...) to run the lambda in its own parallel
                            // flow on the threadpool
                            tasks.Add(
                                Task.Run(async() =>
                            {
                                try
                                {
                                    await testFlow(j).ConfigureAwait(false);
                                }
                                finally
                                {
                                    throttler.Release();
                                }
                            }));
                        }

                        await Task.WhenAll(tasks).ConfigureAwait(false);
                    }

                    client.Disconnect();
                }

                await serverTask.ConfigureAwait(false);
            }
        }