public async Task NegotiateReturnedConnectionIdIsSetOnConnection()
            {
                string connectionId = null;

                var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false);

                testHttpHandler.OnNegotiate((request, cancellationToken) => ResponseUtils.CreateResponse(HttpStatusCode.OK,
                                                                                                         JsonConvert.SerializeObject(new
                {
                    connectionId        = "0rge0d00-0040-0030-0r00-000q00r00e00",
                    availableTransports = new object[]
                    {
                        new
                        {
                            transport       = "LongPolling",
                            transferFormats = new[] { "Text" }
                        },
                    }
                })));
                testHttpHandler.OnLongPoll(cancellationToken => ResponseUtils.CreateResponse(HttpStatusCode.NoContent));
                testHttpHandler.OnLongPollDelete((token) => ResponseUtils.CreateResponse(HttpStatusCode.Accepted));

                using (var noErrorScope = new VerifyNoErrorsScope())
                {
                    await WithConnectionAsync(
                        CreateConnection(testHttpHandler, loggerFactory : noErrorScope.LoggerFactory),
                        async (connection) =>
                    {
                        await connection.StartAsync().DefaultTimeout();
                        connectionId = connection.ConnectionId;
                    });
                }

                Assert.Equal("0rge0d00-0040-0030-0r00-000q00r00e00", connectionId);
            }
            public async Task CorrectlyHandlesQueryStringWhenAppendingNegotiateToUrl(string requestedUrl, string expectedNegotiate)
            {
                var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false);

                var negotiateUrlTcs = new TaskCompletionSource <string>();

                testHttpHandler.OnLongPoll(cancellationToken => ResponseUtils.CreateResponse(HttpStatusCode.NoContent));
                testHttpHandler.OnLongPollDelete(cancellationToken => ResponseUtils.CreateResponse(HttpStatusCode.NoContent));
                testHttpHandler.OnNegotiate((request, cancellationToken) =>
                {
                    negotiateUrlTcs.TrySetResult(request.RequestUri.ToString());
                    return(ResponseUtils.CreateResponse(HttpStatusCode.OK,
                                                        ResponseUtils.CreateNegotiationContent()));
                });

                using (var noErrorScope = new VerifyNoErrorsScope())
                {
                    await WithConnectionAsync(
                        CreateConnection(testHttpHandler, url : requestedUrl, loggerFactory : noErrorScope.LoggerFactory),
                        async (connection) =>
                    {
                        await connection.StartAsync().DefaultTimeout();
                    });
                }

                Assert.Equal(expectedNegotiate, await negotiateUrlTcs.Task.DefaultTimeout());
            }
            public async Task NegotiateThatReturnsUrlGetFollowed()
            {
                var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false);
                var firstNegotiate  = true;

                testHttpHandler.OnNegotiate((request, cancellationToken) =>
                {
                    if (firstNegotiate)
                    {
                        firstNegotiate = false;
                        return(ResponseUtils.CreateResponse(HttpStatusCode.OK,
                                                            JsonConvert.SerializeObject(new
                        {
                            url = "https://another.domain.url/chat"
                        })));
                    }

                    return(ResponseUtils.CreateResponse(HttpStatusCode.OK,
                                                        JsonConvert.SerializeObject(new
                    {
                        connectionId = "0rge0d00-0040-0030-0r00-000q00r00e00",
                        availableTransports = new object[]
                        {
                            new
                            {
                                transport = "LongPolling",
                                transferFormats = new[] { "Text" }
                            },
                        }
                    })));
                });

                testHttpHandler.OnLongPoll((token) =>
                {
                    var tcs = new TaskCompletionSource <HttpResponseMessage>(TaskCreationOptions.RunContinuationsAsynchronously);

                    token.Register(() => tcs.TrySetResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)));

                    return(tcs.Task);
                });

                testHttpHandler.OnLongPollDelete((token) => ResponseUtils.CreateResponse(HttpStatusCode.Accepted));

                using (var noErrorScope = new VerifyNoErrorsScope())
                {
                    await WithConnectionAsync(
                        CreateConnection(testHttpHandler, loggerFactory : noErrorScope.LoggerFactory),
                        async (connection) =>
                    {
                        await connection.StartAsync().DefaultTimeout();
                    });
                }

                Assert.Equal("http://fakeuri.org/negotiate?negotiateVersion=1", testHttpHandler.ReceivedRequests[0].RequestUri.ToString());
                Assert.Equal("https://another.domain.url/chat/negotiate?negotiateVersion=1", testHttpHandler.ReceivedRequests[1].RequestUri.ToString());
                Assert.Equal("https://another.domain.url/chat?id=0rge0d00-0040-0030-0r00-000q00r00e00", testHttpHandler.ReceivedRequests[2].RequestUri.ToString());
                Assert.Equal("https://another.domain.url/chat?id=0rge0d00-0040-0030-0r00-000q00r00e00", testHttpHandler.ReceivedRequests[3].RequestUri.ToString());
                Assert.Equal(5, testHttpHandler.ReceivedRequests.Count);
            }
            public async Task TransportPipeIsCompletedWhenErrorOccursInTransport()
            {
                bool ExpectedErrors(WriteContext writeContext)
                {
                    return(writeContext.LoggerName == typeof(LongPollingTransport).FullName &&
                           writeContext.EventId.Name == "ErrorSending");
                }

                using (StartVerifiableLog(expectedErrorsFilter: ExpectedErrors))
                {
                    var httpHandler = new TestHttpMessageHandler();

                    var longPollResult = new TaskCompletionSource <HttpResponseMessage>();
                    httpHandler.OnLongPoll(cancellationToken =>
                    {
                        cancellationToken.Register(() =>
                        {
                            longPollResult.TrySetResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent));
                        });
                        return(longPollResult.Task);
                    });
                    httpHandler.OnLongPollDelete(cancellationToken => ResponseUtils.CreateResponse(HttpStatusCode.NoContent));

                    httpHandler.OnSocketSend((data, _) =>
                    {
                        Assert.Collection(data, i => Assert.Equal(0x42, i));
                        return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.InternalServerError)));
                    });

                    await WithConnectionAsync(
                        CreateConnection(httpHandler, LoggerFactory),
                        async (connection) =>
                    {
                        await connection.StartAsync(TransferFormat.Text).OrTimeout();
                        await connection.Transport.Output.WriteAsync(new byte[] { 0x42 }).OrTimeout();

                        // We should get the exception in the transport input completion.
                        await Assert.ThrowsAsync <HttpRequestException>(() => connection.Transport.Input.WaitForWriterToComplete());
                    });
                }
            }
            public async Task ConnectionIdGetsSetWithNegotiateProtocolGreaterThanZero()
            {
                string connectionId = null;

                var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false);

                testHttpHandler.OnNegotiate((request, cancellationToken) => ResponseUtils.CreateResponse(HttpStatusCode.OK,
                                                                                                         JsonConvert.SerializeObject(new
                {
                    connectionId        = "0rge0d00-0040-0030-0r00-000q00r00e00",
                    negotiateVersion    = 1,
                    connectionToken     = "different-id",
                    availableTransports = new object[]
                    {
                        new
                        {
                            transport       = "LongPolling",
                            transferFormats = new[] { "Text" }
                        },
                    },
                    newField = "ignore this",
                })));
                testHttpHandler.OnLongPoll(cancellationToken => ResponseUtils.CreateResponse(HttpStatusCode.NoContent));
                testHttpHandler.OnLongPollDelete((token) => ResponseUtils.CreateResponse(HttpStatusCode.Accepted));

                using (var noErrorScope = new VerifyNoErrorsScope())
                {
                    await WithConnectionAsync(
                        CreateConnection(testHttpHandler, loggerFactory : noErrorScope.LoggerFactory),
                        async (connection) =>
                    {
                        await connection.StartAsync().DefaultTimeout();
                        connectionId = connection.ConnectionId;
                    });
                }

                Assert.Equal("0rge0d00-0040-0030-0r00-000q00r00e00", connectionId);
                Assert.Equal("http://fakeuri.org/negotiate?negotiateVersion=1", testHttpHandler.ReceivedRequests[0].RequestUri.ToString());
                Assert.Equal("http://fakeuri.org/?id=different-id", testHttpHandler.ReceivedRequests[1].RequestUri.ToString());
            }
            public async Task NegotiateThatReturnsUrlGetFollowedWithAccessToken()
            {
                var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false);
                var firstNegotiate  = true;

                testHttpHandler.OnNegotiate((request, cancellationToken) =>
                {
                    if (firstNegotiate)
                    {
                        firstNegotiate = false;

                        // The first negotiate requires an access token
                        if (request.Headers.Authorization?.Parameter != "firstSecret")
                        {
                            return(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized));
                        }

                        return(ResponseUtils.CreateResponse(HttpStatusCode.OK,
                                                            JsonConvert.SerializeObject(new
                        {
                            url = "https://another.domain.url/chat",
                            accessToken = "secondSecret"
                        })));
                    }

                    // All other requests require an access token
                    if (request.Headers.Authorization?.Parameter != "secondSecret")
                    {
                        return(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized));
                    }

                    return(ResponseUtils.CreateResponse(HttpStatusCode.OK,
                                                        JsonConvert.SerializeObject(new
                    {
                        connectionId = "0rge0d00-0040-0030-0r00-000q00r00e00",
                        availableTransports = new object[]
                        {
                            new
                            {
                                transport = "LongPolling",
                                transferFormats = new[] { "Text" }
                            },
                        }
                    })));
                });

                testHttpHandler.OnLongPoll((request, token) =>
                {
                    // All other requests require an access token
                    if (request.Headers.Authorization?.Parameter != "secondSecret")
                    {
                        return(Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.Unauthorized)));
                    }
                    var tcs = new TaskCompletionSource <HttpResponseMessage>(TaskCreationOptions.RunContinuationsAsynchronously);

                    token.Register(() => tcs.TrySetResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent)));

                    return(tcs.Task);
                });

                testHttpHandler.OnLongPollDelete((token) => ResponseUtils.CreateResponse(HttpStatusCode.Accepted));

                Task <string> AccessTokenProvider() => Task.FromResult <string>("firstSecret");

                using (var noErrorScope = new VerifyNoErrorsScope())
                {
                    await WithConnectionAsync(
                        CreateConnection(testHttpHandler, loggerFactory : noErrorScope.LoggerFactory, accessTokenProvider : AccessTokenProvider),
                        async (connection) =>
                    {
                        await connection.StartAsync(TransferFormat.Text).OrTimeout();
                    });
                }

                Assert.Equal("http://fakeuri.org/negotiate", testHttpHandler.ReceivedRequests[0].RequestUri.ToString());
                Assert.Equal("https://another.domain.url/chat/negotiate", testHttpHandler.ReceivedRequests[1].RequestUri.ToString());
                Assert.Equal("https://another.domain.url/chat?id=0rge0d00-0040-0030-0r00-000q00r00e00", testHttpHandler.ReceivedRequests[2].RequestUri.ToString());
                Assert.Equal("https://another.domain.url/chat?id=0rge0d00-0040-0030-0r00-000q00r00e00", testHttpHandler.ReceivedRequests[3].RequestUri.ToString());
                // Delete request
                Assert.Equal(5, testHttpHandler.ReceivedRequests.Count);
            }