Wait for reads before advancing clock in Http2TimeoutTests (#3090)

Prior to this change, HTTP/2 read rate limit tests would fail when the stalled read started after the test started advancing the clock.
This commit is contained in:
Stephen Halter 2018-11-13 11:33:48 -08:00 committed by GitHub
parent 5db6394769
commit 6d375e9027
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 20 deletions

View File

@ -100,6 +100,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
new KeyValuePair<string, string>("g", _4kHeaderValue),
};
protected static IEnumerable<KeyValuePair<string, string>> ReadRateRequestHeaders(int expectedBytes) => new[]
{
new KeyValuePair<string, string>(HeaderNames.Method, "POST"),
new KeyValuePair<string, string>(HeaderNames.Path, "/" + expectedBytes),
new KeyValuePair<string, string>(HeaderNames.Scheme, "http"),
new KeyValuePair<string, string>(HeaderNames.Authority, "localhost:80"),
};
protected static readonly byte[] _helloBytes = Encoding.ASCII.GetBytes("hello");
protected static readonly byte[] _worldBytes = Encoding.ASCII.GetBytes("world");
protected static readonly byte[] _helloWorldBytes = Encoding.ASCII.GetBytes("hello, world");
@ -137,6 +145,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
protected readonly RequestDelegate _waitForAbortApplication;
protected readonly RequestDelegate _waitForAbortFlushingApplication;
protected readonly RequestDelegate _waitForAbortWithDataApplication;
protected readonly RequestDelegate _readRateApplication;
protected readonly RequestDelegate _echoMethod;
protected readonly RequestDelegate _echoHost;
protected readonly RequestDelegate _echoPath;
@ -315,6 +324,26 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_runningStreams[streamIdFeature.StreamId].TrySetResult(null);
};
_readRateApplication = async context =>
{
var expectedBytes = int.Parse(context.Request.Path.Value.Substring(1));
var buffer = new byte[Http2PeerSettings.MinAllowedMaxFrameSize];
var received = 0;
while (received < expectedBytes)
{
received += await context.Request.Body.ReadAsync(buffer, 0, buffer.Length);
}
var stalledReadTask = context.Request.Body.ReadAsync(buffer, 0, buffer.Length);
// Write to the response so the test knows the app started the stalled read.
await context.Response.Body.WriteAsync(new byte[1], 0, 1);
await stalledReadTask;
};
_echoMethod = context =>
{
context.Response.Headers["Method"] = context.Request.Method;

View File

@ -563,10 +563,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_timeoutControl.Initialize(mockSystemClock.UtcNow);
await InitializeConnectionAsync(_echoApplication);
await InitializeConnectionAsync(_readRateApplication);
// _helloWorldBytes is 12 bytes, and 12 bytes / 240 bytes/sec = .05 secs which is far below the grace period.
await StartStreamAsync(1, _browserRequestHeaders, endStream: false);
await StartStreamAsync(1, ReadRateRequestHeaders(_helloWorldBytes.Length), endStream: false);
await SendDataAsync(1, _helloWorldBytes, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
@ -575,7 +575,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
withLength: _helloWorldBytes.Length,
withLength: 1,
withFlags: (byte)Http2DataFrameFlags.NONE,
withStreamId: 1);
@ -612,10 +612,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_timeoutControl.Initialize(mockSystemClock.UtcNow);
await InitializeConnectionAsync(_echoApplication);
await InitializeConnectionAsync(_readRateApplication);
// _maxData is 16 KiB, and 16 KiB / 240 bytes/sec ~= 68 secs which is far above the grace period.
await StartStreamAsync(1, _browserRequestHeaders, endStream: false);
await StartStreamAsync(1, ReadRateRequestHeaders(_maxData.Length), endStream: false);
await SendDataAsync(1, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
@ -624,7 +624,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
withLength: _maxData.Length,
withLength: 1,
withFlags: (byte)Http2DataFrameFlags.NONE,
withStreamId: 1);
@ -665,10 +665,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_timeoutControl.Initialize(mockSystemClock.UtcNow);
await InitializeConnectionAsync(_echoApplication);
await InitializeConnectionAsync(_readRateApplication);
// _maxData is 16 KiB, and 16 KiB / 240 bytes/sec ~= 68 secs which is far above the grace period.
await StartStreamAsync(1, _browserRequestHeaders, endStream: false);
await StartStreamAsync(1, ReadRateRequestHeaders(_maxData.Length), endStream: false);
await SendDataAsync(1, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
@ -677,11 +677,11 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
withLength: _maxData.Length,
withLength: 1,
withFlags: (byte)Http2DataFrameFlags.NONE,
withStreamId: 1);
await StartStreamAsync(3, _browserRequestHeaders, endStream: false);
await StartStreamAsync(3, ReadRateRequestHeaders(_maxData.Length), endStream: false);
await SendDataAsync(3, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
@ -689,7 +689,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
withLength: _maxData.Length,
withLength: 1,
withFlags: (byte)Http2DataFrameFlags.NONE,
withStreamId: 3);
@ -734,10 +734,10 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
_timeoutControl.Initialize(mockSystemClock.UtcNow);
await InitializeConnectionAsync(_echoApplication);
await InitializeConnectionAsync(_readRateApplication);
// _maxData is 16 KiB, and 16 KiB / 240 bytes/sec ~= 68 secs which is far above the grace period.
await StartStreamAsync(1, _browserRequestHeaders, endStream: false);
await StartStreamAsync(1, ReadRateRequestHeaders(_maxData.Length), endStream: false);
await SendDataAsync(1, _maxData, endStream: true);
await ExpectAsync(Http2FrameType.HEADERS,
@ -746,7 +746,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withStreamId: 1);
await ExpectAsync(Http2FrameType.DATA,
withLength: _maxData.Length,
withLength: 1,
withFlags: (byte)Http2DataFrameFlags.NONE,
withStreamId: 1);
@ -755,7 +755,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withFlags: (byte)Http2DataFrameFlags.END_STREAM,
withStreamId: 1);
await StartStreamAsync(3, _browserRequestHeaders, endStream: false);
await StartStreamAsync(3, ReadRateRequestHeaders(_maxData.Length), endStream: false);
await SendDataAsync(3, _maxData, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
@ -763,7 +763,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
withLength: _maxData.Length,
withLength: 1,
withFlags: (byte)Http2DataFrameFlags.NONE,
withStreamId: 3);
@ -819,7 +819,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
else
{
await _echoApplication(context);
await _readRateApplication(context);
}
});
@ -830,7 +830,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
}
await SendDataAsync(1, _maxData, endStream: true);
await StartStreamAsync(3, _browserRequestHeaders, endStream: false);
await StartStreamAsync(3, ReadRateRequestHeaders(_helloWorldBytes.Length), endStream: false);
await SendDataAsync(3, _helloWorldBytes, endStream: false);
await ExpectAsync(Http2FrameType.HEADERS,
@ -838,7 +838,7 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withFlags: (byte)Http2HeadersFrameFlags.END_HEADERS,
withStreamId: 3);
await ExpectAsync(Http2FrameType.DATA,
withLength: _helloWorldBytes.Length,
withLength: 1,
withFlags: (byte)Http2DataFrameFlags.NONE,
withStreamId: 3);
@ -859,11 +859,14 @@ namespace Microsoft.AspNetCore.Server.Kestrel.Core.Tests
withFlags: (byte)Http2DataFrameFlags.END_STREAM,
withStreamId: 1);
await ExpectAsync(Http2FrameType.WINDOW_UPDATE,
var updateFrame = await ExpectAsync(Http2FrameType.WINDOW_UPDATE,
withLength: 4,
withFlags: (byte)Http2DataFrameFlags.NONE,
withStreamId: 0);
var expectedUpdateSize = ((framesConnectionInWindow / 2) + 1) * _maxData.Length + _helloWorldBytes.Length;
Assert.Equal(expectedUpdateSize, updateFrame.WindowUpdateSizeIncrement);
AdvanceClock(limits.MinRequestBodyDataRate.GracePeriod);
_mockTimeoutHandler.Verify(h => h.OnTimeout(It.IsAny<TimeoutReason>()), Times.Never);