#52 - Enable parallel tests by using dynamic ports.

This commit is contained in:
Chris Ross 2014-07-24 16:13:03 -07:00
parent 53e38e2a23
commit 6fab49b6e0
30 changed files with 636 additions and 451 deletions

View File

@ -47,6 +47,24 @@ namespace Microsoft.Net.Server
/// <param name="port">If empty, the default port for the given scheme will be used (80 or 443).</param>
/// <param name="path">Should start and end with a '/', though a missing trailing slash will be added. This value must be un-escaped.</param>
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);
}
/// <summary>
/// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364698(v=vs.85).aspx
/// </summary>
/// <param name="scheme">http or https. Will be normalized to lower case.</param>
/// <param name="host">+, *, IPv4, [IPv6], or a dns name. Http.Sys does not permit punycode (xn--), use Unicode instead.</param>
/// <param name="port">If empty, the default port for the given scheme will be used (80 or 443).</param>
/// <param name="path">Should start and end with a '/', though a missing trailing slash will be added. This value must be un-escaped.</param>
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
{

View File

@ -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);
}

View File

@ -22,7 +22,6 @@
<Compile Include="HttpsTests.cs" />
<Compile Include="WebSocketTests.cs" />
<Compile Include="OpaqueUpgradeTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RequestBodyTests.cs" />
<Compile Include="RequestHeaderTests.cs" />
<Compile Include="RequestTests.cs" />

View File

@ -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<InvalidOperationException>(async () => await SendOpaqueRequestAsync(method, Address, extraHeader));
await Assert.ThrowsAsync<InvalidOperationException>(async () => await SendOpaqueRequestAsync(method, address, extraHeader));
}
}

View File

@ -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)]

View File

@ -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]);

View File

@ -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);

View File

@ -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<IHttpRequestFeature>();
@ -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);

View File

@ -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<string> 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<string> 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<string> 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<Stream>("owin.ResponseBody").Write(new byte[10], 0, 10);
return env.Get<Stream>("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<string> 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<HttpRequestException>(() => SendRequestAsync(Address));
await Assert.ThrowsAsync<HttpRequestException>(() => 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<AggregateException>(() => SendRequestAsync(Address).Result);
Assert.Throws<AggregateException>(() => 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<AggregateException>(() => SendRequestAsync(Address).Result);
Assert.Throws<AggregateException>(() => 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<string> contentLength;

View File

@ -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<IHttpResponseFeature>();
@ -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<IHttpResponseFeature>();
@ -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<IHttpResponseFeature>();
@ -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<IHttpResponseFeature>();
@ -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<Stream>("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<IHttpResponseFeature>();
@ -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<IHttpResponseFeature>();
@ -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<IHttpResponseFeature>();
@ -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

View File

@ -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<string> 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<IHttpSendFileFeature>();
@ -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<IHttpSendFileFeature>();
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<string> 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<IHttpSendFileFeature>();
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<string> 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<IHttpSendFileFeature>();
@ -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<string> 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<IHttpSendFileFeature>();
@ -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<string> 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<IHttpSendFileFeature>();
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<string> 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<IHttpSendFileFeature>();
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<IHttpSendFileFeature>();
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<IHttpSendFileFeature>();
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<string> 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<IHttpSendFileFeature>();
@ -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<string> 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<IHttpSendFileFeature>();
@ -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<string> 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<IHttpSendFileFeature>();
@ -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<string> contentLength;
Assert.True(response.Content.Headers.TryGetValues("content-length", out contentLength), "Content-Length");

View File

@ -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);
}
}

View File

@ -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<string> 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<string> requestTask = SendRequestAsync(Address);
Task<string> requestTask = SendRequestAsync(address);
Assert.Throws<AggregateException>(() => requestTask.Result);
// Do it again to make sure the server didn't crash
requestTask = SendRequestAsync(Address);
requestTask = SendRequestAsync(address);
Assert.Throws<AggregateException>(() => requestTask.Result);
}
}
@ -125,7 +128,8 @@ namespace Microsoft.AspNet.Server.WebListener
int requestCount = 0;
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
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<Task> requestTasks = new List<Task>();
for (int i = 0; i < requestLimit; i++)
{
Task<string> requestTask = SendRequestAsync(Address);
Task<string> requestTask = SendRequestAsync(address);
requestTasks.Add(requestTask);
}
@ -162,7 +166,8 @@ namespace Microsoft.AspNet.Server.WebListener
int requestCount = 0;
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
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<Task> requestTasks = new List<Task>();
for (int i = 0; i < requestLimit; i++)
{
Task<string> requestTask = SendRequestAsync(Address);
Task<string> 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<SocketException>(() => 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);
}
}

View File

@ -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);
}

View File

