Fix AbortedStream_ResetsAndDrainsRequest_RefusesFramesAfterCooldownExpires (#9487)

This commit is contained in:
Justin Kotalik 2019-04-18 12:44:54 -07:00 committed by GitHub
parent caac31c925
commit 10d70c5c9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 11 deletions

View File

@ -1163,6 +1163,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
internal async Task WaitForConnectionErrorAsync<TException>(bool ignoreNonGoAwayFrames, int expectedLastStreamId, Http2ErrorCode expectedErrorCode, params string[] expectedErrorMessage) internal async Task WaitForConnectionErrorAsync<TException>(bool ignoreNonGoAwayFrames, int expectedLastStreamId, Http2ErrorCode expectedErrorCode, params string[] expectedErrorMessage)
where TException : Exception where TException : Exception
{
await WaitForConnectionErrorAsyncDoNotCloseTransport<TException>(ignoreNonGoAwayFrames, expectedLastStreamId, expectedErrorCode, expectedErrorMessage);
_pair.Application.Output.Complete();
}
internal async Task WaitForConnectionErrorAsyncDoNotCloseTransport<TException>(bool ignoreNonGoAwayFrames, int expectedLastStreamId, Http2ErrorCode expectedErrorCode, params string[] expectedErrorMessage)
where TException : Exception
{ {
var frame = await ReceiveFrameAsync(); var frame = await ReceiveFrameAsync();
@ -1184,7 +1191,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
} }
await _connectionTask.DefaultTimeout(); await _connectionTask.DefaultTimeout();
_pair.Application.Output.Complete(); TestApplicationErrorLogger.LogInformation("Stopping Connection From ConnectionErrorAsync");
} }
internal async Task WaitForStreamErrorAsync(int expectedStreamId, Http2ErrorCode expectedErrorCode, string expectedErrorMessage) internal async Task WaitForStreamErrorAsync(int expectedStreamId, Http2ErrorCode expectedErrorCode, string expectedErrorMessage)

View File

@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http2;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure; using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Microsoft.AspNetCore.Testing; using Microsoft.AspNetCore.Testing;
using Microsoft.AspNetCore.Testing.xunit; using Microsoft.AspNetCore.Testing.xunit;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Net.Http.Headers; using Microsoft.Net.Http.Headers;
using Moq; using Moq;
using Xunit; using Xunit;
@ -193,11 +194,13 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
} }
[Theory] [Theory]
[Flaky("https://github.com/aspnet/AspNetCore-Internal/issues/1879", FlakyOn.All)] [Repeat(20)]
[InlineData((int)Http2FrameType.DATA)] [InlineData((int)Http2FrameType.DATA)]
[InlineData((int)Http2FrameType.CONTINUATION)] [InlineData((int)Http2FrameType.CONTINUATION)]
public async Task AbortedStream_ResetsAndDrainsRequest_RefusesFramesAfterCooldownExpires(int intFinalFrameType) public async Task AbortedStream_ResetsAndDrainsRequest_RefusesFramesAfterCooldownExpires(int intFinalFrameType)
{ {
var closeLock = new object();
var closed = false;
var finalFrameType = (Http2FrameType)intFinalFrameType; var finalFrameType = (Http2FrameType)intFinalFrameType;
// Remove callback that completes _pair.Application.Output on abort. // Remove callback that completes _pair.Application.Output on abort.
_mockConnectionContext.Reset(); _mockConnectionContext.Reset();
@ -216,8 +219,6 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
await WaitForStreamErrorAsync(1, Http2ErrorCode.INTERNAL_ERROR, "The connection was aborted by the application."); await WaitForStreamErrorAsync(1, Http2ErrorCode.INTERNAL_ERROR, "The connection was aborted by the application.");
var cts = new CancellationTokenSource();
async Task AdvanceClockAndSendFrames() async Task AdvanceClockAndSendFrames()
{ {
if (finalFrameType == Http2FrameType.CONTINUATION) if (finalFrameType == Http2FrameType.CONTINUATION)
@ -227,7 +228,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
} }
// There's a race when the appfunc is exiting about how soon it unregisters the stream, so retry until success. // There's a race when the appfunc is exiting about how soon it unregisters the stream, so retry until success.
while (!cts.Token.IsCancellationRequested) while (!closed)
{ {
// Just past the timeout // Just past the timeout
mockSystemClock.UtcNow += Constants.RequestBodyDrainTimeout + TimeSpan.FromTicks(1); mockSystemClock.UtcNow += Constants.RequestBodyDrainTimeout + TimeSpan.FromTicks(1);
@ -247,24 +248,24 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
throw new NotImplementedException(finalFrameType.ToString()); throw new NotImplementedException(finalFrameType.ToString());
} }
if (!cts.Token.IsCancellationRequested) // TODO how do I force a function to go async?
{ await Task.Delay(1);
await Task.Delay(10);
}
} }
} }
var sendTask = AdvanceClockAndSendFrames(); var sendTask = AdvanceClockAndSendFrames();
await WaitForConnectionErrorAsync<Http2ConnectionErrorException>( await WaitForConnectionErrorAsyncDoNotCloseTransport<Http2ConnectionErrorException>(
ignoreNonGoAwayFrames: false, ignoreNonGoAwayFrames: false,
expectedLastStreamId: 1, expectedLastStreamId: 1,
Http2ErrorCode.STREAM_CLOSED, Http2ErrorCode.STREAM_CLOSED,
CoreStrings.FormatHttp2ErrorStreamClosed(finalFrameType, 1)); CoreStrings.FormatHttp2ErrorStreamClosed(finalFrameType, 1));
cts.Cancel(); closed = true;
await sendTask.DefaultTimeout(); await sendTask.DefaultTimeout();
_pair.Application.Output.Complete();
} }
[Fact] [Fact]