Fix flaky ResponseTests.FailedWritesResultInAbortedRequest.

This commit is contained in:
Cesar Blum Silveira 2017-05-17 17:01:34 -07:00 committed by GitHub
parent 7f0319f5dd
commit f8a6433cd5
1 changed files with 15 additions and 23 deletions

View File

@ -2063,40 +2063,32 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
[Theory] [Theory]
[MemberData(nameof(ConnectionAdapterData))] [MemberData(nameof(ConnectionAdapterData))]
public async Task FailedWritesResultInAbortedRequest(ListenOptions listenOptions) public async Task ThrowsOnWriteWithRequestAbortedTokenAfterRequestIsAborted(ListenOptions listenOptions)
{ {
var testContext = new TestServiceContext();
// This should match _maxBytesPreCompleted in SocketOutput // This should match _maxBytesPreCompleted in SocketOutput
var maxBytesPreCompleted = 65536; var maxBytesPreCompleted = 65536;
// Ensure string is long enough to disable write-behind buffering // Ensure string is long enough to disable write-behind buffering
var largeString = new string('a', maxBytesPreCompleted + 1); var largeString = new string('a', maxBytesPreCompleted + 1);
var writeTcs = new TaskCompletionSource<object>(); var writeTcs = new TaskCompletionSource<object>();
var registrationWh = new ManualResetEventSlim(); var requestAbortedWh = new ManualResetEventSlim();
var connectionCloseWh = new ManualResetEventSlim();
var requestStartWh = new ManualResetEventSlim(); var requestStartWh = new ManualResetEventSlim();
using (var server = new TestServer(async httpContext => using (var server = new TestServer(async httpContext =>
{ {
requestStartWh.Set(); requestStartWh.Set();
var response = httpContext.Response; var response = httpContext.Response;
var request = httpContext.Request; var request = httpContext.Request;
var lifetime = httpContext.Features.Get<IHttpRequestLifetimeFeature>(); var lifetime = httpContext.Features.Get<IHttpRequestLifetimeFeature>();
lifetime.RequestAborted.Register(() => registrationWh.Set()); lifetime.RequestAborted.Register(() => requestAbortedWh.Set());
Assert.True(requestAbortedWh.Wait(TimeSpan.FromSeconds(10)));
await request.Body.CopyToAsync(Stream.Null);
Assert.True(connectionCloseWh.Wait(10_000));
try try
{ {
// Ensure write is long enough to disable write-behind buffering await response.WriteAsync(largeString, lifetime.RequestAborted);
for (int i = 0; i < 100; i++)
{
await response.WriteAsync(largeString, lifetime.RequestAborted);
registrationWh.Wait(1000);
}
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -2105,26 +2097,26 @@ namespace Microsoft.AspNetCore.Server.Kestrel.FunctionalTests
} }
writeTcs.SetException(new Exception("This shouldn't be reached.")); writeTcs.SetException(new Exception("This shouldn't be reached."));
}, testContext, listenOptions)) }, new TestServiceContext(), listenOptions))
{ {
using (var connection = server.CreateConnection()) using (var connection = server.CreateConnection())
{ {
await connection.Send( await connection.Send(
"POST / HTTP/1.1", "POST / HTTP/1.1",
"Host:", "Host:",
"Content-Length: 5", "Content-Length: 0",
"", "",
"Hello"); "");
Assert.True(requestStartWh.Wait(10_000)); Assert.True(requestStartWh.Wait(TimeSpan.FromSeconds(10)));
} }
connectionCloseWh.Set(); // Write failed - can throw TaskCanceledException or OperationCanceledException,
// dependending on how far the canceled write goes.
await Assert.ThrowsAnyAsync<OperationCanceledException>(async () => await writeTcs.Task).TimeoutAfter(TimeSpan.FromSeconds(15));
// Write failed
await Assert.ThrowsAsync<TaskCanceledException>(async () => await writeTcs.Task).TimeoutAfter(TimeSpan.FromSeconds(15));
// RequestAborted tripped // RequestAborted tripped
Assert.True(registrationWh.Wait(1000)); Assert.True(requestAbortedWh.Wait(TimeSpan.FromSeconds(1)));
} }
} }