Merge remote-tracking branch 'origin/release/2.1' into tratcher/testhost/2.2

# Conflicts:
#	eng/targets/Packaging.targets
#	src/Hosting/TestHost/test/ClientHandlerTests.cs
#	src/Middleware/WebSockets/test/ConformanceTests/Microsoft.AspNetCore.WebSockets.ConformanceTests.csproj
This commit is contained in:
Chris R 2018-12-03 09:26:57 -08:00
commit d73e3b20b8
14 changed files with 78 additions and 109 deletions

View File

@ -157,51 +157,50 @@ namespace Microsoft.AspNetCore.TestHost
[Fact] [Fact]
public async Task HeadersAvailableBeforeBodyFinished() public async Task HeadersAvailableBeforeBodyFinished()
{ {
ManualResetEvent block = new ManualResetEvent(false); var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context => var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context =>
{ {
context.Response.Headers["TestHeader"] = "TestValue"; context.Response.Headers["TestHeader"] = "TestValue";
await context.Response.WriteAsync("BodyStarted,"); await context.Response.WriteAsync("BodyStarted,");
block.WaitOne(); await block.Task;
await context.Response.WriteAsync("BodyFinished"); await context.Response.WriteAsync("BodyFinished");
})); }));
var httpClient = new HttpClient(handler); var httpClient = new HttpClient(handler);
HttpResponseMessage response = await httpClient.GetAsync("https://example.com/", HttpResponseMessage response = await httpClient.GetAsync("https://example.com/",
HttpCompletionOption.ResponseHeadersRead); HttpCompletionOption.ResponseHeadersRead);
Assert.Equal("TestValue", response.Headers.GetValues("TestHeader").First()); Assert.Equal("TestValue", response.Headers.GetValues("TestHeader").First());
block.Set(); block.SetResult(0);
Assert.Equal("BodyStarted,BodyFinished", await response.Content.ReadAsStringAsync()); Assert.Equal("BodyStarted,BodyFinished", await response.Content.ReadAsStringAsync());
} }
[Fact] [Fact]
public async Task FlushSendsHeaders() public async Task FlushSendsHeaders()
{ {
ManualResetEvent block = new ManualResetEvent(false); var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context => var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context =>
{ {
context.Response.Headers["TestHeader"] = "TestValue"; context.Response.Headers["TestHeader"] = "TestValue";
context.Response.Body.Flush(); context.Response.Body.Flush();
block.WaitOne(); await block.Task;
await context.Response.WriteAsync("BodyFinished"); await context.Response.WriteAsync("BodyFinished");
})); }));
var httpClient = new HttpClient(handler); var httpClient = new HttpClient(handler);
HttpResponseMessage response = await httpClient.GetAsync("https://example.com/", HttpResponseMessage response = await httpClient.GetAsync("https://example.com/",
HttpCompletionOption.ResponseHeadersRead); HttpCompletionOption.ResponseHeadersRead);
Assert.Equal("TestValue", response.Headers.GetValues("TestHeader").First()); Assert.Equal("TestValue", response.Headers.GetValues("TestHeader").First());
block.Set(); block.SetResult(0);
Assert.Equal("BodyFinished", await response.Content.ReadAsStringAsync()); Assert.Equal("BodyFinished", await response.Content.ReadAsStringAsync());
} }
[Fact] [Fact]
public async Task ClientDisposalCloses() public async Task ClientDisposalCloses()
{ {
ManualResetEvent block = new ManualResetEvent(false); var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
var handler = new ClientHandler(PathString.Empty, new DummyApplication(context => var handler = new ClientHandler(PathString.Empty, new DummyApplication(context =>
{ {
context.Response.Headers["TestHeader"] = "TestValue"; context.Response.Headers["TestHeader"] = "TestValue";
context.Response.Body.Flush(); context.Response.Body.Flush();
block.WaitOne(); return block.Task;
return Task.FromResult(0);
})); }));
var httpClient = new HttpClient(handler); var httpClient = new HttpClient(handler);
HttpResponseMessage response = await httpClient.GetAsync("https://example.com/", HttpResponseMessage response = await httpClient.GetAsync("https://example.com/",
@ -211,21 +210,20 @@ namespace Microsoft.AspNetCore.TestHost
Task<int> readTask = responseStream.ReadAsync(new byte[100], 0, 100); Task<int> readTask = responseStream.ReadAsync(new byte[100], 0, 100);
Assert.False(readTask.IsCompleted); Assert.False(readTask.IsCompleted);
responseStream.Dispose(); responseStream.Dispose();
var result = await readTask.TimeoutAfter(TimeSpan.FromSeconds(10)); var read = await readTask.WithTimeout();
Assert.Equal(0, result); Assert.Equal(0, read);
block.Set(); block.SetResult(0);
} }
[Fact] [Fact]
public async Task ClientCancellationAborts() public async Task ClientCancellationAborts()
{ {
ManualResetEvent block = new ManualResetEvent(false); var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
var handler = new ClientHandler(PathString.Empty, new DummyApplication(context => var handler = new ClientHandler(PathString.Empty, new DummyApplication(context =>
{ {
context.Response.Headers["TestHeader"] = "TestValue"; context.Response.Headers["TestHeader"] = "TestValue";
context.Response.Body.Flush(); context.Response.Body.Flush();
block.WaitOne(); return block.Task;
return Task.FromResult(0);
})); }));
var httpClient = new HttpClient(handler); var httpClient = new HttpClient(handler);
HttpResponseMessage response = await httpClient.GetAsync("https://example.com/", HttpResponseMessage response = await httpClient.GetAsync("https://example.com/",
@ -236,8 +234,8 @@ namespace Microsoft.AspNetCore.TestHost
Task<int> readTask = responseStream.ReadAsync(new byte[100], 0, 100, cts.Token); Task<int> readTask = responseStream.ReadAsync(new byte[100], 0, 100, cts.Token);
Assert.False(readTask.IsCompleted, "Not Completed"); Assert.False(readTask.IsCompleted, "Not Completed");
cts.Cancel(); cts.Cancel();
await Assert.ThrowsAsync<OperationCanceledException>(() => readTask.TimeoutAfter(TimeSpan.FromSeconds(10))); await Assert.ThrowsAsync<OperationCanceledException>(() => readTask.WithTimeout());
block.Set(); block.SetResult(0);
} }
[Fact] [Fact]
@ -255,19 +253,19 @@ namespace Microsoft.AspNetCore.TestHost
[Fact] [Fact]
public async Task ExceptionAfterFirstWriteIsReported() public async Task ExceptionAfterFirstWriteIsReported()
{ {
ManualResetEvent block = new ManualResetEvent(false); var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context => var handler = new ClientHandler(PathString.Empty, new DummyApplication(async context =>
{ {
context.Response.Headers["TestHeader"] = "TestValue"; context.Response.Headers["TestHeader"] = "TestValue";
await context.Response.WriteAsync("BodyStarted"); await context.Response.WriteAsync("BodyStarted");
block.WaitOne(); await block.Task;
throw new InvalidOperationException("Test Exception"); throw new InvalidOperationException("Test Exception");
})); }));
var httpClient = new HttpClient(handler); var httpClient = new HttpClient(handler);
HttpResponseMessage response = await httpClient.GetAsync("https://example.com/", HttpResponseMessage response = await httpClient.GetAsync("https://example.com/",
HttpCompletionOption.ResponseHeadersRead); HttpCompletionOption.ResponseHeadersRead);
Assert.Equal("TestValue", response.Headers.GetValues("TestHeader").First()); Assert.Equal("TestValue", response.Headers.GetValues("TestHeader").First());
block.Set(); block.SetResult(0);
var ex = await Assert.ThrowsAsync<HttpRequestException>(() => response.Content.ReadAsStringAsync()); var ex = await Assert.ThrowsAsync<HttpRequestException>(() => response.Content.ReadAsStringAsync());
Assert.IsType<InvalidOperationException>(ex.GetBaseException()); Assert.IsType<InvalidOperationException>(ex.GetBaseException());
} }

View File

@ -102,18 +102,17 @@ namespace Microsoft.AspNetCore.TestHost
[Fact] [Fact]
public async Task HeadersAvailableBeforeSyncBodyFinished() public async Task HeadersAvailableBeforeSyncBodyFinished()
{ {
var block = new ManualResetEvent(false); var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
var builder = new WebHostBuilder().Configure(app => var builder = new WebHostBuilder().Configure(app =>
{ {
app.Run(c => app.Run(async c =>
{ {
c.Response.Headers["TestHeader"] = "TestValue"; c.Response.Headers["TestHeader"] = "TestValue";
var bytes = Encoding.UTF8.GetBytes("BodyStarted" + Environment.NewLine); var bytes = Encoding.UTF8.GetBytes("BodyStarted" + Environment.NewLine);
c.Response.Body.Write(bytes, 0, bytes.Length); c.Response.Body.Write(bytes, 0, bytes.Length);
Assert.True(block.WaitOne(TimeSpan.FromSeconds(5))); await block.Task;
bytes = Encoding.UTF8.GetBytes("BodyFinished"); bytes = Encoding.UTF8.GetBytes("BodyFinished");
c.Response.Body.Write(bytes, 0, bytes.Length); c.Response.Body.Write(bytes, 0, bytes.Length);
return Task.CompletedTask;
}); });
}); });
var server = new TestServer(builder); var server = new TestServer(builder);
@ -122,21 +121,21 @@ namespace Microsoft.AspNetCore.TestHost
Assert.Equal("TestValue", context.Response.Headers["TestHeader"]); Assert.Equal("TestValue", context.Response.Headers["TestHeader"]);
var reader = new StreamReader(context.Response.Body); var reader = new StreamReader(context.Response.Body);
Assert.Equal("BodyStarted", reader.ReadLine()); Assert.Equal("BodyStarted", reader.ReadLine());
block.Set(); block.SetResult(0);
Assert.Equal("BodyFinished", reader.ReadToEnd()); Assert.Equal("BodyFinished", reader.ReadToEnd());
} }
[Fact] [Fact]
public async Task HeadersAvailableBeforeAsyncBodyFinished() public async Task HeadersAvailableBeforeAsyncBodyFinished()
{ {
var block = new ManualResetEvent(false); var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
var builder = new WebHostBuilder().Configure(app => var builder = new WebHostBuilder().Configure(app =>
{ {
app.Run(async c => app.Run(async c =>
{ {
c.Response.Headers["TestHeader"] = "TestValue"; c.Response.Headers["TestHeader"] = "TestValue";
await c.Response.WriteAsync("BodyStarted" + Environment.NewLine); await c.Response.WriteAsync("BodyStarted" + Environment.NewLine);
Assert.True(block.WaitOne(TimeSpan.FromSeconds(5))); await block.Task;
await c.Response.WriteAsync("BodyFinished"); await c.Response.WriteAsync("BodyFinished");
}); });
}); });
@ -146,21 +145,21 @@ namespace Microsoft.AspNetCore.TestHost
Assert.Equal("TestValue", context.Response.Headers["TestHeader"]); Assert.Equal("TestValue", context.Response.Headers["TestHeader"]);
var reader = new StreamReader(context.Response.Body); var reader = new StreamReader(context.Response.Body);
Assert.Equal("BodyStarted", await reader.ReadLineAsync()); Assert.Equal("BodyStarted", await reader.ReadLineAsync());
block.Set(); block.SetResult(0);
Assert.Equal("BodyFinished", await reader.ReadToEndAsync()); Assert.Equal("BodyFinished", await reader.ReadToEndAsync());
} }
[Fact] [Fact]
public async Task FlushSendsHeaders() public async Task FlushSendsHeaders()
{ {
var block = new ManualResetEvent(false); var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
var builder = new WebHostBuilder().Configure(app => var builder = new WebHostBuilder().Configure(app =>
{ {
app.Run(async c => app.Run(async c =>
{ {
c.Response.Headers["TestHeader"] = "TestValue"; c.Response.Headers["TestHeader"] = "TestValue";
c.Response.Body.Flush(); c.Response.Body.Flush();
block.WaitOne(); await block.Task;
await c.Response.WriteAsync("BodyFinished"); await c.Response.WriteAsync("BodyFinished");
}); });
}); });
@ -168,21 +167,21 @@ namespace Microsoft.AspNetCore.TestHost
var context = await server.SendAsync(c => { }); var context = await server.SendAsync(c => { });
Assert.Equal("TestValue", context.Response.Headers["TestHeader"]); Assert.Equal("TestValue", context.Response.Headers["TestHeader"]);
block.Set(); block.SetResult(0);
Assert.Equal("BodyFinished", new StreamReader(context.Response.Body).ReadToEnd()); Assert.Equal("BodyFinished", new StreamReader(context.Response.Body).ReadToEnd());
} }
[Fact] [Fact]
public async Task ClientDisposalCloses() public async Task ClientDisposalCloses()
{ {
var block = new ManualResetEvent(false); var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
var builder = new WebHostBuilder().Configure(app => var builder = new WebHostBuilder().Configure(app =>
{ {
app.Run(async c => app.Run(async c =>
{ {
c.Response.Headers["TestHeader"] = "TestValue"; c.Response.Headers["TestHeader"] = "TestValue";
c.Response.Body.Flush(); c.Response.Body.Flush();
block.WaitOne(); await block.Task;
await c.Response.WriteAsync("BodyFinished"); await c.Response.WriteAsync("BodyFinished");
}); });
}); });
@ -194,20 +193,20 @@ namespace Microsoft.AspNetCore.TestHost
Task<int> readTask = responseStream.ReadAsync(new byte[100], 0, 100); Task<int> readTask = responseStream.ReadAsync(new byte[100], 0, 100);
Assert.False(readTask.IsCompleted); Assert.False(readTask.IsCompleted);
responseStream.Dispose(); responseStream.Dispose();
Assert.True(readTask.Wait(TimeSpan.FromSeconds(10))); var read = await readTask.WithTimeout();
Assert.Equal(0, readTask.Result); Assert.Equal(0, read);
block.Set(); block.SetResult(0);
} }
[Fact] [Fact]
public void ClientCancellationAborts() public async Task ClientCancellationAborts()
{ {
var block = new ManualResetEvent(false); var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
var builder = new WebHostBuilder().Configure(app => var builder = new WebHostBuilder().Configure(app =>
{ {
app.Run(c => app.Run(c =>
{ {
block.Set(); block.SetResult(0);
Assert.True(c.RequestAborted.WaitHandle.WaitOne(TimeSpan.FromSeconds(10))); Assert.True(c.RequestAborted.WaitHandle.WaitOne(TimeSpan.FromSeconds(10)));
c.RequestAborted.ThrowIfCancellationRequested(); c.RequestAborted.ThrowIfCancellationRequested();
return Task.CompletedTask; return Task.CompletedTask;
@ -216,24 +215,23 @@ namespace Microsoft.AspNetCore.TestHost
var server = new TestServer(builder); var server = new TestServer(builder);
var cts = new CancellationTokenSource(); var cts = new CancellationTokenSource();
var contextTask = server.SendAsync(c => { }, cts.Token); var contextTask = server.SendAsync(c => { }, cts.Token);
block.WaitOne(); await block.Task;
cts.Cancel(); cts.Cancel();
var ex = Assert.Throws<AggregateException>(() => contextTask.Wait(TimeSpan.FromSeconds(10))); await Assert.ThrowsAsync<OperationCanceledException>(() => contextTask.WithTimeout());
Assert.IsAssignableFrom<OperationCanceledException>(ex.GetBaseException());
} }
[Fact] [Fact]
public async Task ClientCancellationAbortsReadAsync() public async Task ClientCancellationAbortsReadAsync()
{ {
var block = new ManualResetEvent(false); var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
var builder = new WebHostBuilder().Configure(app => var builder = new WebHostBuilder().Configure(app =>
{ {
app.Run(async c => app.Run(async c =>
{ {
c.Response.Headers["TestHeader"] = "TestValue"; c.Response.Headers["TestHeader"] = "TestValue";
c.Response.Body.Flush(); c.Response.Body.Flush();
block.WaitOne(); await block.Task;
await c.Response.WriteAsync("BodyFinished"); await c.Response.WriteAsync("BodyFinished");
}); });
}); });
@ -246,9 +244,8 @@ namespace Microsoft.AspNetCore.TestHost
var readTask = responseStream.ReadAsync(new byte[100], 0, 100, cts.Token); var readTask = responseStream.ReadAsync(new byte[100], 0, 100, cts.Token);
Assert.False(readTask.IsCompleted); Assert.False(readTask.IsCompleted);
cts.Cancel(); cts.Cancel();
var ex = Assert.Throws<AggregateException>(() => readTask.Wait(TimeSpan.FromSeconds(10))); await Assert.ThrowsAsync<OperationCanceledException>(() => readTask.WithTimeout());
Assert.IsAssignableFrom<OperationCanceledException>(ex.GetBaseException()); block.SetResult(0);
block.Set();
} }
[Fact] [Fact]
@ -268,14 +265,14 @@ namespace Microsoft.AspNetCore.TestHost
[Fact] [Fact]
public async Task ExceptionAfterFirstWriteIsReported() public async Task ExceptionAfterFirstWriteIsReported()
{ {
var block = new ManualResetEvent(false); var block = new TaskCompletionSource<int>(TaskCreationOptions.RunContinuationsAsynchronously);
var builder = new WebHostBuilder().Configure(app => var builder = new WebHostBuilder().Configure(app =>
{ {
app.Run(async c => app.Run(async c =>
{ {
c.Response.Headers["TestHeader"] = "TestValue"; c.Response.Headers["TestHeader"] = "TestValue";
await c.Response.WriteAsync("BodyStarted"); await c.Response.WriteAsync("BodyStarted");
block.WaitOne(); await block.Task;
throw new InvalidOperationException("Test Exception"); throw new InvalidOperationException("Test Exception");
}); });
}); });
@ -284,7 +281,7 @@ namespace Microsoft.AspNetCore.TestHost
Assert.Equal("TestValue", context.Response.Headers["TestHeader"]); Assert.Equal("TestValue", context.Response.Headers["TestHeader"]);
Assert.Equal(11, context.Response.Body.Read(new byte[100], 0, 100)); Assert.Equal(11, context.Response.Body.Read(new byte[100], 0, 100));
block.Set(); block.SetResult(0);
var ex = Assert.Throws<IOException>(() => context.Response.Body.Read(new byte[100], 0, 100)); var ex = Assert.Throws<IOException>(() => context.Response.Body.Read(new byte[100], 0, 100));
Assert.IsAssignableFrom<InvalidOperationException>(ex.InnerException); Assert.IsAssignableFrom<InvalidOperationException>(ex.InnerException);
} }

View File

@ -0,0 +1,29 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading.Tasks;
namespace Microsoft.AspNetCore.TestHost
{
internal static class Utilities
{
internal static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(15);
internal static Task<T> WithTimeout<T>(this Task<T> task) => task.WithTimeout(DefaultTimeout);
internal static async Task<T> WithTimeout<T>(this Task<T> task, TimeSpan timeout)
{
var completedTask = await Task.WhenAny(task, Task.Delay(timeout));
if (completedTask == task)
{
return await task;
}
else
{
throw new TimeoutException("The task has timed out.");
}
}
}
}

View File

@ -1,42 +0,0 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:6155/",
"sslPort": 44371
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "ManagedSockets"
}
},
"AutobahnTestApp": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "ManagedSockets"
}
},
"AutobahnTestApp (SSL)": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "https://localhost:5443",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "ManagedSockets"
}
},
"WebListener": {
"commandName": "Project",
"commandLineArgs": "--server Microsoft.AspNetCore.Server.HttpSys",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "ManagedSockets"
}
}
}
}

View File

@ -1,4 +1,4 @@
using System; using System;
using System.IO; using System.IO;
namespace Microsoft.AspNetCore.WebSockets.ConformanceTest namespace Microsoft.AspNetCore.WebSockets.ConformanceTest
@ -7,22 +7,7 @@ namespace Microsoft.AspNetCore.WebSockets.ConformanceTest
{ {
public static string GetApplicationPath(string projectName) public static string GetApplicationPath(string projectName)
{ {
var applicationBasePath = AppContext.BaseDirectory; return Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, projectName));
var directoryInfo = new DirectoryInfo(applicationBasePath);
do
{
var solutionFileInfo = new FileInfo(Path.Combine(directoryInfo.FullName, "WebSockets.sln"));
if (solutionFileInfo.Exists)
{
return Path.GetFullPath(Path.Combine(directoryInfo.FullName, "test", projectName));
}
directoryInfo = directoryInfo.Parent;
}
while (directoryInfo.Parent != null);
throw new Exception($"Solution root could not be found using {applicationBasePath}");
} }
} }
} }

View File

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework> <TargetFramework>netcoreapp2.2</TargetFramework>
<DefaultItemExcludes>$(DefaultItemExcludes);AutobahnTestApp\**\*</DefaultItemExcludes>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -9,6 +10,7 @@
<Reference Include="Microsoft.Extensions.Logging" /> <Reference Include="Microsoft.Extensions.Logging" />
<Reference Include="Microsoft.Extensions.Logging.Console" /> <Reference Include="Microsoft.Extensions.Logging.Console" />
<Content Include="AutobahnTestApp\**\*" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup> </ItemGroup>
</Project> </Project>