示例#1
0
        async Task ListenerShutdownWithPendingAcceptsTest(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener = null;

            try
            {
                listener = GetHybridConnectionListener(endpointTestType);
                var client = GetHybridConnectionClient(endpointTestType);

                TestUtility.Log($"Opening {listener}");
                await listener.OpenAsync(TimeSpan.FromSeconds(20));

                var acceptTasks = new List <Task <HybridConnectionStream> >(600);
                TestUtility.Log($"Calling listener.AcceptConnectionAsync() {acceptTasks.Capacity} times");
                for (int i = 0; i < acceptTasks.Capacity; i++)
                {
                    acceptTasks.Add(listener.AcceptConnectionAsync());
                    Assert.False(acceptTasks[i].IsCompleted);
                }

                TestUtility.Log($"Closing {listener}");
                await listener.CloseAsync(TimeSpan.FromSeconds(10));

                listener = null;
                for (int i = 0; i < acceptTasks.Count; i++)
                {
                    Assert.True(acceptTasks[i].Wait(TimeSpan.FromSeconds(5)));
                    Assert.Null(acceptTasks[i].Result);
                }
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
示例#2
0
        async Task RawWebSocketSenderTest(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener = null;

            try
            {
                listener = GetHybridConnectionListener(endpointTestType);

                var clientWebSocket = new ClientWebSocket();
                var wssUri          = await GetWebSocketConnectionUri(endpointTestType);

                using (var cancelSource = new CancellationTokenSource(TimeSpan.FromMinutes(1)))
                {
                    TestUtility.Log($"Opening {listener}");
                    await listener.OpenAsync(cancelSource.Token);

                    await clientWebSocket.ConnectAsync(wssUri, cancelSource.Token);

                    var listenerStream = await listener.AcceptConnectionAsync();

                    TestUtility.Log("Client and Listener are connected!");
                    Assert.Null(clientWebSocket.SubProtocol);

                    byte[] sendBuffer = this.CreateBuffer(1024, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
                    await clientWebSocket.SendAsync(new ArraySegment <byte>(sendBuffer), WebSocketMessageType.Binary, true, cancelSource.Token);

                    TestUtility.Log($"clientWebSocket wrote {sendBuffer.Length} bytes");

                    byte[] readBuffer = new byte[sendBuffer.Length];
                    await this.ReadCountBytesAsync(listenerStream, readBuffer, 0, readBuffer.Length, TimeSpan.FromSeconds(30));

                    Assert.Equal(sendBuffer, readBuffer);

                    TestUtility.Log("Calling clientStream.CloseAsync");
                    var clientStreamCloseTask = clientWebSocket.CloseAsync(WebSocketCloseStatus.EndpointUnavailable, "From Test Code", cancelSource.Token);
                    TestUtility.Log("Reading from listenerStream");
                    int bytesRead = await this.SafeReadAsync(listenerStream, readBuffer, 0, readBuffer.Length);

                    TestUtility.Log($"listenerStream.Read returned {bytesRead} bytes");
                    Assert.Equal(0, bytesRead);

                    TestUtility.Log("Calling listenerStream.CloseAsync");
                    var   listenerStreamCloseTask = listenerStream.CloseAsync(cancelSource.Token);
                    await listenerStreamCloseTask;
                    TestUtility.Log("Calling listenerStream.CloseAsync completed");
                    await clientStreamCloseTask;
                    TestUtility.Log("Calling clientStream.CloseAsync completed");

                    TestUtility.Log($"Closing {listener}");
                    await listener.CloseAsync(TimeSpan.FromSeconds(10));

                    listener = null;
                }
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
        async Task WriteLargeDataSetTest(EndpointTestType endpointTestType, int kilobytesToSend = 1024)
        {
            HybridConnectionListener listener = null;

            try
            {
                listener = GetHybridConnectionListener(endpointTestType);
                var client = GetHybridConnectionClient(endpointTestType);

                TestUtility.Log($"Opening {listener}");
                await listener.OpenAsync(TimeSpan.FromSeconds(30));

                var clientStream = await client.CreateConnectionAsync();

                var listenerStream = await listener.AcceptConnectionAsync();

                TestUtility.Log($"clientStream and listenerStream connected! {listenerStream}");

                byte[] sendBuffer = this.CreateBuffer(kilobytesToSend * 1024, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
                byte[] readBuffer = new byte[sendBuffer.Length];

                TestUtility.Log($"Sending {sendBuffer.Length} bytes from client->listener");
                var sendTask = clientStream.WriteAsync(sendBuffer, 0, sendBuffer.Length);
                var readTask = this.ReadCountBytesAsync(listenerStream, readBuffer, 0, readBuffer.Length, TimeSpan.FromSeconds(30));

                await Task.WhenAll(sendTask, readTask);

                TestUtility.Log($"Sending and Reading complete");
                Assert.Equal(sendBuffer, readBuffer);

                TestUtility.Log($"Sending {sendBuffer.Length} bytes from listener->client");
                sendTask = listenerStream.WriteAsync(sendBuffer, 0, sendBuffer.Length);
                readTask = this.ReadCountBytesAsync(clientStream, readBuffer, 0, readBuffer.Length, TimeSpan.FromSeconds(30));

                await Task.WhenAll(sendTask, readTask);

                TestUtility.Log($"Sending and Reading complete");
                Assert.Equal(sendBuffer, readBuffer);

                TestUtility.Log("Calling clientStream.Shutdown");
                clientStream.Shutdown();
                int bytesRead = await this.SafeReadAsync(listenerStream, readBuffer, 0, readBuffer.Length);

                TestUtility.Log($"listenerStream.Read returned {bytesRead} bytes");
                Assert.Equal(0, bytesRead);

                TestUtility.Log("Calling listenerStream.Dispose");
                listenerStream.Dispose();

                TestUtility.Log("Calling clientStream.Dispose");
                clientStream.Dispose();
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
        async Task EmptyRequestEmptyResponse(EndpointTestType endpointTestType)
        {
            var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
            HybridConnectionListener listener = this.GetHybridConnectionListener(endpointTestType);

            try
            {
                await listener.OpenAsync(cts.Token);

                listener.RequestHandler = async(context) =>
                {
                    TestUtility.Log($"RequestHandler: {context.Request.HttpMethod} {context.Request.Url}");
                    await context.Response.CloseAsync();
                };

                RelayConnectionStringBuilder connectionString = GetConnectionStringBuilder(endpointTestType);
                Uri endpointUri   = connectionString.Endpoint;
                Uri hybridHttpUri = new UriBuilder("https://", endpointUri.Host, endpointUri.Port, connectionString.EntityPath).Uri;

                using (var client = new HttpClient {
                    BaseAddress = hybridHttpUri
                })
                {
                    client.DefaultRequestHeaders.ExpectContinue = false;

                    var getRequest = new HttpRequestMessage();
                    getRequest.Method = HttpMethod.Get;
                    await AddAuthorizationHeader(connectionString, getRequest, hybridHttpUri);

                    LogRequest(getRequest, client);
                    using (HttpResponseMessage response = await client.SendAsync(getRequest))
                    {
                        LogResponse(response);
                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                        Assert.Equal(0, response.Content.ReadAsStreamAsync().Result.Length);
                    }

                    var postRequest = new HttpRequestMessage();
                    postRequest.Method = HttpMethod.Post;
                    await AddAuthorizationHeader(connectionString, postRequest, hybridHttpUri);

                    LogRequest(postRequest, client);
                    using (HttpResponseMessage response = await client.SendAsync(postRequest))
                    {
                        LogResponse(response);
                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                        Assert.Equal(0, response.Content.ReadAsStreamAsync().Result.Length);
                    }
                }

                await listener.CloseAsync(cts.Token);
            }
            finally
            {
                await SafeCloseAsync(listener);
            }
        }
示例#5
0
        async Task ClientShutdownTest(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener = null;

            try
            {
                listener = GetHybridConnectionListener(endpointTestType);
                var client = GetHybridConnectionClient(endpointTestType);

                TestUtility.Log($"Opening {listener}");
                await listener.OpenAsync(TimeSpan.FromSeconds(30));

                var clientStream = await client.CreateConnectionAsync();

                var listenerStream = await listener.AcceptConnectionAsync();

                TestUtility.Log("Client and Listener HybridStreams are connected!");

                byte[] sendBuffer = this.CreateBuffer(1024, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
                await clientStream.WriteAsync(sendBuffer, 0, sendBuffer.Length);

                TestUtility.Log($"clientStream wrote {sendBuffer.Length} bytes");

                byte[] readBuffer = new byte[sendBuffer.Length];
                await this.ReadCountBytesAsync(listenerStream, readBuffer, 0, readBuffer.Length, TimeSpan.FromSeconds(30));

                Assert.Equal(sendBuffer, readBuffer);

                TestUtility.Log("Calling clientStream.Shutdown");
                clientStream.Shutdown();
                int bytesRead = await this.SafeReadAsync(listenerStream, readBuffer, 0, readBuffer.Length);

                TestUtility.Log($"listenerStream.Read returned {bytesRead} bytes");
                Assert.Equal(0, bytesRead);

                TestUtility.Log("Calling listenerStream.Shutdown and Dispose");
                listenerStream.Shutdown();
                listenerStream.Dispose();
                bytesRead = await this.SafeReadAsync(clientStream, readBuffer, 0, readBuffer.Length);

                TestUtility.Log($"clientStream.Read returned {bytesRead} bytes");
                Assert.Equal(0, bytesRead);

                TestUtility.Log("Calling clientStream.Dispose");
                clientStream.Dispose();

                TestUtility.Log($"Closing {listener}");
                await listener.CloseAsync(TimeSpan.FromSeconds(10));

                listener = null;
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
        async Task HybridConnectionTest(EndpointTestType endpointTestType, bool useBuiltInClientWebSocket)
        {
            HybridConnectionListener listener = null;

            try
            {
                listener = this.GetHybridConnectionListener(endpointTestType);
                listener.UseBuiltInClientWebSocket = useBuiltInClientWebSocket;
                var client = GetHybridConnectionClient(endpointTestType);
                client.UseBuiltInClientWebSocket = useBuiltInClientWebSocket;

                TestUtility.Log($"Opening {listener}");
                await listener.OpenAsync(TimeSpan.FromSeconds(30));

                var clientStream = await client.CreateConnectionAsync();

                var listenerStream = await listener.AcceptConnectionAsync();

                TestUtility.Log("Client and Listener HybridStreams are connected!");

                byte[] sendBuffer = this.CreateBuffer(1024, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
                await clientStream.WriteAsync(sendBuffer, 0, sendBuffer.Length);

                TestUtility.Log($"clientStream wrote {sendBuffer.Length} bytes");

                byte[] readBuffer = new byte[sendBuffer.Length];
                await this.ReadCountBytesAsync(listenerStream, readBuffer, 0, readBuffer.Length, TimeSpan.FromSeconds(30));

                Assert.Equal(sendBuffer, readBuffer);

                TestUtility.Log("Calling clientStream.CloseAsync");
                var clientStreamCloseTask = clientStream.CloseAsync(new CancellationTokenSource(TimeSpan.FromSeconds(10)).Token);
                TestUtility.Log("Reading from listenerStream");
                int bytesRead = await this.SafeReadAsync(listenerStream, readBuffer, 0, readBuffer.Length);

                TestUtility.Log($"listenerStream.Read returned {bytesRead} bytes");
                Assert.Equal(0, bytesRead);

                TestUtility.Log("Calling listenerStream.CloseAsync");
                var   listenerStreamCloseTask = listenerStream.CloseAsync(new CancellationTokenSource(TimeSpan.FromSeconds(10)).Token);
                await listenerStreamCloseTask;
                TestUtility.Log("Calling listenerStream.CloseAsync completed");
                await clientStreamCloseTask;
                TestUtility.Log("Calling clientStream.CloseAsync completed");

                TestUtility.Log($"Closing {listener}");
                await listener.CloseAsync(TimeSpan.FromSeconds(10));

                listener = null;
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
        async Task LargeRequestEmptyResponse(EndpointTestType endpointTestType)
        {
            var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
            HybridConnectionListener listener = this.GetHybridConnectionListener(endpointTestType);

            try
            {
                await listener.OpenAsync(cts.Token);

                string requestBody = null;
                listener.RequestHandler = async(context) =>
                {
                    TestUtility.Log("HybridConnectionListener.RequestHandler invoked with Request:");
                    TestUtility.Log($"{context.Request.HttpMethod} {context.Request.Url}");
                    context.Request.Headers.AllKeys.ToList().ForEach((k) => TestUtility.Log($"{k}: {context.Request.Headers[k]}"));
                    requestBody = StreamToString(context.Request.InputStream);
                    TestUtility.Log($"Body Length: {requestBody.Length}");
                    await context.Response.CloseAsync();
                };

                RelayConnectionStringBuilder connectionString = GetConnectionStringBuilder(endpointTestType);
                Uri endpointUri   = connectionString.Endpoint;
                Uri hybridHttpUri = new UriBuilder("https://", endpointUri.Host, endpointUri.Port, connectionString.EntityPath).Uri;

                using (var client = new HttpClient {
                    BaseAddress = hybridHttpUri
                })
                {
                    client.DefaultRequestHeaders.ExpectContinue = false;
                    var postRequest = new HttpRequestMessage();
                    await AddAuthorizationHeader(connectionString, postRequest, hybridHttpUri);

                    postRequest.Method = HttpMethod.Post;
                    var body = new string('y', 65 * 1024);
                    postRequest.Content = new StringContent(body);
                    LogRequest(postRequest, client, showBody: false);
                    using (HttpResponseMessage response = await client.SendAsync(postRequest, cts.Token))
                    {
                        LogResponse(response);
                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                        Assert.Equal(0, response.Content.ReadAsStreamAsync().Result.Length);
                        Assert.Equal(body.Length, requestBody.Length);
                    }
                }

                await listener.CloseAsync(cts.Token);
            }
            finally
            {
                await SafeCloseAsync(listener);
            }
        }
示例#8
0
        async Task RawWebSocketSenderTest(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener = null;

            try
            {
                listener = GetHybridConnectionListener(endpointTestType);
                await TestRawWebSocket(listener, endpointTestType);
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
        /// <summary>
        /// Returns a HybridConnectionListener based on the EndpointTestType (authenticated/unauthenticated).
        /// </summary>
        protected HybridConnectionListener GetHybridConnectionListener(EndpointTestType endpointTestType)
        {
            // Even if the endpoint is unauthenticated, the *listener* still needs to be authenticated
            if (endpointTestType == EndpointTestType.Unauthenticated)
            {
                var connectionStringBuilder = new RelayConnectionStringBuilder(this.ConnectionString)
                {
                    EntityPath = Constants.UnauthenticatedEntityPath
                };
                return(new HybridConnectionListener(connectionStringBuilder.ToString()));
            }

            return(new HybridConnectionListener(GetConnectionString(endpointTestType)));
        }
示例#10
0
        async Task NonExistantNamespaceTest(EndpointTestType endpointTestType)
        {
            string badAddress = $"sb://fakeendpoint.{Guid.NewGuid()}.com";
            HybridConnectionListener listener = null;

            try
            {
                TestUtility.Log($"Setting ConnectionStringBuilder.Endpoint to '{badAddress}'");

                var fakeEndpointConnectionStringBuilder = new RelayConnectionStringBuilder(this.ConnectionString)
                {
                    Endpoint = new Uri(badAddress)
                };

                if (endpointTestType == EndpointTestType.Authenticated)
                {
                    fakeEndpointConnectionStringBuilder.EntityPath = Constants.AuthenticatedEntityPath;
                }
                else
                {
                    fakeEndpointConnectionStringBuilder.EntityPath = Constants.UnauthenticatedEntityPath;
                }

                var fakeEndpointConnectionString = fakeEndpointConnectionStringBuilder.ToString();

                listener = new HybridConnectionListener(fakeEndpointConnectionString);
                var client = new HybridConnectionClient(fakeEndpointConnectionString);

                TestUtility.Log($"Opening Listener");
                var relayException = await Assert.ThrowsAsync <RelayException>(() => listener.OpenAsync());

                TestUtility.Log($"Received Exception {relayException.ToStringWithoutCallstack()}");
                Assert.True(relayException.IsTransient, "Listener.Open() should return a transient Exception");

                TestUtility.Log($"Opening Client");
                relayException = await Assert.ThrowsAsync <RelayException>(() => client.CreateConnectionAsync());

                TestUtility.Log($"Received Exception {relayException.ToStringWithoutCallstack()}");
                Assert.True(relayException.IsTransient, "Client.Open() should return a transient Exception");
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
        /// <summary>
        /// Since these tests all share a common connection string, this method will modify the
        /// endpoint / shared access keys as needed based on the EndpointTestType.
        /// </summary>
        protected RelayConnectionStringBuilder GetConnectionStringBuilder(EndpointTestType endpointTestType)
        {
            var connectionStringBuilder = new RelayConnectionStringBuilder(this.ConnectionString);

            if (endpointTestType == EndpointTestType.Unauthenticated)
            {
                connectionStringBuilder.EntityPath            = Constants.UnauthenticatedEntityPath;
                connectionStringBuilder.SharedAccessKey       = string.Empty;
                connectionStringBuilder.SharedAccessKeyName   = string.Empty;
                connectionStringBuilder.SharedAccessSignature = string.Empty;
            }
            else
            {
                connectionStringBuilder.EntityPath = Constants.AuthenticatedEntityPath;
            }

            return(connectionStringBuilder);
        }
示例#12
0
        async Task NonExistantNamespaceTest(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener = null;

            try
            {
                TestUtility.Log("Setting ConnectionStringBuilder.Endpoint to 'sb://fakeendpoint.com'");

                var fakeEndpointConnectionStringBuilder = new RelayConnectionStringBuilder(this.ConnectionString)
                {
                    Endpoint = new Uri("sb://fakeendpoint.com")
                };

                if (endpointTestType == EndpointTestType.Authenticated)
                {
                    fakeEndpointConnectionStringBuilder.EntityPath = Constants.AuthenticatedEntityPath;
                }
                else
                {
                    fakeEndpointConnectionStringBuilder.EntityPath = Constants.UnauthenticatedEntityPath;
                }

                var fakeEndpointConnectionString = fakeEndpointConnectionStringBuilder.ToString();

                listener = new HybridConnectionListener(fakeEndpointConnectionString);
                var client = new HybridConnectionClient(fakeEndpointConnectionString);

// TODO: Remove this once .NET Core supports inspecting the StatusCode/Description. https://github.com/dotnet/corefx/issues/13773
#if NET451
                await Assert.ThrowsAsync <EndpointNotFoundException>(() => listener.OpenAsync());

                await Assert.ThrowsAsync <EndpointNotFoundException>(() => client.CreateConnectionAsync());
#else
                await Assert.ThrowsAsync <RelayException>(() => listener.OpenAsync());

                await Assert.ThrowsAsync <RelayException>(() => client.CreateConnectionAsync());
#endif
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
示例#13
0
        /// <summary>
        /// Since these tests all share a common connection string, this method will modify the
        /// endpoint / shared access keys as needed based on the EndpointTestType, and return a WebSocket URI.
        /// </summary>
        async Task <Uri> GetWebSocketConnectionUri(EndpointTestType endpointTestType)
        {
            var clientConnectionString  = GetConnectionString(endpointTestType);
            var connectionStringBuilder = new RelayConnectionStringBuilder(clientConnectionString);
            var connectionUriString     = $"wss://{connectionStringBuilder.Endpoint.Host}/$hc/{connectionStringBuilder.EntityPath}";

            if (endpointTestType == EndpointTestType.Authenticated)
            {
                var tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(
                    connectionStringBuilder.SharedAccessKeyName,
                    connectionStringBuilder.SharedAccessKey);

                var token = await tokenProvider.GetTokenAsync(connectionStringBuilder.Endpoint.ToString(), TimeSpan.FromMinutes(10));

                connectionUriString += $"?sb-hc-token={WebUtility.UrlEncode(token.TokenString)}";
            }

            return(new Uri(connectionUriString));
        }
示例#14
0
        async Task CustomWebSocketTest()
        {
            HybridConnectionListener listener = null;

            try
            {
                EndpointTestType endpointTestType = EndpointTestType.Authenticated;
                listener = GetHybridConnectionListener(endpointTestType);
                CustomClientWebSocketFactory factory = new CustomClientWebSocketFactory();
                listener.ClientWebSocketFactory = factory;
                await TestRawWebSocket(listener, endpointTestType);

                Assert.True(factory.WasCreateCalled);
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
示例#15
0
        async Task ConcurrentClientsTest(EndpointTestType endpointTestType)
        {
            const int ClientCount             = 100;
            HybridConnectionListener listener = null;

            try
            {
                listener = GetHybridConnectionListener(endpointTestType);
                var client = GetHybridConnectionClient(endpointTestType);

                TestUtility.Log($"Opening {listener}");
                await listener.OpenAsync(TimeSpan.FromSeconds(10));

                TestUtility.Log($"Opening {ClientCount} connections quickly");

                var createConnectionTasks = new List <Task <HybridConnectionStream> >();
                for (var i = 0; i < ClientCount; i++)
                {
                    createConnectionTasks.Add(client.CreateConnectionAsync());
                }

                var senderTasks = new List <Task>();
                for (var i = 0; i < ClientCount; i++)
                {
                    this.AcceptEchoListener(listener);
                    senderTasks.Add(this.RunEchoClientAsync(await createConnectionTasks[i], i + 1));
                }

                await Task.WhenAll(senderTasks);

                TestUtility.Log($"Closing {listener}");
                await listener.CloseAsync(TimeSpan.FromSeconds(10));

                listener = null;
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
        async Task NonExistantNamespaceTest(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener = null;

            try
            {
                TestUtility.Log("Setting ConnectionStringBuilder.Endpoint to 'sb://fakeendpoint.com'");

                var fakeEndpointConnectionStringBuilder = new RelayConnectionStringBuilder(this.ConnectionString)
                {
                    Endpoint = new Uri("sb://fakeendpoint.com")
                };

                if (endpointTestType == EndpointTestType.Authenticated)
                {
                    fakeEndpointConnectionStringBuilder.EntityPath = Constants.AuthenticatedEntityPath;
                }
                else
                {
                    fakeEndpointConnectionStringBuilder.EntityPath = Constants.UnauthenticatedEntityPath;
                }

                var fakeEndpointConnectionString = fakeEndpointConnectionStringBuilder.ToString();

                listener = new HybridConnectionListener(fakeEndpointConnectionString);
                var client = new HybridConnectionClient(fakeEndpointConnectionString);

                await Assert.ThrowsAsync <EndpointNotFoundException>(() => listener.OpenAsync());

                await Assert.ThrowsAsync <EndpointNotFoundException>(() => client.CreateConnectionAsync());
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
示例#17
0
        async Task ListenerAbortWhileClientReadingTest(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener = null;

            try
            {
                listener = GetHybridConnectionListener(endpointTestType);
                var client = GetHybridConnectionClient(endpointTestType);

                TestUtility.Log($"Opening {listener}");
                await listener.OpenAsync(TimeSpan.FromSeconds(30));

                var clientStream = await client.CreateConnectionAsync();

                var listenerStream = await listener.AcceptConnectionAsync();

                TestUtility.Log("Client and Listener HybridStreams are connected!");

                using (var cancelSource = new CancellationTokenSource())
                {
                    TestUtility.Log("Aborting listener WebSocket");
                    cancelSource.Cancel();
                    await listenerStream.CloseAsync(cancelSource.Token);
                }

                byte[] readBuffer = new byte[1024];
                await Assert.ThrowsAsync <RelayException>(() => clientStream.ReadAsync(readBuffer, 0, readBuffer.Length));

                TestUtility.Log("Calling clientStream.Close");
                var clientCloseTask = clientStream.CloseAsync(CancellationToken.None);
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
示例#18
0
        async Task SmallRequestSmallResponse(EndpointTestType endpointTestType)
        {
            var cts = new CancellationTokenSource(TimeSpan.FromSeconds(60));
            HybridConnectionListener listener = null;

            try
            {
                listener = this.GetHybridConnectionListener(endpointTestType);
                RelayConnectionStringBuilder connectionString = GetConnectionStringBuilder(endpointTestType);
                Uri endpointUri = connectionString.Endpoint;

                string         expectedResponse   = "{ \"a\" : true }";
                HttpStatusCode expectedStatusCode = HttpStatusCode.OK;
                listener.RequestHandler = (context) =>
                {
                    TestUtility.Log("HybridConnectionListener.RequestHandler invoked with Request:");
                    TestUtility.Log($"{context.Request.HttpMethod} {context.Request.Url}");
                    context.Request.Headers.AllKeys.ToList().ForEach((k) => TestUtility.Log($"{k}: {context.Request.Headers[k]}"));
                    TestUtility.Log(StreamToString(context.Request.InputStream));

                    context.Response.StatusCode = expectedStatusCode;
                    byte[] responseBytes = Encoding.UTF8.GetBytes(expectedResponse);
                    context.Response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
                    context.Response.Close();
                };

                TestUtility.Log($"Opening {listener}");
                await listener.OpenAsync(cts.Token);

                Uri hybridHttpUri = new UriBuilder("https://", endpointUri.Host, endpointUri.Port, connectionString.EntityPath).Uri;
                using (var client = new HttpClient {
                    BaseAddress = hybridHttpUri
                })
                {
                    client.DefaultRequestHeaders.ExpectContinue = false;

                    var getRequest = new HttpRequestMessage();
                    await AddAuthorizationHeader(connectionString, getRequest, hybridHttpUri);

                    getRequest.Method = HttpMethod.Get;
                    LogHttpRequest(getRequest, client);
                    using (HttpResponseMessage response = await client.SendAsync(getRequest, cts.Token))
                    {
                        LogHttpResponse(response);
                        Assert.Equal(expectedStatusCode, response.StatusCode);
                        Assert.Equal("OK", response.ReasonPhrase);
                        Assert.Equal(expectedResponse, await response.Content.ReadAsStringAsync());
                    }

                    var postRequest = new HttpRequestMessage();
                    await AddAuthorizationHeader(connectionString, postRequest, hybridHttpUri);

                    postRequest.Method = HttpMethod.Post;
                    string body = "{  \"a\": 11,   \"b\" :22, \"c\":\"test\",    \"d\":true}";
                    postRequest.Content = new StringContent(body);
                    postRequest.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                    LogHttpRequest(postRequest, client);
                    using (HttpResponseMessage response = await client.SendAsync(postRequest, cts.Token))
                    {
                        LogHttpResponse(response);
                        Assert.Equal(expectedStatusCode, response.StatusCode);
                        Assert.Equal("OK", response.ReasonPhrase);
                        Assert.Equal(expectedResponse, await response.Content.ReadAsStringAsync());
                    }
                }

                TestUtility.Log($"Closing {listener}");
                await listener.CloseAsync(cts.Token);

                listener = null;
            }
            finally
            {
                cts.Dispose();
                await this.SafeCloseAsync(listener);
            }
        }
示例#19
0
        async Task RequestHeadersTest(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener = null;

            try
            {
                listener = this.GetHybridConnectionListener(endpointTestType);
                var client = GetHybridConnectionClient(endpointTestType);

                var listenerRequestTcs = new TaskCompletionSource <IDictionary <string, string> >();
                listener.AcceptHandler = (context) =>
                {
                    try
                    {
                        var headers = new Dictionary <string, string>();
                        foreach (string headerName in context.Request.Headers.AllKeys)
                        {
                            headers[headerName] = context.Request.Headers[headerName];
                        }

                        listenerRequestTcs.SetResult(headers);
                        return(Task.FromResult(true));
                    }
                    catch (Exception e)
                    {
                        listenerRequestTcs.TrySetException(e);
                        throw;
                    }
                };

                TestUtility.Log($"Opening {listener}");
                await listener.OpenAsync(TimeSpan.FromSeconds(30));

                const string ExpectedRequestHeaderName  = "CustomHeader1";
                const string ExpectedRequestHeaderValue = "Some value here; other-value/here.";

                var clientRequestHeaders = new Dictionary <string, string>();
                clientRequestHeaders[ExpectedRequestHeaderName] = ExpectedRequestHeaderValue;
                var clientStream = await client.CreateConnectionAsync(clientRequestHeaders);

                var listenerStream = await listener.AcceptConnectionAsync();

                TestUtility.Log("Client and Listener HybridStreams are connected!");

                Assert.True(listenerRequestTcs.Task.Wait(TimeSpan.FromSeconds(5)), "AcceptHandler should have been invoked by now.");
                IDictionary <string, string> listenerRequestHeaders = await listenerRequestTcs.Task;
                Assert.True(listenerRequestHeaders.ContainsKey(ExpectedRequestHeaderName), "Expected header name should be present.");
                Assert.Equal(ExpectedRequestHeaderValue, listenerRequestHeaders[ExpectedRequestHeaderName]);

                byte[] sendBuffer = this.CreateBuffer(1025, new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 });
                await clientStream.WriteAsync(sendBuffer, 0, sendBuffer.Length);

                TestUtility.Log($"clientStream wrote {sendBuffer.Length} bytes");

                byte[] readBuffer = new byte[sendBuffer.Length];
                await this.ReadCountBytesAsync(listenerStream, readBuffer, 0, sendBuffer.Length, TimeSpan.FromSeconds(30));

                Assert.Equal(sendBuffer, readBuffer);

                var clientStreamCloseTask = clientStream.CloseAsync(new CancellationTokenSource(TimeSpan.FromSeconds(10)).Token);
                await listenerStream.CloseAsync(new CancellationTokenSource(TimeSpan.FromSeconds(10)).Token);

                await clientStreamCloseTask;

                TestUtility.Log($"Closing {listener}");
                await listener.CloseAsync(TimeSpan.FromSeconds(10));

                listener = null;
            }
            finally
            {
                await this.SafeCloseAsync(listener);
            }
        }
        /// <summary>
        /// Returns a HybridConnectionClient based on the EndpointTestType (authenticated/unauthenticated).
        /// </summary>
        protected HybridConnectionClient GetHybridConnectionClient(EndpointTestType endpointTestType)
        {
            var connectionString = GetConnectionString(endpointTestType);

            return(new HybridConnectionClient(connectionString));
        }
        async Task LoadBalancedListeners(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener1 = null;
            HybridConnectionListener listener2 = null;
            var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));

            try
            {
                listener1 = this.GetHybridConnectionListener(endpointTestType);
                listener2 = this.GetHybridConnectionListener(endpointTestType);
                RelayConnectionStringBuilder connectionString = GetConnectionStringBuilder(endpointTestType);
                Uri endpointUri = connectionString.Endpoint;

                TestUtility.Log("Opening HybridConnectionListeners");
                await Task.WhenAll(
                    listener1.OpenAsync(cts.Token),
                    listener2.OpenAsync(cts.Token));

                const int TotalExpectedRequestCount = 50;
                long      listenerRequestCount1     = 0;
                long      listenerRequestCount2     = 0;

                listener1.RequestHandler = async(context) =>
                {
                    Interlocked.Increment(ref listenerRequestCount1);
                    context.Response.OutputStream.WriteByte(1);
                    await context.Response.CloseAsync();
                };

                listener2.RequestHandler = async(context) =>
                {
                    Interlocked.Increment(ref listenerRequestCount2);
                    context.Response.OutputStream.WriteByte(2);
                    await context.Response.CloseAsync();
                };

                Uri hybridHttpUri = new UriBuilder("https://", endpointUri.Host, endpointUri.Port, connectionString.EntityPath).Uri;
                await Enumerable.Range(0, TotalExpectedRequestCount).ParallelBatchAsync(
                    batchSize: 10,
                    parallelTasksCount: 10,
                    asyncTask: async(indexes) =>
                {
                    string messageIndexes = string.Join(",", indexes);
                    TestUtility.Log($"Messages {messageIndexes} starting");
                    try
                    {
                        foreach (var index in indexes)
                        {
                            var httpRequest = (HttpWebRequest)WebRequest.Create(hybridHttpUri);
                            using (var abortRegistration = cts.Token.Register(() => httpRequest.Abort()))
                            {
                                httpRequest.Method = HttpMethod.Get.Method;
                                await AddAuthorizationHeader(connectionString, httpRequest.Headers, hybridHttpUri);

                                using (var httpResponse = (HttpWebResponse)(await httpRequest.GetResponseAsync()))
                                {
                                    Assert.Equal(HttpStatusCode.OK, httpResponse.StatusCode);
                                }
                            }
                        }
                    }
                    catch (WebException webException)
                    {
                        TestUtility.Log($"Messages {messageIndexes} Error: {webException}");
                        throw;
                    }

                    TestUtility.Log($"Messages {messageIndexes} complete");
                });

                TestUtility.Log($"Listener1 Request Count: {listenerRequestCount1}");
                TestUtility.Log($"Listener2 Request Count: {listenerRequestCount2}");

                Assert.Equal(TotalExpectedRequestCount, listenerRequestCount1 + listenerRequestCount2);
                Assert.True(listenerRequestCount1 > 0, "Listener 1 should have received some of the events.");
                Assert.True(listenerRequestCount2 > 0, "Listener 2 should have received some of the events.");

                await Task.WhenAll(
                    listener1.CloseAsync(cts.Token),
                    listener2.CloseAsync(cts.Token));
            }
            finally
            {
                TestUtility.Log("Shutting down");
                cts.Dispose();
                await Task.WhenAll(
                    SafeCloseAsync(listener1),
                    SafeCloseAsync(listener2));
            }
        }
        /// <summary>
        /// Since these tests all share a common connection string, this method will modify the
        /// endpoint / shared access keys as needed based on the EndpointTestType.
        /// </summary>
        protected string GetConnectionString(EndpointTestType endpointTestType)
        {
            var connectionStringBuilder = this.GetConnectionStringBuilder(endpointTestType);

            return(connectionStringBuilder.ToString());
        }
        async Task MultiValueHeader(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener = this.GetHybridConnectionListener(endpointTestType);

            try
            {
                RelayConnectionStringBuilder connectionString = GetConnectionStringBuilder(endpointTestType);
                Uri endpointUri = connectionString.Endpoint;

                TestUtility.Log("Calling HybridConnectionListener.Open");
                await listener.OpenAsync(TimeSpan.FromSeconds(30));

                const string CustomHeaderName   = "X-CustomHeader";
                string       requestHeaderValue = string.Empty;
                listener.RequestHandler = (context) =>
                {
                    TestUtility.Log("HybridConnectionListener.RequestHandler invoked with Request:");
                    TestUtility.Log($"{context.Request.HttpMethod} {context.Request.Url}");
                    context.Request.Headers.AllKeys.ToList().ForEach((k) => TestUtility.Log($"{k}: {context.Request.Headers[k]}"));
                    TestUtility.Log(StreamToString(context.Request.InputStream));
                    requestHeaderValue = context.Request.Headers[CustomHeaderName];

                    context.Response.Headers.Add(CustomHeaderName, "responseValue1");
                    context.Response.Headers.Add(CustomHeaderName, "responseValue2");
                    context.Response.OutputStream.Close();
                };

                Uri hybridHttpUri = new UriBuilder("https://", endpointUri.Host, endpointUri.Port, connectionString.EntityPath).Uri;
                using (var client = new HttpClient {
                    BaseAddress = hybridHttpUri
                })
                {
                    client.DefaultRequestHeaders.ExpectContinue = false;

                    var getRequest = new HttpRequestMessage();
                    getRequest.Method = HttpMethod.Get;
                    await AddAuthorizationHeader(connectionString, getRequest, hybridHttpUri);

                    getRequest.Headers.Add(CustomHeaderName, "requestValue1");
                    getRequest.Headers.Add(CustomHeaderName, "requestValue2");

                    LogRequest(getRequest, client);
                    using (HttpResponseMessage response = await client.SendAsync(getRequest))
                    {
                        LogResponse(response);
                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                        Assert.Equal("requestValue1, requestValue2", requestHeaderValue);
                        string[] responseHeaders = string.Join(",", response.Headers.GetValues(CustomHeaderName)).Split(new[] { ',' });
                        for (int i = 0; i < responseHeaders.Length; i++)
                        {
                            responseHeaders[i] = responseHeaders[i].Trim(' ', '\t');
                        }

                        Assert.Equal(new [] { "responseValue1", "responseValue2" }, responseHeaders);
                    }
                }

                await listener.CloseAsync(TimeSpan.FromSeconds(10));
            }
            finally
            {
                await SafeCloseAsync(listener);
            }
        }
        async Task QueryString(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener = this.GetHybridConnectionListener(endpointTestType);

            try
            {
                RelayConnectionStringBuilder connectionString = GetConnectionStringBuilder(endpointTestType);
                Uri endpointUri = connectionString.Endpoint;

                TestUtility.Log("Calling HybridConnectionListener.Open");
                await listener.OpenAsync(TimeSpan.FromSeconds(30));

                var queryStringTests = new[]
                {
                    new { Original = "?foo=bar", Output = "?foo=bar" },
                    new { Original = "?sb-hc-id=1", Output = "" },
                    new { Original = "?sb-hc-id=1&custom=value", Output = "?custom=value" },
                    new { Original = "?custom=value&sb-hc-id=1", Output = "?custom=value" },
                    new { Original = "?sb-hc-undefined=true", Output = "" },
                    new { Original = "? Key =  Value With Space ", Output = "?+Key+=++Value+With+Space" }, // HttpUtility.ParseQueryString.ToString() in the cloud service changes this
                    new { Original = "?key='value'", Output = "?key=%27value%27" },                        // HttpUtility.ParseQueryString.ToString() in the cloud service changes this
                    new { Original = "?key=\"value\"", Output = "?key=%22value%22" },                      // HttpUtility.ParseQueryString.ToString() in the cloud service changes this
                    new { Original = "?key=<value>", Output = "?key=%3cvalue%3e" },
#if PENDING_SERVICE_UPDATE
                    new { Original = "?foo=bar&", Output = "?foo=bar&" },
                    new { Original = "?&foo=bar", Output = "?foo=bar" }, // HttpUtility.ParseQueryString.ToString() in the cloud service changes this
                    new { Original = "?sb-hc-undefined", Output = "?sb-hc-undefined" },
                    new { Original = "?CustomValue", Output = "?CustomValue" },
                    new { Original = "?custom-Value", Output = "?custom-Value" },
                    new { Original = "?custom&value", Output = "?custom&value" },
                    new { Original = "?&custom&value&", Output = "?&custom&value&" },
                    new { Original = "?&&value&&", Output = "?&&value&&" },
                    new { Original = "?+", Output = "?+" },
                    new { Original = "?%20", Output = "?+" },                                        // HttpUtility.ParseQueryString.ToString() in the cloud service changes this
                    new { Original = "? Not a key value pair ", Output = "?+Not+a+key+value+pair" }, // HttpUtility.ParseQueryString.ToString() in the cloud service changes this
                    new { Original = "?&+&", Output = "?&+&" },
                    new { Original = "?%2f%3a%3d%26", Output = "?%2f%3a%3d%26" },
#endif
                };

                RelayedHttpListenerContext actualRequestContext = null;
                listener.RequestHandler = async(context) =>
                {
                    TestUtility.Log($"RequestHandler {context.Request.HttpMethod} {context.Request.Url}");
                    actualRequestContext = context;
                    await context.Response.CloseAsync();
                };

                foreach (var queryStringTest in queryStringTests)
                {
                    string originalQueryString = queryStringTest.Original;
                    string expectedQueryString = queryStringTest.Output;
                    actualRequestContext = null;

                    TestUtility.Log($"Testing Query String '{originalQueryString}'");
                    Uri hybridHttpUri = new UriBuilder("https://", endpointUri.Host, endpointUri.Port, connectionString.EntityPath, originalQueryString).Uri;
                    using (var client = new HttpClient {
                        BaseAddress = hybridHttpUri
                    })
                    {
                        client.DefaultRequestHeaders.ExpectContinue = false;

                        var getRequest = new HttpRequestMessage();
                        getRequest.Method = HttpMethod.Get;
                        await AddAuthorizationHeader(connectionString, getRequest, hybridHttpUri);

                        LogRequestLine(getRequest, client);
                        using (HttpResponseMessage response = await client.SendAsync(getRequest))
                        {
                            LogResponseLine(response);
                            Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                            Assert.Equal(expectedQueryString, actualRequestContext.Request.Url.Query);
                        }
                    }
                }

                await listener.CloseAsync(TimeSpan.FromSeconds(10));
            }
            finally
            {
                await SafeCloseAsync(listener);
            }
        }
        async Task RequestHandlerErrors(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener = this.GetHybridConnectionListener(endpointTestType);

            try
            {
                RelayConnectionStringBuilder connectionString = GetConnectionStringBuilder(endpointTestType);
                Uri endpointUri = connectionString.Endpoint;
                await listener.OpenAsync(TimeSpan.FromSeconds(30));

                Uri hybridHttpUri = new UriBuilder("https://", endpointUri.Host, endpointUri.Port, connectionString.EntityPath).Uri;
                using (var client = new HttpClient {
                    BaseAddress = hybridHttpUri
                })
                {
                    client.DefaultRequestHeaders.ExpectContinue = false;

                    var request = new HttpRequestMessage();
                    request.Method = HttpMethod.Get;
                    await AddAuthorizationHeader(connectionString, request, hybridHttpUri);

                    LogRequestLine(request, client);
                    using (HttpResponseMessage response = await client.SendAsync(request))
                    {
                        LogResponse(response);
                        Assert.Equal(HttpStatusCode.NotImplemented, response.StatusCode);
                        Assert.Contains("RequestHandler has not been configured", response.ReasonPhrase);
                        Assert.Contains("TrackingId", response.ReasonPhrase);
                        Assert.Contains(hybridHttpUri.Host, response.ReasonPhrase);
                        Assert.Contains(connectionString.EntityPath, response.ReasonPhrase);
                        string viaHeader = response.Headers.Via.ToString();
                        Assert.Contains(hybridHttpUri.Host, viaHeader);
                    }

                    string userExceptionMessage = "User Error";
                    listener.RequestHandler = (context) =>
                    {
                        throw new InvalidOperationException(userExceptionMessage);
                    };

                    request        = new HttpRequestMessage();
                    request.Method = HttpMethod.Get;
                    await AddAuthorizationHeader(connectionString, request, hybridHttpUri);

                    LogRequestLine(request, client);
                    using (HttpResponseMessage response = await client.SendAsync(request))
                    {
                        LogResponse(response);
                        Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);
                        Assert.Contains("RequestHandler", response.ReasonPhrase);
                        Assert.Contains("exception", response.ReasonPhrase, StringComparison.OrdinalIgnoreCase);
                        Assert.Contains("TrackingId", response.ReasonPhrase);
                        Assert.Contains(hybridHttpUri.Host, response.ReasonPhrase);
                        Assert.Contains(connectionString.EntityPath, response.ReasonPhrase);
                        string viaHeader = response.Headers.Via.ToString();
                        Assert.Contains(hybridHttpUri.Host, viaHeader);

                        // Details of the Exception in the Listener must not be sent
                        Assert.DoesNotContain("InvalidOperationException", response.ReasonPhrase);
                        Assert.DoesNotContain(userExceptionMessage, response.ReasonPhrase);
                    }
                }

                await listener.CloseAsync(TimeSpan.FromSeconds(10));
            }
            finally
            {
                await SafeCloseAsync(listener);
            }
        }
        async Task ResponseHeadersAfterBody(EndpointTestType endpointTestType)
        {
            var cts      = new CancellationTokenSource(TimeSpan.FromSeconds(60));
            var listener = this.GetHybridConnectionListener(endpointTestType);

            try
            {
                await listener.OpenAsync(cts.Token);

                var requestHandlerComplete = new TaskCompletionSource <object>();
                listener.RequestHandler = (context) =>
                {
                    TestUtility.Log($"RequestHandler: {context.Request.HttpMethod} {context.Request.Url}");
                    try
                    {
                        // Begin writing to the output stream
                        context.Response.OutputStream.WriteByte((byte)'X');

                        // Now try to change some things which are no longer mutable
                        var exception = Assert.Throws <InvalidOperationException>(() => context.Response.StatusCode = HttpStatusCode.Found);
                        Assert.Contains("TrackingId", exception.Message, StringComparison.OrdinalIgnoreCase);
                        exception = Assert.Throws <InvalidOperationException>(() => context.Response.StatusDescription = "Test Description");
                        Assert.Contains("TrackingId", exception.Message, StringComparison.OrdinalIgnoreCase);
                        exception = Assert.Throws <InvalidOperationException>(() => context.Response.Headers["CustomHeader"] = "Header value");
                        Assert.Contains("TrackingId", exception.Message, StringComparison.OrdinalIgnoreCase);

                        context.Response.OutputStream.Close();
                        requestHandlerComplete.TrySetResult(null);
                    }
                    catch (Exception e)
                    {
                        requestHandlerComplete.TrySetException(e);
                    }
                };

                RelayConnectionStringBuilder connectionString = GetConnectionStringBuilder(endpointTestType);
                Uri endpointUri   = connectionString.Endpoint;
                Uri hybridHttpUri = new UriBuilder("https://", endpointUri.Host, endpointUri.Port, connectionString.EntityPath).Uri;

                using (var client = new HttpClient {
                    BaseAddress = hybridHttpUri
                })
                {
                    client.DefaultRequestHeaders.ExpectContinue = false;

                    var getRequest = new HttpRequestMessage();
                    await AddAuthorizationHeader(connectionString, getRequest, hybridHttpUri);

                    LogRequest(getRequest, client);
                    var sendTask = client.SendAsync(getRequest);

                    // This will throw if anything failed in the RequestHandler
                    await requestHandlerComplete.Task;

                    using (HttpResponseMessage response = await sendTask)
                    {
                        LogResponse(response);
                        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
                        Assert.Equal(1, (await response.Content.ReadAsStreamAsync()).Length);
                    }
                }

                await listener.CloseAsync(cts.Token);
            }
            finally
            {
                await SafeCloseAsync(listener);
            }
        }
示例#27
0
        async Task AcceptHandlerTest(EndpointTestType endpointTestType)
        {
            HybridConnectionListener listener = null;

            try
            {
                listener = GetHybridConnectionListener(endpointTestType);
                TestUtility.Log($"Opening {listener}");
                await listener.OpenAsync(TimeSpan.FromSeconds(30));

                // Install a Custom AcceptHandler which allows using Headers to control the StatusCode, StatusDescription,
                // and whether to accept or reject the client.
                listener.AcceptHandler = TestAcceptHandler;

                var clientConnectionString = GetConnectionString(endpointTestType);

                var connectionStringBuilder = new RelayConnectionStringBuilder(clientConnectionString);

                var wssUri = await GetWebSocketConnectionUri(endpointTestType);

                TestUtility.Log($"Using WebSocket address {wssUri}");
                using (var cancelSource = new CancellationTokenSource(TimeSpan.FromMinutes(1)))
                {
                    TestUtility.Log("Testing HybridConnectionListener.AcceptHandler accepting with only returning true");
                    AcceptEchoListener(listener);
                    var clientWebSocket = new ClientWebSocket();
                    clientWebSocket.Options.SetRequestHeader(TestAcceptHandlerResultHeader, true.ToString());
                    await clientWebSocket.ConnectAsync(wssUri, cancelSource.Token);

                    await clientWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Test closing web socket", cancelSource.Token);

                    TestUtility.Log("Testing HybridConnectionListener.AcceptHandler accepting and setting response header");
                    AcceptEchoListener(listener);
                    clientWebSocket = new ClientWebSocket();
                    clientWebSocket.Options.SetRequestHeader(TestAcceptHandlerResultHeader, true.ToString());
                    clientWebSocket.Options.SetRequestHeader(TestAcceptHandlerSetResponseHeader, "X-CustomHeader: Test value");
                    await clientWebSocket.ConnectAsync(wssUri, cancelSource.Token);

                    await clientWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Test closing web socket", cancelSource.Token);

                    TestUtility.Log("Testing HybridConnectionListener.AcceptHandler rejecting with only returning false");
                    AcceptEchoListener(listener);
                    HttpStatusCode expectedStatusCode        = HttpStatusCode.BadRequest;
                    string         expectedStatusDescription = "Rejected by user code";
                    clientWebSocket = new ClientWebSocket();
                    clientWebSocket.Options.SetRequestHeader(TestAcceptHandlerResultHeader, false.ToString());
                    var webSocketException = await Assert.ThrowsAsync <WebSocketException>(() => clientWebSocket.ConnectAsync(wssUri, cancelSource.Token));

                    VerifyHttpStatusCodeAndDescription(webSocketException, expectedStatusCode, expectedStatusDescription);

                    TestUtility.Log("Testing HybridConnectionListener.AcceptHandler rejecting with setting status code and returning false");
                    AcceptEchoListener(listener);
                    expectedStatusCode        = HttpStatusCode.Unauthorized;
                    expectedStatusDescription = "Unauthorized";
                    clientWebSocket           = new ClientWebSocket();
                    clientWebSocket.Options.SetRequestHeader(TestAcceptHandlerResultHeader, false.ToString());
                    clientWebSocket.Options.SetRequestHeader(TestAcceptHandlerStatusCodeHeader, ((int)expectedStatusCode).ToString());
                    webSocketException = await Assert.ThrowsAsync <WebSocketException>(() => clientWebSocket.ConnectAsync(wssUri, cancelSource.Token));

                    VerifyHttpStatusCodeAndDescription(webSocketException, expectedStatusCode, expectedStatusDescription);

                    TestUtility.Log("Testing HybridConnectionListener.AcceptHandler rejecting with setting status code+description and returning false");
                    AcceptEchoListener(listener);
                    expectedStatusCode        = HttpStatusCode.Unauthorized;
                    expectedStatusDescription = "Status Description from test";
                    clientWebSocket           = new ClientWebSocket();
                    clientWebSocket.Options.SetRequestHeader(TestAcceptHandlerResultHeader, false.ToString());
                    clientWebSocket.Options.SetRequestHeader(TestAcceptHandlerStatusCodeHeader, ((int)expectedStatusCode).ToString());
                    clientWebSocket.Options.SetRequestHeader(TestAcceptHandlerStatusDescriptionHeader, expectedStatusDescription);
                    webSocketException = await Assert.ThrowsAsync <WebSocketException>(() => clientWebSocket.ConnectAsync(wssUri, cancelSource.Token));

                    VerifyHttpStatusCodeAndDescription(webSocketException, expectedStatusCode, expectedStatusDescription);

                    TestUtility.Log("Testing HybridConnectionListener.AcceptHandler with a custom handler that returns null instead of a valid Task<bool>");
                    listener.AcceptHandler = context => null;
                    AcceptEchoListener(listener);
                    expectedStatusCode        = HttpStatusCode.BadGateway;
                    expectedStatusDescription = "The Listener's custom AcceptHandler threw an exception. See Listener logs for details.";
                    clientWebSocket           = new ClientWebSocket();
                    webSocketException        = await Assert.ThrowsAsync <WebSocketException>(() => clientWebSocket.ConnectAsync(wssUri, cancelSource.Token));

                    VerifyHttpStatusCodeAndDescription(webSocketException, expectedStatusCode, expectedStatusDescription, false);
                }
            }
            finally
            {
                await SafeCloseAsync(listener);
            }
        }