From 6fab49b6e0640865bb87730ec18f992df21631fc Mon Sep 17 00:00:00 2001 From: Chris Ross Date: Thu, 24 Jul 2014 16:13:03 -0700 Subject: [PATCH] #52 - Enable parallel tests by using dynamic ports. --- src/Microsoft.Net.Server/UrlPrefix.cs | 34 +++++++-- .../AuthenticationTests.cs | 73 +++++++++++-------- ...t.Server.WebListener.FunctionalTests.kproj | 1 - .../OpaqueUpgradeTests.cs | 30 ++++---- .../Properties/AssemblyInfo.cs | 19 ----- .../RequestBodyTests.cs | 37 ++++++---- .../RequestHeaderTests.cs | 29 ++++---- .../RequestTests.cs | 42 ++++++----- .../ResponseBodyTests.cs | 42 ++++++----- .../ResponseHeaderTests.cs | 59 ++++++++------- .../ResponseSendFileTests.cs | 66 ++++++++++------- .../ResponseTests.cs | 32 ++++---- .../ServerTests.cs | 59 +++++++++------ .../Utilities.cs | 66 +++++++++++++---- .../WebSocketTests.cs | 30 +++++--- .../AuthenticationTests.cs | 32 ++++---- .../HttpsTests.cs | 1 + ...Microsoft.Net.Server.FunctionalTests.kproj | 1 - .../OpaqueUpgradeTests.cs | 24 +++--- .../Properties/AssemblyInfo.cs | 8 -- .../RequestBodyTests.cs | 37 ++++++---- .../RequestHeaderTests.cs | 28 +++---- .../RequestTests.cs | 39 +++++----- .../ResponseBodyTests.cs | 32 ++++---- .../ResponseHeaderTests.cs | 47 +++++++----- .../ResponseSendFileTests.cs | 61 +++++++++------- .../ResponseTests.cs | 32 ++++---- .../ServerTests.cs | 33 +++++---- .../Utilities.cs | 66 +++++++++++++---- .../WebSocketTests.cs | 27 ++++--- 30 files changed, 636 insertions(+), 451 deletions(-) delete mode 100644 test/Microsoft.AspNet.Server.WebListener.FunctionalTests/Properties/AssemblyInfo.cs delete mode 100644 test/Microsoft.Net.Server.FunctionalTests/Properties/AssemblyInfo.cs diff --git a/src/Microsoft.Net.Server/UrlPrefix.cs b/src/Microsoft.Net.Server/UrlPrefix.cs index f8b8783813..0d1e732bef 100644 --- a/src/Microsoft.Net.Server/UrlPrefix.cs +++ b/src/Microsoft.Net.Server/UrlPrefix.cs @@ -47,6 +47,24 @@ namespace Microsoft.Net.Server /// If empty, the default port for the given scheme will be used (80 or 443). /// Should start and end with a '/', though a missing trailing slash will be added. This value must be un-escaped. public static UrlPrefix Create(string scheme, string host, string port, string path) + { + int? portValue = null; + if (!string.IsNullOrWhiteSpace(port)) + { + portValue = int.Parse(port, NumberStyles.None, CultureInfo.InvariantCulture); + } + + return UrlPrefix.Create(scheme, host, portValue, path); + } + + /// + /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364698(v=vs.85).aspx + /// + /// http or https. Will be normalized to lower case. + /// +, *, IPv4, [IPv6], or a dns name. Http.Sys does not permit punycode (xn--), use Unicode instead. + /// If empty, the default port for the given scheme will be used (80 or 443). + /// Should start and end with a '/', though a missing trailing slash will be added. This value must be un-escaped. + public static UrlPrefix Create(string scheme, string host, int? portValue, string path) { bool isHttps; if (string.Equals(Constants.HttpScheme, scheme, StringComparison.OrdinalIgnoreCase)) @@ -69,15 +87,15 @@ namespace Microsoft.Net.Server throw new ArgumentNullException("host"); } - int portValue; - if (string.IsNullOrWhiteSpace(port)) + string port; + if (!portValue.HasValue) { port = isHttps ? "443" : "80"; portValue = isHttps ? 443 : 80; } else { - portValue = int.Parse(port, NumberStyles.None, CultureInfo.InvariantCulture); + port = portValue.Value.ToString(CultureInfo.InvariantCulture); } // Http.Sys requires the path end with a slash. @@ -90,14 +108,14 @@ namespace Microsoft.Net.Server path += "/"; } - return new UrlPrefix(isHttps, scheme, host, port, portValue, path); + return new UrlPrefix(isHttps, scheme, host, port, portValue.Value, path); } public static UrlPrefix Create(string prefix) { string scheme = null; string host = null; - string port = null; + int? port = null; string path = null; string whole = prefix ?? string.Empty; @@ -123,11 +141,11 @@ namespace Microsoft.Net.Server scheme = whole.Substring(0, delimiterStart1); string portString = whole.Substring(delimiterEnd2, delimiterStart3 - delimiterEnd2); - int ignored; - if (int.TryParse(portString, NumberStyles.Integer, CultureInfo.InvariantCulture, out ignored)) + int portValue; + if (int.TryParse(portString, NumberStyles.Integer, CultureInfo.InvariantCulture, out portValue)) { host = whole.Substring(delimiterEnd1, delimiterStart2 - delimiterEnd1); - port = portString; + port = portValue; } else { diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/AuthenticationTests.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/AuthenticationTests.cs index db7417482d..acb4313ea1 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/AuthenticationTests.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/AuthenticationTests.cs @@ -29,8 +29,6 @@ namespace Microsoft.AspNet.Server.WebListener { public class AuthenticationTests { - private const string Address = "http://localhost:8080/"; - [Theory] [InlineData(AuthenticationTypes.AllowAnonymous)] [InlineData(AuthenticationTypes.Kerberos)] @@ -41,7 +39,8 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData(AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /*AuthenticationTypes.Digest |*/ AuthenticationTypes.Basic)] public async Task AuthTypes_AllowAnonymous_NoChallenge(AuthenticationTypes authType) { - using (Utilities.CreateAuthServer(authType | AuthenticationTypes.AllowAnonymous, env => + string address; + using (Utilities.CreateHttpAuthServer(authType | AuthenticationTypes.AllowAnonymous, out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); Assert.NotNull(context.User); @@ -49,7 +48,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address); + var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(0, response.Headers.WwwAuthenticate.Count); } @@ -63,12 +62,13 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData(AuthenticationTypes.Basic)] public async Task AuthType_RequireAuth_ChallengesAdded(AuthenticationTypes authType) { - using (Utilities.CreateAuthServer(authType, env => + string address; + using (Utilities.CreateHttpAuthServer(authType, out address, env => { throw new NotImplementedException(); })) { - var response = await SendRequestAsync(Address); + var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(authType.ToString(), response.Headers.WwwAuthenticate.ToString(), StringComparer.OrdinalIgnoreCase); } @@ -82,7 +82,8 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData(AuthenticationTypes.Basic)] public async Task AuthType_AllowAnonymousButSpecify401_ChallengesAdded(AuthenticationTypes authType) { - using (Utilities.CreateAuthServer(authType | AuthenticationTypes.AllowAnonymous, env => + string address; + using (Utilities.CreateHttpAuthServer(authType | AuthenticationTypes.AllowAnonymous, out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); Assert.NotNull(context.User); @@ -91,7 +92,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address); + var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(authType.ToString(), response.Headers.WwwAuthenticate.ToString(), StringComparer.OrdinalIgnoreCase); } @@ -100,13 +101,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task MultipleAuthTypes_AllowAnonymousButSpecify401_ChallengesAdded() { - using (Utilities.CreateAuthServer( + string address; + using (Utilities.CreateHttpAuthServer( AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM /* | AuthenticationTypes.Digest TODO: Not implemented */ | AuthenticationTypes.Basic | AuthenticationTypes.AllowAnonymous, + out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); @@ -116,7 +119,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address); + var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal("Kerberos, Negotiate, NTLM, basic", response.Headers.WwwAuthenticate.ToString(), StringComparer.OrdinalIgnoreCase); } @@ -131,8 +134,9 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData(AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /* AuthenticationTypes.Digest |*/ AuthenticationTypes.Basic)] public async Task AuthTypes_AllowAnonymousButSpecify401_Success(AuthenticationTypes authType) { + string address; int requestId = 0; - using (Utilities.CreateAuthServer(authType | AuthenticationTypes.AllowAnonymous, env => + using (Utilities.CreateHttpAuthServer(authType | AuthenticationTypes.AllowAnonymous, out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); Assert.NotNull(context.User); @@ -153,7 +157,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address, useDefaultCredentials: true); + var response = await SendRequestAsync(address, useDefaultCredentials: true); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } } @@ -167,7 +171,8 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData(AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /* AuthenticationTypes.Digest |*/ AuthenticationTypes.Basic)] public async Task AuthTypes_RequireAuth_Success(AuthenticationTypes authType) { - using (Utilities.CreateAuthServer(authType, env => + string address; + using (Utilities.CreateHttpAuthServer(authType, out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); Assert.NotNull(context.User); @@ -175,7 +180,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address, useDefaultCredentials: true); + var response = await SendRequestAsync(address, useDefaultCredentials: true); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } } @@ -190,7 +195,8 @@ namespace Microsoft.AspNet.Server.WebListener // [InlineData(AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /*AuthenticationTypes.Digest |*/ AuthenticationTypes.Basic)] public async Task AuthTypes_GetSingleDescriptions(AuthenticationTypes authType) { - using (Utilities.CreateAuthServer(authType | AuthenticationTypes.AllowAnonymous, env => + string address; + using (Utilities.CreateHttpAuthServer(authType | AuthenticationTypes.AllowAnonymous, out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); var resultList = context.GetAuthenticationTypes(); @@ -209,7 +215,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address); + var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(0, response.Headers.WwwAuthenticate.Count); } @@ -218,13 +224,14 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task AuthTypes_GetMultipleDescriptions() { + string address; AuthenticationTypes authType = AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /*AuthenticationTypes.Digest |*/ AuthenticationTypes.Basic; - using (Utilities.CreateAuthServer(authType | AuthenticationTypes.AllowAnonymous, env => + using (Utilities.CreateHttpAuthServer(authType | AuthenticationTypes.AllowAnonymous, out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); var resultList = context.GetAuthenticationTypes(); @@ -232,7 +239,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address); + var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(0, response.Headers.WwwAuthenticate.Count); } @@ -247,8 +254,9 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData(AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /*AuthenticationTypes.Digest |*/ AuthenticationTypes.Basic)] public async Task AuthTypes_AuthenticateWithNoUser_NoResults(AuthenticationTypes authType) { + string address; var authTypeList = authType.ToString().Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); - using (Utilities.CreateAuthServer(authType | AuthenticationTypes.AllowAnonymous, env => + using (Utilities.CreateHttpAuthServer(authType | AuthenticationTypes.AllowAnonymous, out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); Assert.NotNull(context.User); @@ -258,7 +266,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address); + var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(0, response.Headers.WwwAuthenticate.Count); } @@ -273,8 +281,9 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData(AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /*AuthenticationTypes.Digest |*/ AuthenticationTypes.Basic)] public async Task AuthTypes_AuthenticateWithUser_OneResult(AuthenticationTypes authType) { + string address; var authTypeList = authType.ToString().Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); - using (Utilities.CreateAuthServer(authType, env => + using (Utilities.CreateHttpAuthServer(authType, out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); Assert.NotNull(context.User); @@ -284,7 +293,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address, useDefaultCredentials: true); + var response = await SendRequestAsync(address, useDefaultCredentials: true); Assert.Equal(HttpStatusCode.OK, response.StatusCode); } } @@ -298,8 +307,9 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData(AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /*AuthenticationTypes.Digest |*/ AuthenticationTypes.Basic)] public async Task AuthTypes_ChallengeWithoutAuthTypes_AllChallengesSent(AuthenticationTypes authType) { + string address; var authTypeList = authType.ToString().Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); - using (Utilities.CreateAuthServer(authType | AuthenticationTypes.AllowAnonymous, env => + using (Utilities.CreateHttpAuthServer(authType | AuthenticationTypes.AllowAnonymous, out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); Assert.NotNull(context.User); @@ -308,7 +318,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address); + var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(authTypeList.Count(), response.Headers.WwwAuthenticate.Count); } @@ -323,8 +333,9 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData(AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /*AuthenticationTypes.Digest |*/ AuthenticationTypes.Basic)] public async Task AuthTypes_ChallengeWithAllAuthTypes_AllChallengesSent(AuthenticationTypes authType) { + string address; var authTypeList = authType.ToString().Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); - using (Utilities.CreateAuthServer(authType | AuthenticationTypes.AllowAnonymous, env => + using (Utilities.CreateHttpAuthServer(authType | AuthenticationTypes.AllowAnonymous, out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); Assert.NotNull(context.User); @@ -333,7 +344,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address); + var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(authTypeList.Count(), response.Headers.WwwAuthenticate.Count); } @@ -347,8 +358,9 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData(AuthenticationTypes.Basic)] public async Task AuthTypes_ChallengeOneAuthType_OneChallengeSent(AuthenticationTypes authType) { + string address; var authTypes = AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /*AuthenticationTypes.Digest |*/ AuthenticationTypes.Basic; - using (Utilities.CreateAuthServer(authTypes | AuthenticationTypes.AllowAnonymous, env => + using (Utilities.CreateHttpAuthServer(authTypes | AuthenticationTypes.AllowAnonymous, out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); Assert.NotNull(context.User); @@ -357,7 +369,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address); + var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(1, response.Headers.WwwAuthenticate.Count); Assert.Equal(authType.ToString(), response.Headers.WwwAuthenticate.First().Scheme); @@ -372,10 +384,11 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData(AuthenticationTypes.Basic)] public async Task AuthTypes_ChallengeDisabledAuthType_Error(AuthenticationTypes authType) { + string address; var authTypes = AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /*AuthenticationTypes.Digest |*/ AuthenticationTypes.Basic; authTypes = authTypes & ~authType; var authTypeList = authType.ToString().Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries); - using (Utilities.CreateAuthServer(authTypes | AuthenticationTypes.AllowAnonymous, env => + using (Utilities.CreateHttpAuthServer(authTypes | AuthenticationTypes.AllowAnonymous, out address, env => { var context = new DefaultHttpContext((IFeatureCollection)env); Assert.NotNull(context.User); @@ -384,7 +397,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - var response = await SendRequestAsync(Address); + var response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(0, response.Headers.WwwAuthenticate.Count); } diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/Microsoft.AspNet.Server.WebListener.FunctionalTests.kproj b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/Microsoft.AspNet.Server.WebListener.FunctionalTests.kproj index afd9e549f3..93e75d54f4 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/Microsoft.AspNet.Server.WebListener.FunctionalTests.kproj +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/Microsoft.AspNet.Server.WebListener.FunctionalTests.kproj @@ -22,7 +22,6 @@ - diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/OpaqueUpgradeTests.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/OpaqueUpgradeTests.cs index 345092d7ff..cfbcb1827c 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/OpaqueUpgradeTests.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/OpaqueUpgradeTests.cs @@ -16,7 +16,6 @@ // permissions and limitations under the License. using System; -using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Net.Sockets; @@ -24,8 +23,8 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNet.FeatureModel; -using Microsoft.AspNet.HttpFeature; using Microsoft.AspNet.Http; +using Microsoft.AspNet.HttpFeature; using Microsoft.AspNet.PipelineCore; using Xunit; @@ -33,12 +32,11 @@ namespace Microsoft.AspNet.Server.WebListener { public class OpaqueUpgradeTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task OpaqueUpgrade_SupportKeys_Present() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); try @@ -53,7 +51,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); Assert.False(response.Headers.TransferEncodingChunked.HasValue, "Chunked"); Assert.Equal(0, response.Content.Headers.ContentLength); @@ -65,7 +63,8 @@ namespace Microsoft.AspNet.Server.WebListener public async Task OpaqueUpgrade_AfterHeadersSent_Throws() { bool? upgradeThrew = null; - using (Utilities.CreateHttpServer(async env => + string address; + using (Utilities.CreateHttpServer(out address, async env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); await httpContext.Response.WriteAsync("Hello World"); @@ -82,7 +81,7 @@ namespace Microsoft.AspNet.Server.WebListener } })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); Assert.True(response.Headers.TransferEncodingChunked.Value, "Chunked"); Assert.True(upgradeThrew.Value); @@ -94,7 +93,8 @@ namespace Microsoft.AspNet.Server.WebListener { ManualResetEvent waitHandle = new ManualResetEvent(false); bool? upgraded = null; - using (Utilities.CreateHttpServer(async env => + string address; + using (Utilities.CreateHttpServer(out address, async env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Response.Headers["Upgrade"] = "websocket"; // Win8.1 blocks anything but WebSockets @@ -106,7 +106,7 @@ namespace Microsoft.AspNet.Server.WebListener waitHandle.Set(); })) { - using (Stream stream = await SendOpaqueRequestAsync("GET", Address)) + using (Stream stream = await SendOpaqueRequestAsync("GET", address)) { Assert.True(waitHandle.WaitOne(TimeSpan.FromSeconds(1)), "Timed out"); Assert.True(upgraded.HasValue, "Upgraded not set"); @@ -140,7 +140,8 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData("PUT", "Content-Length: 0")] public async Task OpaqueUpgrade_VariousMethodsUpgradeSendAndReceive_Success(string method, string extraHeader) { - using (Utilities.CreateHttpServer(async env => + string address; + using (Utilities.CreateHttpServer(out address, async env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); try @@ -162,7 +163,7 @@ namespace Microsoft.AspNet.Server.WebListener } })) { - using (Stream stream = await SendOpaqueRequestAsync(method, Address, extraHeader)) + using (Stream stream = await SendOpaqueRequestAsync(method, address, extraHeader)) { byte[] data = new byte[100]; stream.WriteAsync(data, 0, 49).Wait(); @@ -182,7 +183,8 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData("CUSTOMVERB", "Transfer-Encoding: chunked")] public async Task OpaqueUpgrade_InvalidMethodUpgrade_Disconnected(string method, string extraHeader) { - using (Utilities.CreateHttpServer(async env => + string address; + using (Utilities.CreateHttpServer(out address, async env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); try @@ -197,7 +199,7 @@ namespace Microsoft.AspNet.Server.WebListener } })) { - await Assert.ThrowsAsync(async () => await SendOpaqueRequestAsync(method, Address, extraHeader)); + await Assert.ThrowsAsync(async () => await SendOpaqueRequestAsync(method, address, extraHeader)); } } diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/Properties/AssemblyInfo.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/Properties/AssemblyInfo.cs deleted file mode 100644 index a462d9475f..0000000000 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) Microsoft Open Technologies, Inc. -// All Rights Reserved -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING -// WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF -// TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR -// NON-INFRINGEMENT. -// See the Apache 2 License for the specific language governing -// permissions and limitations under the License. - -// These tests can't run in parallel because they all use the same port. -[assembly: Xunit.CollectionBehaviorAttribute(Xunit.CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true)] diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestBodyTests.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestBodyTests.cs index 62edea48b6..8a92ce2a04 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestBodyTests.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestBodyTests.cs @@ -31,12 +31,11 @@ namespace Microsoft.AspNet.Server.WebListener { public class RequestBodyTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task RequestBody_ReadSync_Success() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); byte[] input = new byte[100]; @@ -46,7 +45,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - string response = await SendRequestAsync(Address, "Hello World"); + string response = await SendRequestAsync(address, "Hello World"); Assert.Equal("Hello World", response); } } @@ -54,7 +53,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task RequestBody_ReadAync_Success() { - using (Utilities.CreateHttpServer(async env => + string address; + using (Utilities.CreateHttpServer(out address, async env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); byte[] input = new byte[100]; @@ -63,7 +63,7 @@ namespace Microsoft.AspNet.Server.WebListener await httpContext.Response.Body.WriteAsync(input, 0, read); })) { - string response = await SendRequestAsync(Address, "Hello World"); + string response = await SendRequestAsync(address, "Hello World"); Assert.Equal("Hello World", response); } } @@ -71,7 +71,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task RequestBody_ReadBeginEnd_Success() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); byte[] input = new byte[100]; @@ -81,7 +82,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - string response = await SendRequestAsync(Address, "Hello World"); + string response = await SendRequestAsync(address, "Hello World"); Assert.Equal("Hello World", response); } } @@ -90,7 +91,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task RequestBody_InvalidBuffer_ArgumentException() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); byte[] input = new byte[100]; @@ -104,7 +106,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - string response = await SendRequestAsync(Address, "Hello World"); + string response = await SendRequestAsync(address, "Hello World"); Assert.Equal(string.Empty, response); } } @@ -113,7 +115,8 @@ namespace Microsoft.AspNet.Server.WebListener public async Task RequestBody_ReadSyncPartialBody_Success() { StaggardContent content = new StaggardContent(); - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); byte[] input = new byte[10]; @@ -125,7 +128,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - string response = await SendRequestAsync(Address, content); + string response = await SendRequestAsync(address, content); Assert.Equal(string.Empty, response); } } @@ -134,7 +137,8 @@ namespace Microsoft.AspNet.Server.WebListener public async Task RequestBody_ReadAsyncPartialBody_Success() { StaggardContent content = new StaggardContent(); - using (Utilities.CreateHttpServer(async env => + string address; + using (Utilities.CreateHttpServer(out address, async env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); byte[] input = new byte[10]; @@ -145,7 +149,7 @@ namespace Microsoft.AspNet.Server.WebListener Assert.Equal(5, read); })) { - string response = await SendRequestAsync(Address, content); + string response = await SendRequestAsync(address, content); Assert.Equal(string.Empty, response); } } @@ -153,7 +157,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task RequestBody_PostWithImidateBody_Success() { - using (Utilities.CreateHttpServer(async env => + string address; + using (Utilities.CreateHttpServer(out address, async env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); byte[] input = new byte[11]; @@ -165,7 +170,7 @@ namespace Microsoft.AspNet.Server.WebListener await httpContext.Response.Body.WriteAsync(input, 0, 10); })) { - string response = await SendSocketRequestAsync(Address); + string response = await SendSocketRequestAsync(address); string[] lines = response.Split('\r', '\n'); Assert.Equal(13, lines.Length); Assert.Equal("HTTP/1.1 200 OK", lines[0]); diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestHeaderTests.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestHeaderTests.cs index d87dadcc65..14af34cc55 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestHeaderTests.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestHeaderTests.cs @@ -28,23 +28,22 @@ namespace Microsoft.AspNet.Server.WebListener { public class RequestHeaderTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task RequestHeaders_ClientSendsDefaultHeaders_Success() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var requestHeaders = new DefaultHttpContext((IFeatureCollection)env).Request.Headers; // NOTE: The System.Net client only sends the Connection: keep-alive header on the first connection per service-point. // Assert.Equal(2, requestHeaders.Count); // Assert.Equal("Keep-Alive", requestHeaders.Get("Connection")); - Assert.Equal("localhost:8080", requestHeaders.Get("Host")); + Assert.NotNull(requestHeaders.Get("Host")); Assert.Equal(null, requestHeaders.Get("Accept")); return Task.FromResult(0); })) { - string response = await SendRequestAsync(Address); + string response = await SendRequestAsync(address); Assert.Equal(string.Empty, response); } } @@ -52,23 +51,24 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task RequestHeaders_ClientSendsCustomHeaders_Success() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var requestHeaders = new DefaultHttpContext((IFeatureCollection)env).Request.Headers; Assert.Equal(4, requestHeaders.Count); - Assert.Equal("localhost:8080", requestHeaders.Get("Host")); + Assert.NotNull(requestHeaders.Get("Host")); Assert.Equal("close", requestHeaders.Get("Connection")); - Assert.Equal(1, requestHeaders["Custom-Header"].Length); // Apparently Http.Sys squashes request headers together. + Assert.Equal(1, requestHeaders.GetValues("Custom-Header").Count); Assert.Equal("custom1, and custom2, custom3", requestHeaders.Get("Custom-Header")); - Assert.Equal(1, requestHeaders["Spacer-Header"].Length); + Assert.Equal(1, requestHeaders.GetValues("Spacer-Header").Count); Assert.Equal("spacervalue, spacervalue", requestHeaders.Get("Spacer-Header")); return Task.FromResult(0); })) { string[] customValues = new string[] { "custom1, and custom2", "custom3" }; - await SendRequestAsync("localhost", 8080, "Custom-Header", customValues); + await SendRequestAsync(address, "Custom-Header", customValues); } } @@ -80,15 +80,14 @@ namespace Microsoft.AspNet.Server.WebListener } } - private async Task SendRequestAsync(string host, int port, string customHeader, string[] customValues) + private async Task SendRequestAsync(string address, string customHeader, string[] customValues) { + var uri = new Uri(address); StringBuilder builder = new StringBuilder(); builder.AppendLine("GET / HTTP/1.1"); builder.AppendLine("Connection: close"); builder.Append("HOST: "); - builder.Append(host); - builder.Append(':'); - builder.AppendLine(port.ToString()); + builder.AppendLine(uri.Authority); foreach (string value in customValues) { builder.Append(customHeader); @@ -101,7 +100,7 @@ namespace Microsoft.AspNet.Server.WebListener byte[] request = Encoding.ASCII.GetBytes(builder.ToString()); Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp); - socket.Connect(host, port); + socket.Connect(uri.Host, uri.Port); socket.Send(request); diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestTests.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestTests.cs index 57bb19b423..1cd71e5a03 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestTests.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/RequestTests.cs @@ -32,12 +32,11 @@ namespace Microsoft.AspNet.Server.WebListener public class RequestTests { - private const string Address = "http://localhost:8080"; - [Fact] public async Task Request_SimpleGet_Success() { - using (Utilities.CreateServer("http", "localhost", "8080", "/basepath", env => + string root; + using (Utilities.CreateHttpServerReturnRoot("/basepath", out root, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); try @@ -77,21 +76,22 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - string response = await SendRequestAsync(Address + "/basepath/SomePath?SomeQuery"); + string response = await SendRequestAsync(root + "/basepath/SomePath?SomeQuery"); Assert.Equal(string.Empty, response); } } [Theory] - [InlineData("/", "http://localhost:8080/", "", "/")] - [InlineData("/basepath/", "http://localhost:8080/basepath", "/basepath", "")] - [InlineData("/basepath/", "http://localhost:8080/basepath/", "/basepath", "/")] - [InlineData("/basepath/", "http://localhost:8080/basepath/subpath", "/basepath", "/subpath")] - [InlineData("/base path/", "http://localhost:8080/base%20path/sub path", "/base path", "/sub path")] - [InlineData("/base葉path/", "http://localhost:8080/base%E8%91%89path/sub%E8%91%89path", "/base葉path", "/sub葉path")] - public async Task Request_PathSplitting(string pathBase, string requestUri, string expectedPathBase, string expectedPath) + [InlineData("/", "/", "", "/")] + [InlineData("/basepath/", "/basepath", "/basepath", "")] + [InlineData("/basepath/", "/basepath/", "/basepath", "/")] + [InlineData("/basepath/", "/basepath/subpath", "/basepath", "/subpath")] + [InlineData("/base path/", "/base%20path/sub path", "/base path", "/sub path")] + [InlineData("/base葉path/", "/base%E8%91%89path/sub%E8%91%89path", "/base葉path", "/sub葉path")] + public async Task Request_PathSplitting(string pathBase, string requestPath, string expectedPathBase, string expectedPath) { - using (Utilities.CreateServer("http", "localhost", "8080", pathBase, env => + string root; + using (Utilities.CreateHttpServerReturnRoot(pathBase, out root, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); try @@ -104,7 +104,6 @@ namespace Microsoft.AspNet.Server.WebListener Assert.Equal(expectedPath, requestInfo.Path); Assert.Equal(expectedPathBase, requestInfo.PathBase); Assert.Equal(string.Empty, requestInfo.QueryString); - Assert.Equal(8080, connectionInfo.LocalPort); } catch (Exception ex) { @@ -114,7 +113,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - string response = await SendRequestAsync(requestUri); + string response = await SendRequestAsync(root + requestPath); Assert.Equal(string.Empty, response); } } @@ -132,9 +131,10 @@ namespace Microsoft.AspNet.Server.WebListener [InlineData("/2/3", "/2/3", "")] [InlineData("/2/3/", "/2/3", "/")] [InlineData("/2/3/random", "/2/3", "/random")] - public async Task Request_MultiplePrefixes(string requestUri, string expectedPathBase, string expectedPath) + public async Task Request_MultiplePrefixes(string requestPath, string expectedPathBase, string expectedPath) { - using (CreateServer(env => + string root; + using (CreateServer(out root, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var requestInfo = httpContext.GetFeature(); @@ -151,19 +151,23 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - string response = await SendRequestAsync(Address + requestUri); + string response = await SendRequestAsync(root + requestPath); Assert.Equal(string.Empty, response); } } - private IDisposable CreateServer(AppFunc app) + private IDisposable CreateServer(out string root, AppFunc app) { + // TODO: We're just doing this to get a dynamic port. This can be removed later when we add support for hot-adding prefixes. + var server = Utilities.CreateHttpServerReturnRoot("/", out root, app); + server.Dispose(); + var rootUri = new Uri(root); var factory = new ServerFactory(loggerFactory: null); var serverInfo = (ServerInformation)factory.Initialize(configuration: null); foreach (string path in new[] { "/", "/11", "/2/3", "/2", "/11/2" }) { - serverInfo.Listener.UrlPrefixes.Add(UrlPrefix.Create("http", "localhost", "8080", path)); + serverInfo.Listener.UrlPrefixes.Add(UrlPrefix.Create(rootUri.Scheme, rootUri.Host, rootUri.Port, path)); } return factory.Start(serverInfo, app); diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseBodyTests.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseBodyTests.cs index 3aa245dddb..11acdde941 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseBodyTests.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseBodyTests.cs @@ -30,19 +30,18 @@ namespace Microsoft.AspNet.Server.WebListener { public class ResponseBodyTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task ResponseBody_WriteNoHeaders_DefaultsToChunked() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Response.Body.Write(new byte[10], 0, 10); return httpContext.Response.Body.WriteAsync(new byte[10], 0, 10); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); Assert.Equal(new Version(1, 1), response.Version); IEnumerable ignored; @@ -55,7 +54,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseBody_WriteChunked_Chunked() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Request.Headers["transfeR-Encoding"] = " CHunked "; @@ -65,7 +65,7 @@ namespace Microsoft.AspNet.Server.WebListener return stream.WriteAsync(new byte[10], 0, 10); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); Assert.Equal(new Version(1, 1), response.Version); IEnumerable ignored; @@ -78,7 +78,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseBody_WriteContentLength_PassedThrough() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Response.Headers["Content-lenGth"] = " 30 "; @@ -88,7 +89,7 @@ namespace Microsoft.AspNet.Server.WebListener return stream.WriteAsync(new byte[10], 0, 10); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); Assert.Equal(new Version(1, 1), response.Version); IEnumerable contentLength; @@ -102,14 +103,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseBody_Http10WriteNoHeaders_DefaultsConnectionClose() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { env["owin.ResponseProtocol"] = "HTTP/1.0"; env.Get("owin.ResponseBody").Write(new byte[10], 0, 10); return env.Get("owin.ResponseBody").WriteAsync(new byte[10], 0, 10); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); Assert.Equal(new Version(1, 1), response.Version); // Http.Sys won't transmit 1.0 IEnumerable ignored; @@ -122,21 +124,23 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseBody_WriteContentLengthNoneWritten_Throws() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Response.Headers["Content-lenGth"] = " 20 "; return Task.FromResult(0); })) { - await Assert.ThrowsAsync(() => SendRequestAsync(Address)); + await Assert.ThrowsAsync(() => SendRequestAsync(address)); } } [Fact] public void ResponseBody_WriteContentLengthNotEnoughWritten_Throws() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Response.Headers["Content-lenGth"] = " 20 "; @@ -144,14 +148,15 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - Assert.Throws(() => SendRequestAsync(Address).Result); + Assert.Throws(() => SendRequestAsync(address).Result); } } [Fact] public void ResponseBody_WriteContentLengthTooMuchWritten_Throws() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Response.Headers["Content-lenGth"] = " 10 "; @@ -160,7 +165,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - Assert.Throws(() => SendRequestAsync(Address).Result); + Assert.Throws(() => SendRequestAsync(address).Result); } } @@ -169,7 +174,8 @@ namespace Microsoft.AspNet.Server.WebListener { ManualResetEvent waitHandle = new ManualResetEvent(false); bool? appThrew = null; - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { try { @@ -188,7 +194,7 @@ namespace Microsoft.AspNet.Server.WebListener })) { // The full response is received. - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); Assert.Equal(new Version(1, 1), response.Version); IEnumerable contentLength; diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseHeaderTests.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseHeaderTests.cs index 726455a650..c086ce3cea 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseHeaderTests.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseHeaderTests.cs @@ -29,17 +29,16 @@ namespace Microsoft.AspNet.Server.WebListener { public class ResponseHeaderTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task ResponseHeaders_ServerSendsDefaultHeaders_Success() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); response.EnsureSuccessStatusCode(); Assert.Equal(2, response.Headers.Count()); Assert.False(response.Headers.TransferEncodingChunked.HasValue); @@ -53,7 +52,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseHeaders_ServerSendsSingleValueKnownHeaders_Success() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var responseInfo = httpContext.GetFeature(); @@ -63,7 +63,7 @@ namespace Microsoft.AspNet.Server.WebListener })) { // HttpClient would merge the headers no matter what - WebRequest request = WebRequest.Create(Address); + WebRequest request = WebRequest.Create(address); HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); Assert.Equal(4, response.Headers.Count); Assert.Null(response.Headers["Transfer-Encoding"]); @@ -77,7 +77,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseHeaders_ServerSendsMultiValueKnownHeaders_Success() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var responseInfo = httpContext.GetFeature(); @@ -87,7 +88,7 @@ namespace Microsoft.AspNet.Server.WebListener })) { // HttpClient would merge the headers no matter what - WebRequest request = WebRequest.Create(Address); + WebRequest request = WebRequest.Create(address); HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); Assert.Equal(4, response.Headers.Count); Assert.Null(response.Headers["Transfer-Encoding"]); @@ -101,7 +102,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseHeaders_ServerSendsCustomHeaders_Success() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var responseInfo = httpContext.GetFeature(); @@ -111,7 +113,7 @@ namespace Microsoft.AspNet.Server.WebListener })) { // HttpClient would merge the headers no matter what - WebRequest request = WebRequest.Create(Address); + WebRequest request = WebRequest.Create(address); HttpWebResponse response = (HttpWebResponse)await request.GetResponseAsync(); Assert.Equal(4, response.Headers.Count); Assert.Null(response.Headers["Transfer-Encoding"]); @@ -125,7 +127,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseHeaders_ServerSendsConnectionClose_Closed() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var responseInfo = httpContext.GetFeature(); @@ -134,7 +137,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); response.EnsureSuccessStatusCode(); Assert.True(response.Headers.ConnectionClose.Value); Assert.Equal(new string[] { "close" }, response.Headers.GetValues("Connection")); @@ -144,13 +147,14 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseHeaders_SendsHttp10_Gets11Close() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { env["owin.ResponseProtocol"] = "HTTP/1.0"; return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); response.EnsureSuccessStatusCode(); Assert.Equal(new Version(1, 1), response.Version); Assert.True(response.Headers.ConnectionClose.Value); @@ -161,13 +165,14 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseHeaders_SendsHttp10WithBody_Gets11Close() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { env["owin.ResponseProtocol"] = "HTTP/1.0"; return env.Get("owin.ResponseBody").WriteAsync(new byte[10], 0, 10); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); response.EnsureSuccessStatusCode(); Assert.Equal(new Version(1, 1), response.Version); Assert.False(response.Headers.TransferEncodingChunked.HasValue); @@ -181,14 +186,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseHeaders_HTTP10Request_Gets11Close() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { return Task.FromResult(0); })) { using (HttpClient client = new HttpClient()) { - HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, Address); + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, address); request.Version = new Version(1, 0); HttpResponseMessage response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); @@ -202,7 +208,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseHeaders_HTTP10Request_RemovesChunkedHeader() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var responseInfo = httpContext.GetFeature(); @@ -213,7 +220,7 @@ namespace Microsoft.AspNet.Server.WebListener { using (HttpClient client = new HttpClient()) { - HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, Address); + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, address); request.Version = new Version(1, 0); HttpResponseMessage response = await client.SendAsync(request); response.EnsureSuccessStatusCode(); @@ -229,8 +236,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task Headers_FlushSendsHeaders_Success() { - using (Utilities.CreateHttpServer( - env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var responseInfo = httpContext.GetFeature(); @@ -244,7 +251,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); response.EnsureSuccessStatusCode(); Assert.Equal(5, response.Headers.Count()); // Date, Server, Chunked @@ -259,8 +266,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task Headers_FlushAsyncSendsHeaders_Success() { - using (Utilities.CreateHttpServer( - async env => + string address; + using (Utilities.CreateHttpServer(out address, async env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var responseInfo = httpContext.GetFeature(); @@ -273,7 +280,7 @@ namespace Microsoft.AspNet.Server.WebListener responseHeaders.Add("Custom3", new string[] { "value3a, value3b", "value3c" }); // Ignored })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); response.EnsureSuccessStatusCode(); Assert.Equal(5, response.Headers.Count()); // Date, Server, Chunked diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseSendFileTests.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseSendFileTests.cs index eda1f7c2de..c02cd06f21 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseSendFileTests.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseSendFileTests.cs @@ -33,7 +33,6 @@ namespace Microsoft.AspNet.Server.WebListener { public class ResponseSendFileTests { - private const string Address = "http://localhost:8080/"; private readonly string AbsoluteFilePath; private readonly string RelativeFilePath; private readonly long FileLength; @@ -48,7 +47,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseSendFile_SupportKeys_Present() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); try @@ -76,7 +76,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); IEnumerable ignored; Assert.True(response.Content.Headers.TryGetValues("content-length", out ignored), "Content-Length"); @@ -91,7 +91,8 @@ namespace Microsoft.AspNet.Server.WebListener { ManualResetEvent waitHandle = new ManualResetEvent(false); bool? appThrew = null; - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var sendFile = httpContext.GetFeature(); @@ -112,7 +113,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); Assert.True(waitHandle.WaitOne(100)); Assert.True(appThrew.HasValue, "appThrew.HasValue"); @@ -123,14 +124,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseSendFile_NoHeaders_DefaultsToChunked() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var sendFile = httpContext.GetFeature(); return sendFile.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); IEnumerable ignored; Assert.False(response.Content.Headers.TryGetValues("content-length", out ignored), "Content-Length"); @@ -142,14 +144,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseSendFile_RelativeFile_Success() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var sendFile = httpContext.GetFeature(); return sendFile.SendFileAsync(RelativeFilePath, 0, null, CancellationToken.None); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); IEnumerable ignored; Assert.False(response.Content.Headers.TryGetValues("content-length", out ignored), "Content-Length"); @@ -161,7 +164,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseSendFile_Chunked_Chunked() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var sendFile = httpContext.GetFeature(); @@ -169,7 +173,7 @@ namespace Microsoft.AspNet.Server.WebListener return sendFile.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); IEnumerable contentLength; Assert.False(response.Content.Headers.TryGetValues("content-length", out contentLength), "Content-Length"); @@ -181,7 +185,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseSendFile_MultipleChunks_Chunked() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var sendFile = httpContext.GetFeature(); @@ -190,7 +195,7 @@ namespace Microsoft.AspNet.Server.WebListener return sendFile.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); IEnumerable contentLength; Assert.False(response.Content.Headers.TryGetValues("content-length", out contentLength), "Content-Length"); @@ -202,14 +207,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseSendFile_ChunkedHalfOfFile_Chunked() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var sendFile = httpContext.GetFeature(); return sendFile.SendFileAsync(AbsoluteFilePath, 0, FileLength / 2, CancellationToken.None); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); IEnumerable contentLength; Assert.False(response.Content.Headers.TryGetValues("content-length", out contentLength), "Content-Length"); @@ -221,14 +227,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseSendFile_ChunkedOffsetOutOfRange_Throws() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var sendFile = httpContext.GetFeature(); return sendFile.SendFileAsync(AbsoluteFilePath, 1234567, null, CancellationToken.None); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(500, (int)response.StatusCode); } } @@ -236,14 +243,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseSendFile_ChunkedCountOutOfRange_Throws() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var sendFile = httpContext.GetFeature(); return sendFile.SendFileAsync(AbsoluteFilePath, 0, 1234567, CancellationToken.None); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(500, (int)response.StatusCode); } } @@ -251,14 +259,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseSendFile_ChunkedCount0_Chunked() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var sendFile = httpContext.GetFeature(); return sendFile.SendFileAsync(AbsoluteFilePath, 0, 0, CancellationToken.None); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); IEnumerable contentLength; Assert.False(response.Content.Headers.TryGetValues("content-length", out contentLength), "Content-Length"); @@ -270,7 +279,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseSendFile_ContentLength_PassedThrough() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var sendFile = httpContext.GetFeature(); @@ -278,7 +288,7 @@ namespace Microsoft.AspNet.Server.WebListener return sendFile.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); IEnumerable contentLength; Assert.True(response.Content.Headers.TryGetValues("content-length", out contentLength), "Content-Length"); @@ -291,7 +301,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseSendFile_ContentLengthSpecific_PassedThrough() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var sendFile = httpContext.GetFeature(); @@ -299,7 +310,7 @@ namespace Microsoft.AspNet.Server.WebListener return sendFile.SendFileAsync(AbsoluteFilePath, 0, 10, CancellationToken.None); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); IEnumerable contentLength; Assert.True(response.Content.Headers.TryGetValues("content-length", out contentLength), "Content-Length"); @@ -312,7 +323,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task ResponseSendFile_ContentLength0_PassedThrough() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var sendFile = httpContext.GetFeature(); @@ -320,7 +332,7 @@ namespace Microsoft.AspNet.Server.WebListener return sendFile.SendFileAsync(AbsoluteFilePath, 0, 0, CancellationToken.None); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); IEnumerable contentLength; Assert.True(response.Content.Headers.TryGetValues("content-length", out contentLength), "Content-Length"); diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseTests.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseTests.cs index 7e411dba05..6d7d13af0c 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseTests.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ResponseTests.cs @@ -28,19 +28,18 @@ namespace Microsoft.AspNet.Server.WebListener { public class ResponseTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task Response_ServerSendsDefaultResponse_ServerProvidesStatusCodeAndReasonPhrase() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); Assert.Equal(200, httpContext.Response.StatusCode); return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); Assert.Equal("OK", response.ReasonPhrase); Assert.Equal(new Version(1, 1), response.Version); @@ -51,7 +50,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task Response_ServerSendsSpecificStatus_ServerProvidesReasonPhrase() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Response.StatusCode = 201; @@ -59,7 +59,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(201, (int)response.StatusCode); Assert.Equal("Created", response.ReasonPhrase); Assert.Equal(new Version(1, 1), response.Version); @@ -70,7 +70,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task Response_ServerSendsSpecificStatusAndReasonPhrase_PassedThrough() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Response.StatusCode = 201; @@ -79,7 +80,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(201, (int)response.StatusCode); Assert.Equal("CustomReasonPhrase", response.ReasonPhrase); Assert.Equal(new Version(1, 1), response.Version); @@ -90,14 +91,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task Response_ServerSendsCustomStatus_NoReasonPhrase() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Response.StatusCode = 901; return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(901, (int)response.StatusCode); Assert.Equal(string.Empty, response.ReasonPhrase); Assert.Equal(string.Empty, await response.Content.ReadAsStringAsync()); @@ -107,14 +109,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task Response_100_Throws() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Response.StatusCode = 100; return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(500, (int)response.StatusCode); } } @@ -122,14 +125,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task Response_0_Throws() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Response.StatusCode = 0; return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode); } } diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ServerTests.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ServerTests.cs index 23ff1f232a..16c9cfa70a 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ServerTests.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/ServerTests.cs @@ -34,17 +34,16 @@ namespace Microsoft.AspNet.Server.WebListener { public class ServerTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task Server_200OK_Success() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { return Task.FromResult(0); })) { - string response = await SendRequestAsync(Address); + string response = await SendRequestAsync(address); Assert.Equal(string.Empty, response); } } @@ -52,14 +51,15 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task Server_SendHelloWorld_Success() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); httpContext.Response.ContentLength = 11; return httpContext.Response.WriteAsync("Hello World"); })) { - string response = await SendRequestAsync(Address); + string response = await SendRequestAsync(address); Assert.Equal("Hello World", response); } } @@ -67,7 +67,8 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task Server_EchoHelloWorld_Success() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); string input = new StreamReader(httpContext.Request.Body).ReadToEnd(); @@ -76,7 +77,7 @@ namespace Microsoft.AspNet.Server.WebListener return httpContext.Response.WriteAsync("Hello World"); })) { - string response = await SendRequestAsync(Address, "Hello World"); + string response = await SendRequestAsync(address, "Hello World"); Assert.Equal("Hello World", response); } } @@ -86,7 +87,8 @@ namespace Microsoft.AspNet.Server.WebListener { Task responseTask; ManualResetEvent received = new ManualResetEvent(false); - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { received.Set(); var httpContext = new DefaultHttpContext((IFeatureCollection)env); @@ -94,7 +96,7 @@ namespace Microsoft.AspNet.Server.WebListener return httpContext.Response.WriteAsync("Hello World"); })) { - responseTask = SendRequestAsync(Address); + responseTask = SendRequestAsync(address); Assert.True(received.WaitOne(10000)); } string response = await responseTask; @@ -104,16 +106,17 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public void Server_AppException_ClientReset() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { throw new InvalidOperationException(); })) { - Task requestTask = SendRequestAsync(Address); + Task requestTask = SendRequestAsync(address); Assert.Throws(() => requestTask.Result); // Do it again to make sure the server didn't crash - requestTask = SendRequestAsync(Address); + requestTask = SendRequestAsync(address); Assert.Throws(() => requestTask.Result); } } @@ -125,7 +128,8 @@ namespace Microsoft.AspNet.Server.WebListener int requestCount = 0; TaskCompletionSource tcs = new TaskCompletionSource(); - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { if (Interlocked.Increment(ref requestCount) == requestLimit) { @@ -142,7 +146,7 @@ namespace Microsoft.AspNet.Server.WebListener List requestTasks = new List(); for (int i = 0; i < requestLimit; i++) { - Task requestTask = SendRequestAsync(Address); + Task requestTask = SendRequestAsync(address); requestTasks.Add(requestTask); } @@ -162,7 +166,8 @@ namespace Microsoft.AspNet.Server.WebListener int requestCount = 0; TaskCompletionSource tcs = new TaskCompletionSource(); - using (Utilities.CreateHttpServer(async env => + string address; + using (Utilities.CreateHttpServer(out address, async env => { if (Interlocked.Increment(ref requestCount) == requestLimit) { @@ -177,7 +182,7 @@ namespace Microsoft.AspNet.Server.WebListener List requestTasks = new List(); for (int i = 0; i < requestLimit; i++) { - Task requestTask = SendRequestAsync(Address); + Task requestTask = SendRequestAsync(address); requestTasks.Add(requestTask); } Assert.True(Task.WaitAll(requestTasks.ToArray(), TimeSpan.FromSeconds(2)), "Timed out"); @@ -192,7 +197,8 @@ namespace Microsoft.AspNet.Server.WebListener ManualResetEvent aborted = new ManualResetEvent(false); ManualResetEvent canceled = new ManualResetEvent(false); - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); CancellationToken ct = httpContext.RequestAborted; @@ -208,7 +214,7 @@ namespace Microsoft.AspNet.Server.WebListener { // Note: System.Net.Sockets does not RST the connection by default, it just FINs. // Http.Sys's disconnect notice requires a RST. - using (Socket socket = await SendHungRequestAsync("GET", Address)) + using (Socket socket = await SendHungRequestAsync("GET", address)) { Assert.True(received.WaitOne(interval), "Receive Timeout"); socket.Close(0); // Force a RST @@ -226,7 +232,8 @@ namespace Microsoft.AspNet.Server.WebListener ManualResetEvent aborted = new ManualResetEvent(false); ManualResetEvent canceled = new ManualResetEvent(false); - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); CancellationToken ct = httpContext.RequestAborted; @@ -240,7 +247,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - using (Socket socket = await SendHungRequestAsync("GET", Address)) + using (Socket socket = await SendHungRequestAsync("GET", address)) { Assert.True(received.WaitOne(interval), "Receive Timeout"); Assert.Throws(() => socket.Receive(new byte[10])); @@ -251,15 +258,19 @@ namespace Microsoft.AspNet.Server.WebListener [Fact] public async Task Server_SetQueueLimit_Success() { - var factory = new ServerFactory(loggerFactory: null); + // TODO: This is just to get a dynamic port + string address; + using (Utilities.CreateHttpServer(out address, env => Task.FromResult(0))) { } + + var factory = new ServerFactory(loggerFactory: null); var serverInfo = (ServerInformation)factory.Initialize(configuration: null); - serverInfo.Listener.UrlPrefixes.Add(UrlPrefix.Create("http://localhost:8080")); + serverInfo.Listener.UrlPrefixes.Add(UrlPrefix.Create(address)); serverInfo.Listener.SetRequestQueueLimit(1001); using (factory.Start(serverInfo, env => Task.FromResult(0))) { - string response = await SendRequestAsync(Address); + string response = await SendRequestAsync(address); Assert.Equal(string.Empty, response); } } diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/Utilities.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/Utilities.cs index 8281848d57..3181a39875 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/Utilities.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/Utilities.cs @@ -25,32 +25,68 @@ namespace Microsoft.AspNet.Server.WebListener internal static class Utilities { - internal static IDisposable CreateHttpServer(AppFunc app) + private const int BasePort = 5001; + private const int MaxPort = 8000; + private static int NextPort = BasePort; + private static object PortLock = new object(); + + internal static IDisposable CreateHttpServer(out string baseAddress, AppFunc app) { - return CreateServer("http", "localhost", "8080", string.Empty, app); + string root; + return CreateDynamicHttpServer(string.Empty, AuthenticationTypes.AllowAnonymous, out root, out baseAddress, app); + } + + internal static IDisposable CreateHttpServerReturnRoot(string path, out string root, AppFunc app) + { + string baseAddress; + return CreateDynamicHttpServer(path, AuthenticationTypes.AllowAnonymous, out root, out baseAddress, app); + } + + internal static IDisposable CreateHttpAuthServer(AuthenticationTypes authType, out string baseAddress, AppFunc app) + { + string root; + return CreateDynamicHttpServer(string.Empty, authType, out root, out baseAddress, app); + } + + internal static IDisposable CreateDynamicHttpServer(string basePath, AuthenticationTypes authType, out string root, out string baseAddress, AppFunc app) + { + var factory = new ServerFactory(loggerFactory: null); + lock (PortLock) + { + while (NextPort < MaxPort) + { + + var port = NextPort++; + var prefix = UrlPrefix.Create("http", "localhost", port, basePath); + root = prefix.Scheme + "://" + prefix.Host + ":" + prefix.Port; + baseAddress = prefix.ToString(); + + var serverInfo = (ServerInformation)factory.Initialize(configuration: null); + serverInfo.Listener.UrlPrefixes.Add(prefix); + serverInfo.Listener.AuthenticationManager.AuthenticationTypes = authType; + try + { + return factory.Start(serverInfo, app); + } + catch (WebListenerException) + { + } + } + NextPort = BasePort; + } + throw new Exception("Failed to locate a free port."); } internal static IDisposable CreateHttpsServer(AppFunc app) { - return CreateServer("https", "localhost", "9090", string.Empty, app); + return CreateServer("https", "localhost", 9090, string.Empty, app); } - internal static IDisposable CreateAuthServer(AuthenticationTypes authType, AppFunc app) - { - return CreateServer("http", "localhost", "8080", string.Empty, authType, app); - } - - internal static IDisposable CreateServer(string scheme, string host, string port, string path, AppFunc app) - { - return CreateServer(scheme, host, port, path, AuthenticationTypes.AllowAnonymous, app); - } - - internal static IDisposable CreateServer(string scheme, string host, string port, string path, AuthenticationTypes authType, AppFunc app) + internal static IDisposable CreateServer(string scheme, string host, int port, string path, AppFunc app) { var factory = new ServerFactory(loggerFactory: null); var serverInfo = (ServerInformation)factory.Initialize(configuration: null); serverInfo.Listener.UrlPrefixes.Add(UrlPrefix.Create(scheme, host, port, path)); - serverInfo.Listener.AuthenticationManager.AuthenticationTypes = authType; return factory.Start(serverInfo, app); } diff --git a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/WebSocketTests.cs b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/WebSocketTests.cs index 3b830843d6..c35719bd76 100644 --- a/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/WebSocketTests.cs +++ b/test/Microsoft.AspNet.Server.WebListener.FunctionalTests/WebSocketTests.cs @@ -30,13 +30,11 @@ namespace Microsoft.AspNet.Server.WebListener { public class WebSocketTests { - private const string Address = "http://localhost:8080/"; - private const string WsAddress = "ws://localhost:8080/"; - [Fact] public async Task WebSocketTests_SupportKeys_Present() { - using (Utilities.CreateHttpServer(env => + string address; + using (Utilities.CreateHttpServer(out address, env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); try @@ -51,7 +49,7 @@ namespace Microsoft.AspNet.Server.WebListener return Task.FromResult(0); })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); Assert.False(response.Headers.TransferEncodingChunked.HasValue, "Chunked"); Assert.Equal(0, response.Content.Headers.ContentLength); @@ -63,7 +61,8 @@ namespace Microsoft.AspNet.Server.WebListener public async Task WebSocketTests_AfterHeadersSent_Throws() { bool? upgradeThrew = null; - using (Utilities.CreateHttpServer(async env => + string address; + using (Utilities.CreateHttpServer(out address, async env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); await httpContext.Response.WriteAsync("Hello World"); @@ -80,7 +79,7 @@ namespace Microsoft.AspNet.Server.WebListener } })) { - HttpResponseMessage response = await SendRequestAsync(Address); + HttpResponseMessage response = await SendRequestAsync(address); Assert.Equal(200, (int)response.StatusCode); Assert.True(response.Headers.TransferEncodingChunked.Value, "Chunked"); Assert.True(upgradeThrew.Value); @@ -92,7 +91,8 @@ namespace Microsoft.AspNet.Server.WebListener { ManualResetEvent waitHandle = new ManualResetEvent(false); bool? upgraded = null; - using (Utilities.CreateHttpServer(async env => + string address; + using (Utilities.CreateHttpServer(out address, async env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var webSocketFeature = httpContext.GetFeature(); @@ -103,7 +103,7 @@ namespace Microsoft.AspNet.Server.WebListener waitHandle.Set(); })) { - using (WebSocket clientWebSocket = await SendWebSocketRequestAsync(WsAddress)) + using (WebSocket clientWebSocket = await SendWebSocketRequestAsync(ConvertToWebSocketAddress(address))) { Assert.True(waitHandle.WaitOne(TimeSpan.FromSeconds(1)), "Timed out"); Assert.True(upgraded.HasValue, "Upgraded not set"); @@ -116,7 +116,8 @@ namespace Microsoft.AspNet.Server.WebListener public async Task WebSocketAccept_SendAndReceive_Success() { byte[] clientBuffer = new byte[] { 0x00, 0x01, 0xFF, 0x00, 0x00 }; - using (Utilities.CreateHttpServer(async env => + string address; + using (Utilities.CreateHttpServer(out address, async env => { var httpContext = new DefaultHttpContext((IFeatureCollection)env); var webSocketFeature = httpContext.GetFeature(); @@ -132,7 +133,7 @@ namespace Microsoft.AspNet.Server.WebListener })) { - using (WebSocket clientWebSocket = await SendWebSocketRequestAsync(WsAddress)) + using (WebSocket clientWebSocket = await SendWebSocketRequestAsync(ConvertToWebSocketAddress(address))) { await clientWebSocket.SendAsync(new ArraySegment(clientBuffer, 0, 3), WebSocketMessageType.Binary, true, CancellationToken.None); @@ -143,6 +144,13 @@ namespace Microsoft.AspNet.Server.WebListener } } + private string ConvertToWebSocketAddress(string address) + { + var builder = new UriBuilder(address); + builder.Scheme = "ws"; + return builder.ToString(); + } + private async Task SendRequestAsync(string uri) { using (HttpClient client = new HttpClient()) diff --git a/test/Microsoft.Net.Server.FunctionalTests/AuthenticationTests.cs b/test/Microsoft.Net.Server.FunctionalTests/AuthenticationTests.cs index 503b515b7e..6c7474f234 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/AuthenticationTests.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/AuthenticationTests.cs @@ -10,8 +10,6 @@ namespace Microsoft.Net.Server { public class AuthenticationTests { - private const string Address = "http://localhost:8080/"; - [Theory] [InlineData(AuthenticationTypes.AllowAnonymous)] [InlineData(AuthenticationTypes.Kerberos)] @@ -22,9 +20,10 @@ namespace Microsoft.Net.Server [InlineData(AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /*AuthenticationTypes.Digest |*/ AuthenticationTypes.Basic)] public async Task AuthTypes_AllowAnonymous_NoChallenge(AuthenticationTypes authType) { - using (var server = Utilities.CreateAuthServer(authType | AuthenticationTypes.AllowAnonymous)) + string address; + using (var server = Utilities.CreateHttpAuthServer(authType | AuthenticationTypes.AllowAnonymous, out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); Assert.NotNull(context.User); @@ -53,9 +52,10 @@ namespace Microsoft.Net.Server [InlineData(AuthenticationTypes.Basic)] public async Task AuthType_RequireAuth_ChallengesAdded(AuthenticationTypes authType) { - using (var server = Utilities.CreateAuthServer(authType)) + string address; + using (var server = Utilities.CreateHttpAuthServer(authType, out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var contextTask = server.GetContextAsync(); // Fails when the server shuts down, the challenge happens internally. @@ -73,9 +73,10 @@ namespace Microsoft.Net.Server [InlineData(AuthenticationTypes.Basic)] public async Task AuthType_AllowAnonymousButSpecify401_ChallengesAdded(AuthenticationTypes authType) { - using (var server = Utilities.CreateAuthServer(authType | AuthenticationTypes.AllowAnonymous)) + string address; + using (var server = Utilities.CreateHttpAuthServer(authType | AuthenticationTypes.AllowAnonymous, out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); Assert.NotNull(context.User); @@ -93,15 +94,16 @@ namespace Microsoft.Net.Server [Fact] public async Task MultipleAuthTypes_AllowAnonymousButSpecify401_ChallengesAdded() { + string address; AuthenticationTypes authType = AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM /* | AuthenticationTypes.Digest TODO: Not implemented */ | AuthenticationTypes.Basic; - using (var server = Utilities.CreateAuthServer(authType | AuthenticationTypes.AllowAnonymous)) + using (var server = Utilities.CreateHttpAuthServer(authType | AuthenticationTypes.AllowAnonymous, out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); Assert.NotNull(context.User); @@ -125,9 +127,10 @@ namespace Microsoft.Net.Server [InlineData(AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /*AuthenticationType.Digest |*/ AuthenticationTypes.Basic)] public async Task AuthTypes_AllowAnonymousButSpecify401_Success(AuthenticationTypes authType) { - using (var server = Utilities.CreateAuthServer(authType | AuthenticationTypes.AllowAnonymous)) + string address; + using (var server = Utilities.CreateHttpAuthServer(authType | AuthenticationTypes.AllowAnonymous, out address)) { - Task responseTask = SendRequestAsync(Address, useDefaultCredentials: true); + Task responseTask = SendRequestAsync(address, useDefaultCredentials: true); var context = await server.GetContextAsync(); Assert.NotNull(context.User); @@ -156,9 +159,10 @@ namespace Microsoft.Net.Server [InlineData(AuthenticationTypes.Kerberos | AuthenticationTypes.Negotiate | AuthenticationTypes.NTLM | /*AuthenticationType.Digest |*/ AuthenticationTypes.Basic)] public async Task AuthTypes_RequireAuth_Success(AuthenticationTypes authType) { - using (var server = Utilities.CreateAuthServer(authType)) + string address; + using (var server = Utilities.CreateHttpAuthServer(authType, out address)) { - Task responseTask = SendRequestAsync(Address, useDefaultCredentials: true); + Task responseTask = SendRequestAsync(address, useDefaultCredentials: true); var context = await server.GetContextAsync(); Assert.NotNull(context.User); diff --git a/test/Microsoft.Net.Server.FunctionalTests/HttpsTests.cs b/test/Microsoft.Net.Server.FunctionalTests/HttpsTests.cs index e4c13293eb..cf7aa0296a 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/HttpsTests.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/HttpsTests.cs @@ -11,6 +11,7 @@ namespace Microsoft.Net.Server { public class HttpsTests { + // Note these tests can't use dynamic ports or run concurrently because the ssl cert must be pre-registered with a specific port. private const string Address = "https://localhost:9090/"; [Fact(Skip = "TODO: Add trait filtering support so these SSL tests don't get run on teamcity or the command line."), Trait("scheme", "https")] diff --git a/test/Microsoft.Net.Server.FunctionalTests/Microsoft.Net.Server.FunctionalTests.kproj b/test/Microsoft.Net.Server.FunctionalTests/Microsoft.Net.Server.FunctionalTests.kproj index 228bd0ad9a..a579d02c1f 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/Microsoft.Net.Server.FunctionalTests.kproj +++ b/test/Microsoft.Net.Server.FunctionalTests/Microsoft.Net.Server.FunctionalTests.kproj @@ -22,7 +22,6 @@ - diff --git a/test/Microsoft.Net.Server.FunctionalTests/OpaqueUpgradeTests.cs b/test/Microsoft.Net.Server.FunctionalTests/OpaqueUpgradeTests.cs index cbf99ec975..48bcc03ba2 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/OpaqueUpgradeTests.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/OpaqueUpgradeTests.cs @@ -12,21 +12,20 @@ namespace Microsoft.Net.Server { public class OpaqueUpgradeTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task OpaqueUpgrade_AfterHeadersSent_Throws() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task clientTask = SendRequestAsync(Address); + Task clientTask = SendRequestAsync(address); var context = await server.GetContextAsync(); byte[] body = Encoding.UTF8.GetBytes("Hello World"); context.Response.Body.Write(body, 0, body.Length); context.Response.Headers["Upgrade"] = "WebSocket"; // Win8.1 blocks anything but WebSocket - Assert.ThrowsAsync(async () => await context.UpgradeAsync()); + await Assert.ThrowsAsync(async () => await context.UpgradeAsync()); context.Dispose(); HttpResponseMessage response = await clientTask; Assert.Equal(200, (int)response.StatusCode); @@ -38,9 +37,10 @@ namespace Microsoft.Net.Server [Fact] public async Task OpaqueUpgrade_GetUpgrade_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task clientTask = SendOpaqueRequestAsync("GET", Address); + Task clientTask = SendOpaqueRequestAsync("GET", address); var context = await server.GetContextAsync(); Assert.True(context.IsUpgradableRequest); @@ -80,9 +80,10 @@ namespace Microsoft.Net.Server [InlineData("PUT", "Content-Length: 0")] public async Task OpaqueUpgrade_VariousMethodsUpgradeSendAndReceive_Success(string method, string extraHeader) { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task clientTask = SendOpaqueRequestAsync(method, Address, extraHeader); + Task clientTask = SendOpaqueRequestAsync(method, address, extraHeader); var context = await server.GetContextAsync(); Assert.True(context.IsUpgradableRequest); @@ -119,9 +120,10 @@ namespace Microsoft.Net.Server [InlineData("CUSTOMVERB", "Transfer-Encoding: chunked")] public async Task OpaqueUpgrade_InvalidMethodUpgrade_Disconnected(string method, string extraHeader) { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - var clientTask = SendOpaqueRequestAsync(method, Address, extraHeader); + var clientTask = SendOpaqueRequestAsync(method, address, extraHeader); var context = await server.GetContextAsync(); Assert.False(context.IsUpgradableRequest); context.Dispose(); diff --git a/test/Microsoft.Net.Server.FunctionalTests/Properties/AssemblyInfo.cs b/test/Microsoft.Net.Server.FunctionalTests/Properties/AssemblyInfo.cs deleted file mode 100644 index 1bc3b800fb..0000000000 --- a/test/Microsoft.Net.Server.FunctionalTests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,8 +0,0 @@ -// ----------------------------------------------------------------------- -// -// Copyright (c) Microsoft Corporation. All rights reserved. -// -// ----------------------------------------------------------------------- - -// These tests can't run in parallel because they all use the same port. -[assembly: Xunit.CollectionBehaviorAttribute(Xunit.CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true)] diff --git a/test/Microsoft.Net.Server.FunctionalTests/RequestBodyTests.cs b/test/Microsoft.Net.Server.FunctionalTests/RequestBodyTests.cs index 89f6d14d32..89e24a90c1 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/RequestBodyTests.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/RequestBodyTests.cs @@ -14,14 +14,13 @@ namespace Microsoft.Net.Server { public class RequestBodyTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task RequestBody_ReadSync_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address, "Hello World"); + Task responseTask = SendRequestAsync(address, "Hello World"); var context = await server.GetContextAsync(); byte[] input = new byte[100]; @@ -37,9 +36,10 @@ namespace Microsoft.Net.Server [Fact] public async Task RequestBody_ReadAync_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address, "Hello World"); + Task responseTask = SendRequestAsync(address, "Hello World"); var context = await server.GetContextAsync(); byte[] input = new byte[100]; @@ -55,9 +55,10 @@ namespace Microsoft.Net.Server [Fact] public async Task RequestBody_ReadBeginEnd_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address, "Hello World"); + Task responseTask = SendRequestAsync(address, "Hello World"); var context = await server.GetContextAsync(); byte[] input = new byte[100]; @@ -74,9 +75,10 @@ namespace Microsoft.Net.Server [Fact] public async Task RequestBody_InvalidBuffer_ArgumentException() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address, "Hello World"); + Task responseTask = SendRequestAsync(address, "Hello World"); var context = await server.GetContextAsync(); byte[] input = new byte[100]; @@ -98,9 +100,10 @@ namespace Microsoft.Net.Server public async Task RequestBody_ReadSyncPartialBody_Success() { StaggardContent content = new StaggardContent(); - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address, content); + Task responseTask = SendRequestAsync(address, content); var context = await server.GetContextAsync(); byte[] input = new byte[10]; @@ -120,9 +123,10 @@ namespace Microsoft.Net.Server public async Task RequestBody_ReadAsyncPartialBody_Success() { StaggardContent content = new StaggardContent(); - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address, content); + Task responseTask = SendRequestAsync(address, content); var context = await server.GetContextAsync(); byte[] input = new byte[10]; @@ -141,9 +145,10 @@ namespace Microsoft.Net.Server [Fact] public async Task RequestBody_PostWithImidateBody_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendSocketRequestAsync(Address); + Task responseTask = SendSocketRequestAsync(address); var context = await server.GetContextAsync(); byte[] input = new byte[11]; diff --git a/test/Microsoft.Net.Server.FunctionalTests/RequestHeaderTests.cs b/test/Microsoft.Net.Server.FunctionalTests/RequestHeaderTests.cs index fbc6cf55d5..3fb03df524 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/RequestHeaderTests.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/RequestHeaderTests.cs @@ -1,5 +1,6 @@ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. +using System; using System.Linq; using System.Net.Http; using System.Net.Sockets; @@ -11,21 +12,20 @@ namespace Microsoft.Net.Server { public class RequestHeaderTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task RequestHeaders_ClientSendsDefaultHeaders_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); var requestHeaders = context.Request.Headers; // NOTE: The System.Net client only sends the Connection: keep-alive header on the first connection per service-point. // Assert.Equal(2, requestHeaders.Count); // Assert.Equal("Keep-Alive", requestHeaders.Get("Connection")); - Assert.Equal("localhost:8080", requestHeaders["Host"]); + Assert.Equal(new Uri(address).Authority, requestHeaders["Host"]); string[] values; Assert.False(requestHeaders.TryGetValue("Accept", out values)); Assert.False(requestHeaders.ContainsKey("Accept")); @@ -40,16 +40,17 @@ namespace Microsoft.Net.Server [Fact] public async Task RequestHeaders_ClientSendsCustomHeaders_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { string[] customValues = new string[] { "custom1, and custom2", "custom3" }; - Task responseTask = SendRequestAsync("localhost", 8080, "Custom-Header", customValues); + Task responseTask = SendRequestAsync(address, "Custom-Header", customValues); var context = await server.GetContextAsync(); var requestHeaders = context.Request.Headers; Assert.Equal(4, requestHeaders.Count); - Assert.Equal("localhost:8080", requestHeaders["Host"]); - Assert.Equal(new[] { "localhost:8080" }, requestHeaders.GetValues("Host")); + Assert.Equal(new Uri(address).Authority, requestHeaders["Host"]); + Assert.Equal(new[] { new Uri(address).Authority }, requestHeaders.GetValues("Host")); Assert.Equal("close", requestHeaders["Connection"]); Assert.Equal(new[] { "close" }, requestHeaders.GetValues("Connection")); // Apparently Http.Sys squashes request headers together. @@ -71,15 +72,14 @@ namespace Microsoft.Net.Server } } - private async Task SendRequestAsync(string host, int port, string customHeader, string[] customValues) + private async Task SendRequestAsync(string address, string customHeader, string[] customValues) { + var uri = new Uri(address); StringBuilder builder = new StringBuilder(); builder.AppendLine("GET / HTTP/1.1"); builder.AppendLine("Connection: close"); builder.Append("HOST: "); - builder.Append(host); - builder.Append(':'); - builder.AppendLine(port.ToString()); + builder.AppendLine(uri.Authority); foreach (string value in customValues) { builder.Append(customHeader); @@ -92,7 +92,7 @@ namespace Microsoft.Net.Server byte[] request = Encoding.ASCII.GetBytes(builder.ToString()); Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp); - socket.Connect(host, port); + socket.Connect(uri.Host, uri.Port); socket.Send(request); diff --git a/test/Microsoft.Net.Server.FunctionalTests/RequestTests.cs b/test/Microsoft.Net.Server.FunctionalTests/RequestTests.cs index 54ef27e237..cf8205c18e 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/RequestTests.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/RequestTests.cs @@ -11,14 +11,13 @@ namespace Microsoft.Net.Server { public class RequestTests { - private const string Address = "http://localhost:8080"; - [Fact] public async Task Request_SimpleGet_Success() { - using (var server = Utilities.CreateServer("http", "localhost", "8080", "/basepath")) + string root; + using (var server = Utilities.CreateHttpServerReturnRoot("/basepath", out root)) { - Task responseTask = SendRequestAsync(Address + "/basepath/SomePath?SomeQuery"); + Task responseTask = SendRequestAsync(root + "/basepath/SomePath?SomeQuery"); var context = await server.GetContextAsync(); @@ -51,17 +50,18 @@ namespace Microsoft.Net.Server } [Theory] - [InlineData("/", "http://localhost:8080/", "", "/")] - [InlineData("/basepath/", "http://localhost:8080/basepath", "/basepath", "")] - [InlineData("/basepath/", "http://localhost:8080/basepath/", "/basepath", "/")] - [InlineData("/basepath/", "http://localhost:8080/basepath/subpath", "/basepath", "/subpath")] - [InlineData("/base path/", "http://localhost:8080/base%20path/sub path", "/base path", "/sub path")] - [InlineData("/base葉path/", "http://localhost:8080/base%E8%91%89path/sub%E8%91%89path", "/base葉path", "/sub葉path")] - public async Task Request_PathSplitting(string pathBase, string requestUri, string expectedPathBase, string expectedPath) + [InlineData("/", "/", "", "/")] + [InlineData("/basepath/", "/basepath", "/basepath", "")] + [InlineData("/basepath/", "/basepath/", "/basepath", "/")] + [InlineData("/basepath/", "/basepath/subpath", "/basepath", "/subpath")] + [InlineData("/base path/", "/base%20path/sub path", "/base path", "/sub path")] + [InlineData("/base葉path/", "/base%E8%91%89path/sub%E8%91%89path", "/base葉path", "/sub葉path")] + public async Task Request_PathSplitting(string pathBase, string requestPath, string expectedPathBase, string expectedPath) { - using (var server = Utilities.CreateServer("http", "localhost", "8080", pathBase)) + string root; + using (var server = Utilities.CreateHttpServerReturnRoot(pathBase, out root)) { - Task responseTask = SendRequestAsync(requestUri); + Task responseTask = SendRequestAsync(root + requestPath); var context = await server.GetContextAsync(); @@ -73,7 +73,6 @@ namespace Microsoft.Net.Server Assert.Equal(expectedPath, request.Path); Assert.Equal(expectedPathBase, request.PathBase); Assert.Equal(string.Empty, request.QueryString); - Assert.Equal(8080, request.LocalPort); context.Dispose(); string response = await responseTask; @@ -96,15 +95,21 @@ namespace Microsoft.Net.Server [InlineData("/2/3/random", "/2/3", "/random")] public async Task Request_MultiplePrefixes(string requestUri, string expectedPathBase, string expectedPath) { - using (var server = new WebListener()) + // TODO: We're just doing this to get a dynamic port. This can be removed later when we add support for hot-adding prefixes. + string root; + var server = Utilities.CreateHttpServerReturnRoot("/", out root); + server.Dispose(); + server = new WebListener(); + using (server) { + var uriBuilder = new UriBuilder(root); foreach (string path in new[] { "/", "/11", "/2/3", "/2", "/11/2" }) { - server.UrlPrefixes.Add(UrlPrefix.Create("http", "localhost", "8080", path)); + server.UrlPrefixes.Add(UrlPrefix.Create(uriBuilder.Scheme, uriBuilder.Host, uriBuilder.Port, path)); } server.Start(); - Task responseTask = SendRequestAsync(Address + requestUri); + Task responseTask = SendRequestAsync(root + requestUri); var context = await server.GetContextAsync(); var request = context.Request; diff --git a/test/Microsoft.Net.Server.FunctionalTests/ResponseBodyTests.cs b/test/Microsoft.Net.Server.FunctionalTests/ResponseBodyTests.cs index 30b32dcc07..299f719f5c 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/ResponseBodyTests.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/ResponseBodyTests.cs @@ -13,14 +13,13 @@ namespace Microsoft.Net.Server { public class ResponseBodyTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task ResponseBody_WriteNoHeaders_DefaultsToChunked() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.Body.Write(new byte[10], 0, 10); @@ -40,9 +39,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseBody_WriteChunked_Chunked() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Request.Headers["transfeR-Encoding"] = " CHunked "; @@ -65,9 +65,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseBody_WriteContentLength_PassedThrough() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.Headers["Content-lenGth"] = " 30 "; @@ -127,9 +128,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseBody_WriteContentLengthNotEnoughWritten_Throws() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.Headers["Content-lenGth"] = " 20 "; @@ -143,9 +145,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseBody_WriteContentLengthTooMuchWritten_Throws() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.Headers["Content-lenGth"] = " 10 "; @@ -160,9 +163,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseBody_WriteContentLengthExtraWritten_Throws() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.Headers["Content-lenGth"] = " 10 "; diff --git a/test/Microsoft.Net.Server.FunctionalTests/ResponseHeaderTests.cs b/test/Microsoft.Net.Server.FunctionalTests/ResponseHeaderTests.cs index d0290f0693..ab12512b17 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/ResponseHeaderTests.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/ResponseHeaderTests.cs @@ -11,14 +11,13 @@ namespace Microsoft.Net.Server { public class ResponseHeaderTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task ResponseHeaders_ServerSendsDefaultHeaders_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Dispose(); @@ -37,9 +36,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseHeaders_ServerSendsSingleValueKnownHeaders_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - WebRequest request = WebRequest.Create(Address); + WebRequest request = WebRequest.Create(address); Task responseTask = request.GetResponseAsync(); var context = await server.GetContextAsync(); @@ -61,9 +61,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseHeaders_ServerSendsMultiValueKnownHeaders_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - WebRequest request = WebRequest.Create(Address); + WebRequest request = WebRequest.Create(address); Task responseTask = request.GetResponseAsync(); var context = await server.GetContextAsync(); @@ -85,9 +86,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseHeaders_ServerSendsCustomHeaders_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - WebRequest request = WebRequest.Create(Address); + WebRequest request = WebRequest.Create(address); Task responseTask = request.GetResponseAsync(); var context = await server.GetContextAsync(); @@ -109,9 +111,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseHeaders_ServerSendsConnectionClose_Closed() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); var responseHeaders = context.Response.Headers; @@ -165,11 +168,12 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseHeaders_HTTP10Request_Gets11Close() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { using (HttpClient client = new HttpClient()) { - HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, Address); + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, address); request.Version = new Version(1, 0); Task responseTask = client.SendAsync(request); @@ -188,11 +192,12 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseHeaders_HTTP10Request_RemovesChunkedHeader() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { using (HttpClient client = new HttpClient()) { - HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, Address); + HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, address); request.Version = new Version(1, 0); Task responseTask = client.SendAsync(request); @@ -216,9 +221,10 @@ namespace Microsoft.Net.Server [Fact] public async Task Headers_FlushSendsHeaders_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); var responseHeaders = context.Response.Headers; @@ -247,9 +253,10 @@ namespace Microsoft.Net.Server [Fact] public async Task Headers_FlushAsyncSendsHeaders_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); var responseHeaders = context.Response.Headers; diff --git a/test/Microsoft.Net.Server.FunctionalTests/ResponseSendFileTests.cs b/test/Microsoft.Net.Server.FunctionalTests/ResponseSendFileTests.cs index 3714c56b98..5139d9ad40 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/ResponseSendFileTests.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/ResponseSendFileTests.cs @@ -13,7 +13,6 @@ namespace Microsoft.Net.Server { public class ResponseSendFileTests { - private const string Address = "http://localhost:8080/"; private readonly string AbsoluteFilePath; private readonly string RelativeFilePath; private readonly long FileLength; @@ -28,9 +27,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseSendFile_MissingFile_Throws() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); await Assert.ThrowsAsync(() => @@ -44,9 +44,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseSendFile_NoHeaders_DefaultsToChunked() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); await context.Response.SendFileAsync(AbsoluteFilePath, 0, null, CancellationToken.None); @@ -64,9 +65,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseSendFile_RelativeFile_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); await context.Response.SendFileAsync(RelativeFilePath, 0, null, CancellationToken.None); @@ -84,9 +86,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseSendFile_Chunked_Chunked() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.Headers["Transfer-EncodinG"] = "CHUNKED"; @@ -105,9 +108,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseSendFile_MultipleChunks_Chunked() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.Headers["Transfer-EncodinG"] = "CHUNKED"; @@ -127,9 +131,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseSendFile_ChunkedHalfOfFile_Chunked() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); await context.Response.SendFileAsync(AbsoluteFilePath, 0, FileLength / 2, CancellationToken.None); @@ -147,9 +152,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseSendFile_ChunkedOffsetOutOfRange_Throws() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); await Assert.ThrowsAsync( @@ -163,9 +169,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseSendFile_ChunkedCountOutOfRange_Throws() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); await Assert.ThrowsAsync( @@ -179,9 +186,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseSendFile_ChunkedCount0_Chunked() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); await context.Response.SendFileAsync(AbsoluteFilePath, 0, 0, CancellationToken.None); @@ -199,9 +207,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseSendFile_ContentLength_PassedThrough() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.Headers["Content-lenGth"] = FileLength.ToString(); @@ -220,9 +229,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseSendFile_ContentLengthSpecific_PassedThrough() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.Headers["Content-lenGth"] = "10"; @@ -242,9 +252,10 @@ namespace Microsoft.Net.Server [Fact] public async Task ResponseSendFile_ContentLength0_PassedThrough() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.Headers["Content-lenGth"] = "0"; diff --git a/test/Microsoft.Net.Server.FunctionalTests/ResponseTests.cs b/test/Microsoft.Net.Server.FunctionalTests/ResponseTests.cs index 6aaceeff89..f5d5c2146c 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/ResponseTests.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/ResponseTests.cs @@ -10,14 +10,13 @@ namespace Microsoft.Net.Server { public class ResponseTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task Response_ServerSendsDefaultResponse_ServerProvidesStatusCodeAndReasonPhrase() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); Assert.Equal(200, context.Response.StatusCode); @@ -34,9 +33,10 @@ namespace Microsoft.Net.Server [Fact] public async Task Response_ServerSendsSpecificStatus_ServerProvidesReasonPhrase() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.StatusCode = 201; @@ -54,9 +54,10 @@ namespace Microsoft.Net.Server [Fact] public async Task Response_ServerSendsSpecificStatusAndReasonPhrase_PassedThrough() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.StatusCode = 201; @@ -75,9 +76,10 @@ namespace Microsoft.Net.Server [Fact] public async Task Response_ServerSendsCustomStatus_NoReasonPhrase() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.StatusCode = 901; @@ -93,9 +95,10 @@ namespace Microsoft.Net.Server [Fact] public async Task Response_100_Throws() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); Assert.Throws(() => { context.Response.StatusCode = 100; }); @@ -108,9 +111,10 @@ namespace Microsoft.Net.Server [Fact] public async Task Response_0_Throws() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); Assert.Throws(() => { context.Response.StatusCode = 0; }); diff --git a/test/Microsoft.Net.Server.FunctionalTests/ServerTests.cs b/test/Microsoft.Net.Server.FunctionalTests/ServerTests.cs index 5778917050..af97555358 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/ServerTests.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/ServerTests.cs @@ -1,7 +1,6 @@ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Http; @@ -15,14 +14,13 @@ namespace Microsoft.Net.Server { public class ServerTests { - private const string Address = "http://localhost:8080/"; - [Fact] public async Task Server_200OK_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Dispose(); @@ -35,9 +33,10 @@ namespace Microsoft.Net.Server [Fact] public async Task Server_SendHelloWorld_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Response.ContentLength = 11; @@ -54,9 +53,10 @@ namespace Microsoft.Net.Server [Fact] public async Task Server_EchoHelloWorld_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task responseTask = SendRequestAsync(Address, "Hello World"); + Task responseTask = SendRequestAsync(address, "Hello World"); var context = await server.GetContextAsync(); string input = new StreamReader(context.Request.Body).ReadToEnd(); @@ -78,11 +78,12 @@ namespace Microsoft.Net.Server TimeSpan interval = TimeSpan.FromSeconds(1); ManualResetEvent canceled = new ManualResetEvent(false); - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { // Note: System.Net.Sockets does not RST the connection by default, it just FINs. // Http.Sys's disconnect notice requires a RST. - Task responseTask = SendHungRequestAsync("GET", Address); + Task responseTask = SendHungRequestAsync("GET", address); var context = await server.GetContextAsync(); CancellationToken ct = context.DisconnectToken; @@ -107,11 +108,12 @@ namespace Microsoft.Net.Server TimeSpan interval = TimeSpan.FromSeconds(1); ManualResetEvent canceled = new ManualResetEvent(false); - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { // Note: System.Net.Sockets does not RST the connection by default, it just FINs. // Http.Sys's disconnect notice requires a RST. - Task responseTask = SendHungRequestAsync("GET", Address); + Task responseTask = SendHungRequestAsync("GET", address); var context = await server.GetContextAsync(); CancellationToken ct = context.DisconnectToken; @@ -132,10 +134,11 @@ namespace Microsoft.Net.Server [Fact] public async Task Server_SetQueueLimit_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { server.SetRequestQueueLimit(1001); - Task responseTask = SendRequestAsync(Address); + Task responseTask = SendRequestAsync(address); var context = await server.GetContextAsync(); context.Dispose(); diff --git a/test/Microsoft.Net.Server.FunctionalTests/Utilities.cs b/test/Microsoft.Net.Server.FunctionalTests/Utilities.cs index e911f5baa2..18c3d31987 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/Utilities.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/Utilities.cs @@ -6,31 +6,67 @@ namespace Microsoft.Net.Server { internal static class Utilities { - internal static WebListener CreateHttpServer() + private const int BasePort = 5001; + private const int MaxPort = 8000; + private static int NextPort = BasePort; + private static object PortLock = new object(); + + internal static WebListener CreateHttpAuthServer(AuthenticationTypes authType, out string baseAddress) { - return CreateServer("http", "localhost", "8080", string.Empty); + var listener = CreateHttpServer(out baseAddress); + listener.AuthenticationManager.AuthenticationTypes = authType; + return listener; } + internal static WebListener CreateHttpServer(out string baseAddress) + { + string root; + return CreateDynamicHttpServer(string.Empty, out root, out baseAddress); + } + + internal static WebListener CreateHttpServerReturnRoot(string path, out string root) + { + string baseAddress; + return CreateDynamicHttpServer(path, out root, out baseAddress); + } + + internal static WebListener CreateDynamicHttpServer(string basePath, out string root, out string baseAddress) + { + lock (PortLock) + { + while (NextPort < MaxPort) + { + var port = NextPort++; + var prefix = UrlPrefix.Create("http", "localhost", port, basePath); + root = prefix.Scheme + "://" + prefix.Host + ":" + prefix.Port; + baseAddress = prefix.ToString(); + var listener = new WebListener(); + listener.UrlPrefixes.Add(prefix); + try + { + listener.Start(); + return listener; + } + catch (WebListenerException) + { + listener.Dispose(); + } + } + NextPort = BasePort; + } + throw new Exception("Failed to locate a free port."); + } + + internal static WebListener CreateHttpsServer() { - return CreateServer("https", "localhost", "9090", string.Empty); + return CreateServer("https", "localhost", 9090, string.Empty); } - internal static WebListener CreateAuthServer(AuthenticationTypes authType) - { - return CreateServer("http", "localhost", "8080", string.Empty, authType); - } - - internal static WebListener CreateServer(string scheme, string host, string port, string path) - { - return CreateServer(scheme, host, port, path, AuthenticationTypes.AllowAnonymous); - } - - internal static WebListener CreateServer(string scheme, string host, string port, string path, AuthenticationTypes authType) + internal static WebListener CreateServer(string scheme, string host, int port, string path) { WebListener listener = new WebListener(); listener.UrlPrefixes.Add(UrlPrefix.Create(scheme, host, port, path)); - listener.AuthenticationManager.AuthenticationTypes = authType; listener.Start(); return listener; } diff --git a/test/Microsoft.Net.Server.FunctionalTests/WebSocketTests.cs b/test/Microsoft.Net.Server.FunctionalTests/WebSocketTests.cs index 946aabec14..e54c94740f 100644 --- a/test/Microsoft.Net.Server.FunctionalTests/WebSocketTests.cs +++ b/test/Microsoft.Net.Server.FunctionalTests/WebSocketTests.cs @@ -12,21 +12,19 @@ namespace Microsoft.Net.Server { public class WebSocketTests { - private const string Address = "http://localhost:8080/"; - private const string WsAddress = "ws://localhost:8080/"; - [Fact] public async Task WebSocketAccept_AfterHeadersSent_Throws() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task clientTask = SendRequestAsync(Address); + Task clientTask = SendRequestAsync(address); var context = await server.GetContextAsync(); byte[] body = Encoding.UTF8.GetBytes("Hello World"); context.Response.Body.Write(body, 0, body.Length); - Assert.ThrowsAsync(async () => await context.AcceptWebSocketAsync()); + await Assert.ThrowsAsync(async () => await context.AcceptWebSocketAsync()); context.Dispose(); HttpResponseMessage response = await clientTask; Assert.Equal(200, (int)response.StatusCode); @@ -38,9 +36,10 @@ namespace Microsoft.Net.Server [Fact] public async Task WebSocketAccept_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task clientTask = SendWebSocketRequestAsync(WsAddress); + Task clientTask = SendWebSocketRequestAsync(ConvertToWebSocketAddress(address)); var context = await server.GetContextAsync(); Assert.True(context.IsUpgradableRequest); @@ -54,9 +53,10 @@ namespace Microsoft.Net.Server [Fact] public async Task WebSocketAccept_SendAndReceive_Success() { - using (var server = Utilities.CreateHttpServer()) + string address; + using (var server = Utilities.CreateHttpServer(out address)) { - Task clientTask = SendWebSocketRequestAsync(WsAddress); + Task clientTask = SendWebSocketRequestAsync(ConvertToWebSocketAddress(address)); var context = await server.GetContextAsync(); Assert.True(context.IsWebSocketRequest); @@ -81,6 +81,13 @@ namespace Microsoft.Net.Server } } + private string ConvertToWebSocketAddress(string address) + { + var builder = new UriBuilder(address); + builder.Scheme = "ws"; + return builder.ToString(); + } + private async Task SendRequestAsync(string uri) { using (HttpClient client = new HttpClient())