@ -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<IHttpWebSocketFeature>();
@ -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<IHttpWebSocketFeature>();
@ -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<byte>(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<HttpResponseMessage> SendRequestAsync(string uri)
{
using (HttpClient client = new HttpClient())

View File

@ -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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address, useDefaultCredentials: true);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address, useDefaultCredentials: true);
Task<HttpResponseMessage> responseTask = SendRequestAsync(address, useDefaultCredentials: true);
var context = await server.GetContextAsync();
Assert.NotNull(context.User);

View File

@ -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")]

View File

@ -22,7 +22,6 @@
<Compile Include="HttpsTests.cs" />
<Compile Include="WebSocketTests.cs" />
<Compile Include="OpaqueUpgradeTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RequestBodyTests.cs" />
<Compile Include="RequestHeaderTests.cs" />
<Compile Include="RequestTests.cs" />

View File

@ -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<HttpResponseMessage> clientTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<InvalidOperationException>(async () => await context.UpgradeAsync());
await Assert.ThrowsAsync<InvalidOperationException>(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<Stream> clientTask = SendOpaqueRequestAsync("GET", Address);
Task<Stream> 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<Stream> clientTask = SendOpaqueRequestAsync(method, Address, extraHeader);
Task<Stream> 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();

View File

@ -1,8 +0,0 @@
// -----------------------------------------------------------------------
// <copyright file="AssemblyInfo.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------
// These tests can't run in parallel because they all use the same port.
[assembly: Xunit.CollectionBehaviorAttribute(Xunit.CollectionBehavior.CollectionPerAssembly, DisableTestParallelization = true)]

View File

@ -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<string> responseTask = SendRequestAsync(Address, "Hello World");
Task<string> 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<string> responseTask = SendRequestAsync(Address, "Hello World");
Task<string> 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<string> responseTask = SendRequestAsync(Address, "Hello World");
Task<string> 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<string> responseTask = SendRequestAsync(Address, "Hello World");
Task<string> 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<string> responseTask = SendRequestAsync(Address, content);
Task<string> 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<string> responseTask = SendRequestAsync(Address, content);
Task<string> 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<string> responseTask = SendSocketRequestAsync(Address);
Task<string> responseTask = SendSocketRequestAsync(address);
var context = await server.GetContextAsync();
byte[] input = new byte[11];

View File

@ -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<string> responseTask = SendRequestAsync(Address);
Task<string> 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);

View File

@ -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<string> responseTask = SendRequestAsync(Address + "/basepath/SomePath?SomeQuery");
Task<string> 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<string> responseTask = SendRequestAsync(requestUri);
Task<string> 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<string> responseTask = SendRequestAsync(Address + requestUri);
Task<string> responseTask = SendRequestAsync(root + requestUri);
var context = await server.GetContextAsync();
var request = context.Request;

View File

@ -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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync();
context.Response.Headers["Content-lenGth"] = " 10 ";

View File

@ -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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<WebResponse> 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<WebResponse> 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<WebResponse> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> 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<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync();
var responseHeaders = context.Response.Headers;

View File

@ -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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync();
await Assert.ThrowsAsync<FileNotFoundException>(() =>
@ -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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync();
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(
@ -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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync();
await Assert.ThrowsAsync<ArgumentOutOfRangeException>(
@ -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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync();
context.Response.Headers["Content-lenGth"] = "0";

View File

@ -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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync();
Assert.Throws<ArgumentOutOfRangeException>(() => { 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<HttpResponseMessage> responseTask = SendRequestAsync(Address);
Task<HttpResponseMessage> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync();
Assert.Throws<ArgumentOutOfRangeException>(() => { context.Response.StatusCode = 0; });

View File

@ -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<string> responseTask = SendRequestAsync(Address);
Task<string> 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<string> responseTask = SendRequestAsync(Address);
Task<string> 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<string> responseTask = SendRequestAsync(Address, "Hello World");
Task<string> 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<Socket> responseTask = SendHungRequestAsync("GET", Address);
Task<Socket> 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<Socket> responseTask = SendHungRequestAsync("GET", Address);
Task<Socket> 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<string> responseTask = SendRequestAsync(Address);
Task<string> responseTask = SendRequestAsync(address);
var context = await server.GetContextAsync();
context.Dispose();

View File

@ -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;
}

View File

@ -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<HttpResponseMessage> clientTask = SendRequestAsync(Address);
Task<HttpResponseMessage> 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<InvalidOperationException>(async () => await context.AcceptWebSocketAsync());
await Assert.ThrowsAsync<InvalidOperationException>(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<WebSocket> clientTask = SendWebSocketRequestAsync(WsAddress);
Task<WebSocket> 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<WebSocket> clientTask = SendWebSocketRequestAsync(WsAddress);
Task<WebSocket> 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<HttpResponseMessage> SendRequestAsync(string uri)
{
using (HttpClient client = new HttpClient())