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:
parent
5db6394769
commit
6d375e9027
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue