Skip to content
This repository has been archived by the owner on Dec 18, 2018. It is now read-only.

WIP: Convert non-serializable data to dictionary lookup #2520

Closed
wants to merge 8 commits into from
20 changes: 13 additions & 7 deletions test/Kestrel.Core.Tests/Http1ConnectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,18 +259,22 @@ public async Task ThrowsWhenOnStartingIsSetAfterResponseStarted()
}

[Theory]
[MemberData(nameof(MinDataRateData))]
public void ConfiguringIHttpMinRequestBodyDataRateFeatureSetsMinRequestBodyDataRate(MinDataRate minDataRate)
[MemberData(nameof(MinDataRateDataNames))]
public void ConfiguringIHttpMinRequestBodyDataRateFeatureSetsMinRequestBodyDataRate(string minDataRateDataName)
{
var minDataRate = MinDataRateData[minDataRateDataName];

((IFeatureCollection)_http1Connection).Get<IHttpMinRequestBodyDataRateFeature>().MinDataRate = minDataRate;

Assert.Same(minDataRate, _http1Connection.MinRequestBodyDataRate);
}

[Theory]
[MemberData(nameof(MinDataRateData))]
public void ConfiguringIHttpMinResponseDataRateFeatureSetsMinResponseDataRate(MinDataRate minDataRate)
[MemberData(nameof(MinDataRateDataNames))]
public void ConfiguringIHttpMinResponseDataRateFeatureSetsMinResponseDataRate(string minDataRateDataName)
{
var minDataRate = MinDataRateData[minDataRateDataName];

((IFeatureCollection)_http1Connection).Get<IHttpMinResponseDataRateFeature>().MinDataRate = minDataRate;

Assert.Same(minDataRate, _http1Connection.MinResponseDataRate);
Expand Down Expand Up @@ -970,10 +974,12 @@ public static TheoryData<string> QueryStringWithNullCharData
TimeSpan.Zero
};

public static TheoryData<MinDataRate> MinDataRateData => new TheoryData<MinDataRate>
public static IEnumerable<object[]> MinDataRateDataNames => MinDataRateData.Keys.Select(key => new object[] { key });

public static IDictionary<string, MinDataRate> MinDataRateData => new Dictionary<string, MinDataRate>
{
null,
new MinDataRate(bytesPerSecond: 1, gracePeriod: TimeSpan.MaxValue)
{ "Null", null },
{ "OneBytePerSecond", new MinDataRate(bytesPerSecond: 1, gracePeriod: TimeSpan.MaxValue) },
};

private class RequestHeadersWrapper : IHeaderDictionary
Expand Down
70 changes: 46 additions & 24 deletions test/Kestrel.Core.Tests/Http2ConnectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1076,23 +1076,27 @@ public Task HEADERS_Received_HeaderBlockContainsResponsePseudoHeaderField_Stream
}

[Theory]
[MemberData(nameof(DuplicatePseudoHeaderFieldData))]
public Task HEADERS_Received_HeaderBlockContainsDuplicatePseudoHeaderField_StreamError(IEnumerable<KeyValuePair<string, string>> headers)
[MemberData(nameof(DuplicatePseudoHeaderFieldDataNames))]
public Task HEADERS_Received_HeaderBlockContainsDuplicatePseudoHeaderField_StreamError(string headersName)
{
var headers = DuplicatePseudoHeaderFieldData[headersName];
return HEADERS_Received_InvalidHeaderFields_StreamError(headers, expectedErrorMessage: CoreStrings.Http2ErrorDuplicatePseudoHeaderField);
}

[Theory]
[MemberData(nameof(MissingPseudoHeaderFieldData))]
public Task HEADERS_Received_HeaderBlockDoesNotContainMandatoryPseudoHeaderField_StreamError(IEnumerable<KeyValuePair<string, string>> headers)
[MemberData(nameof(MissingPseudoHeaderFieldDataNames))]
public Task HEADERS_Received_HeaderBlockDoesNotContainMandatoryPseudoHeaderField_StreamError(string headersName)
{
var headers = MissingPseudoHeaderFieldData[headersName];
return HEADERS_Received_InvalidHeaderFields_StreamError(headers, expectedErrorMessage: CoreStrings.Http2ErrorMissingMandatoryPseudoHeaderFields);
}

[Theory]
[MemberData(nameof(ConnectMissingPseudoHeaderFieldData))]
public async Task HEADERS_Received_HeaderBlockDoesNotContainMandatoryPseudoHeaderField_MethodIsCONNECT_NoError(IEnumerable<KeyValuePair<string, string>> headers)
[MemberData(nameof(ConnectMissingPseudoHeaderFieldDataNames))]
public async Task HEADERS_Received_HeaderBlockDoesNotContainMandatoryPseudoHeaderField_MethodIsCONNECT_NoError(string headersName)
{
var headers = ConnectMissingPseudoHeaderFieldData[headersName];

await InitializeConnectionAsync(_noopApplication);

await SendHeadersAsync(1, Http2HeadersFrameFlags.END_HEADERS | Http2HeadersFrameFlags.END_STREAM, headers);
Expand All @@ -1110,9 +1114,11 @@ await ExpectAsync(Http2FrameType.DATA,
}

[Theory]
[MemberData(nameof(PseudoHeaderFieldAfterRegularHeadersData))]
public Task HEADERS_Received_HeaderBlockContainsPseudoHeaderFieldAfterRegularHeaders_StreamError(IEnumerable<KeyValuePair<string, string>> headers)
[MemberData(nameof(PseudoHeaderFieldAfterRegularHeadersDataNames))]
public Task HEADERS_Received_HeaderBlockContainsPseudoHeaderFieldAfterRegularHeaders_StreamError(string headersName)
{
var headers = PseudoHeaderFieldAfterRegularHeadersData[headersName];

return HEADERS_Received_InvalidHeaderFields_StreamError(headers, expectedErrorMessage: CoreStrings.Http2ErrorPseudoHeaderFieldAfterRegularHeaders);
}

Expand Down Expand Up @@ -2140,9 +2146,11 @@ await WaitForConnectionErrorAsync<Http2ConnectionErrorException>(
}

[Theory]
[MemberData(nameof(MissingPseudoHeaderFieldData))]
public async Task CONTINUATION_Received_HeaderBlockDoesNotContainMandatoryPseudoHeaderField_StreamError(IEnumerable<KeyValuePair<string, string>> headers)
[MemberData(nameof(MissingPseudoHeaderFieldDataNames))]
public async Task CONTINUATION_Received_HeaderBlockDoesNotContainMandatoryPseudoHeaderField_StreamError(string headersName)
{
var headers = MissingPseudoHeaderFieldData[headersName];

await InitializeConnectionAsync(_noopApplication);

Assert.True(await SendHeadersAsync(1, Http2HeadersFrameFlags.NONE, headers));
Expand All @@ -2164,9 +2172,11 @@ await WaitForConnectionErrorAsync<Http2ConnectionErrorException>(
}

[Theory]
[MemberData(nameof(ConnectMissingPseudoHeaderFieldData))]
public async Task CONTINUATION_Received_HeaderBlockDoesNotContainMandatoryPseudoHeaderField_MethodIsCONNECT_NoError(IEnumerable<KeyValuePair<string, string>> headers)
[MemberData(nameof(ConnectMissingPseudoHeaderFieldDataNames))]
public async Task CONTINUATION_Received_HeaderBlockDoesNotContainMandatoryPseudoHeaderField_MethodIsCONNECT_NoError(string headersName)
{
var headers = ConnectMissingPseudoHeaderFieldData[headersName];

await InitializeConnectionAsync(_noopApplication);

await SendHeadersAsync(1, Http2HeadersFrameFlags.END_STREAM, headers);
Expand Down Expand Up @@ -2935,11 +2945,14 @@ public static TheoryData<byte[]> UpperCaseHeaderNameData
}
}

public static TheoryData<IEnumerable<KeyValuePair<string, string>>> DuplicatePseudoHeaderFieldData
public static IEnumerable<object[]> DuplicatePseudoHeaderFieldDataNames =>
DuplicatePseudoHeaderFieldData.Keys.Select(key => new object[] { key });

public static IDictionary<string, IEnumerable<KeyValuePair<string, string>>> DuplicatePseudoHeaderFieldData
{
get
{
var data = new TheoryData<IEnumerable<KeyValuePair<string, string>>>();
var data = new Dictionary<string, IEnumerable<KeyValuePair<string, string>>>();
var requestHeaders = new[]
{
new KeyValuePair<string, string>(":method", "GET"),
Expand All @@ -2951,18 +2964,21 @@ public static TheoryData<IEnumerable<KeyValuePair<string, string>>> DuplicatePse
foreach (var headerField in requestHeaders)
{
var headers = requestHeaders.Concat(new[] { new KeyValuePair<string, string>(headerField.Key, headerField.Value) });
data.Add(headers);
data.Add(headerField.Key, headers);
}

return data;
}
}

public static TheoryData<IEnumerable<KeyValuePair<string, string>>> MissingPseudoHeaderFieldData
public static IEnumerable<object[]> MissingPseudoHeaderFieldDataNames =>
MissingPseudoHeaderFieldData.Keys.Select(key => new object[] { key });

public static IDictionary<string, IEnumerable<KeyValuePair<string, string>>> MissingPseudoHeaderFieldData
{
get
{
var data = new TheoryData<IEnumerable<KeyValuePair<string, string>>>();
var data = new Dictionary<string, IEnumerable<KeyValuePair<string, string>>>();
var requestHeaders = new[]
{
new KeyValuePair<string, string>(":method", "GET"),
Expand All @@ -2973,18 +2989,21 @@ public static TheoryData<IEnumerable<KeyValuePair<string, string>>> MissingPseud
foreach (var headerField in requestHeaders)
{
var headers = requestHeaders.Except(new[] { headerField });
data.Add(headers);
data.Add(headerField.Key, headers);
}

return data;
}
}

public static TheoryData<IEnumerable<KeyValuePair<string, string>>> ConnectMissingPseudoHeaderFieldData
public static IEnumerable<object[]> ConnectMissingPseudoHeaderFieldDataNames =>
ConnectMissingPseudoHeaderFieldData.Keys.Select(key => new object[] { key });

public static IDictionary<string, IEnumerable<KeyValuePair<string, string>>> ConnectMissingPseudoHeaderFieldData
{
get
{
var data = new TheoryData<IEnumerable<KeyValuePair<string, string>>>();
var data = new Dictionary<string, IEnumerable<KeyValuePair<string, string>>>();
var methodHeader = new[] { new KeyValuePair<string, string>(":method", "CONNECT") };
var requestHeaders = new[]
{
Expand All @@ -2996,18 +3015,21 @@ public static TheoryData<IEnumerable<KeyValuePair<string, string>>> ConnectMissi
foreach (var headerField in requestHeaders)
{
var headers = methodHeader.Concat(requestHeaders.Except(new[] { headerField }));
data.Add(headers);
data.Add(headerField.Key, headers);
}

return data;
}
}

public static TheoryData<IEnumerable<KeyValuePair<string, string>>> PseudoHeaderFieldAfterRegularHeadersData
public static IEnumerable<object[]> PseudoHeaderFieldAfterRegularHeadersDataNames =>
PseudoHeaderFieldAfterRegularHeadersData.Keys.Select(key => new object[] { key });

public static IDictionary<string, IEnumerable<KeyValuePair<string, string>>> PseudoHeaderFieldAfterRegularHeadersData
{
get
{
var data = new TheoryData<IEnumerable<KeyValuePair<string, string>>>();
var data = new Dictionary<string, IEnumerable<KeyValuePair<string, string>>>();
var requestHeaders = new[]
{
new KeyValuePair<string, string>(":method", "GET"),
Expand All @@ -3020,7 +3042,7 @@ public static TheoryData<IEnumerable<KeyValuePair<string, string>>> PseudoHeader
foreach (var headerField in requestHeaders.Where(h => h.Key.StartsWith(":")))
{
var headers = requestHeaders.Except(new[] { headerField }).Concat(new[] { headerField });
data.Add(headers);
data.Add(headerField.Key, headers);
}

return data;
Expand Down
38 changes: 25 additions & 13 deletions test/Kestrel.Core.Tests/KestrelServerLimitsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Xunit;

Expand Down Expand Up @@ -154,9 +156,11 @@ public void KeepAliveTimeoutDefault()
}

[Theory]
[MemberData(nameof(TimeoutValidData))]
public void KeepAliveTimeoutValid(TimeSpan value)
[MemberData(nameof(TimeoutValidDataNames))]
public void KeepAliveTimeoutValid(string timeoutName)
{
var value = TimeoutValidData[timeoutName];

Assert.Equal(value, new KestrelServerLimits { KeepAliveTimeout = value }.KeepAliveTimeout);
}

Expand All @@ -167,9 +171,11 @@ public void KeepAliveTimeoutCanBeSetToInfinite()
}

[Theory]
[MemberData(nameof(TimeoutInvalidData))]
public void KeepAliveTimeoutInvalid(TimeSpan value)
[MemberData(nameof(TimeoutInvalidDataNames))]
public void KeepAliveTimeoutInvalid(string timeoutName)
{
var value = TimeoutInvalidData[timeoutName];

var exception = Assert.Throws<ArgumentOutOfRangeException>(() => new KestrelServerLimits { KeepAliveTimeout = value });

Assert.Equal("value", exception.ParamName);
Expand All @@ -183,9 +189,11 @@ public void RequestHeadersTimeoutDefault()
}

[Theory]
[MemberData(nameof(TimeoutValidData))]
public void RequestHeadersTimeoutValid(TimeSpan value)
[MemberData(nameof(TimeoutValidDataNames))]
public void RequestHeadersTimeoutValid(string timeoutName)
{
var value = TimeoutValidData[timeoutName];

Assert.Equal(value, new KestrelServerLimits { RequestHeadersTimeout = value }.RequestHeadersTimeout);
}

Expand Down Expand Up @@ -308,17 +316,21 @@ public void MinResponseBodyDataRateDefault()
Assert.Equal(TimeSpan.FromSeconds(5), new KestrelServerLimits().MinResponseDataRate.GracePeriod);
}

public static TheoryData<TimeSpan> TimeoutValidData => new TheoryData<TimeSpan>
public static IEnumerable<object[]> TimeoutValidDataNames => TimeoutValidData.Keys.Select(key => new object[] { key });

public static IDictionary<string, TimeSpan> TimeoutValidData => new Dictionary<string, TimeSpan>
{
TimeSpan.FromTicks(1),
TimeSpan.MaxValue,
{ "OneTick", TimeSpan.FromTicks(1) },
{ "MaxValue", TimeSpan.MaxValue },
};

public static TheoryData<TimeSpan> TimeoutInvalidData => new TheoryData<TimeSpan>
public static IEnumerable<object[]> TimeoutInvalidDataNames => TimeoutInvalidData.Keys.Select(key => new object[] { key });

public static Dictionary<string, TimeSpan> TimeoutInvalidData => new Dictionary<string, TimeSpan>
{
TimeSpan.MinValue,
TimeSpan.FromTicks(-1),
TimeSpan.Zero
{ "MinValue", TimeSpan.MinValue },
{ "NegativeOneTick", TimeSpan.FromTicks(-1) },
{ "Zero", TimeSpan.Zero },
};
}
}
34 changes: 22 additions & 12 deletions test/Kestrel.Core.Tests/MinDataRateTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Infrastructure;
using Xunit;

Expand Down Expand Up @@ -30,34 +32,42 @@ public void BytesPerSecondInvalid(double value)
}

[Theory]
[MemberData(nameof(GracePeriodValidData))]
public void GracePeriodValid(TimeSpan value)
[MemberData(nameof(GracePeriodValidDataNames))]
public void GracePeriodValid(string gracePeriodName)
{
var value = GracePeriodValidData[gracePeriodName];

Assert.Equal(value, new MinDataRate(bytesPerSecond: 1, gracePeriod: value).GracePeriod);
}

[Theory]
[MemberData(nameof(GracePeriodInvalidData))]
public void GracePeriodInvalid(TimeSpan value)
[MemberData(nameof(GracePeriodInvalidDataNames))]
public void GracePeriodInvalid(string gracePeriodName)
{
var value = GracePeriodInvalidData[gracePeriodName];

var exception = Assert.Throws<ArgumentOutOfRangeException>(() => new MinDataRate(bytesPerSecond: 1, gracePeriod: value));

Assert.Equal("gracePeriod", exception.ParamName);
Assert.StartsWith(CoreStrings.FormatMinimumGracePeriodRequired(Heartbeat.Interval.TotalSeconds), exception.Message);
}

public static TheoryData<TimeSpan> GracePeriodValidData => new TheoryData<TimeSpan>
public static IEnumerable<object[]> GracePeriodValidDataNames => GracePeriodValidData.Keys.Select(key => new object[] { key });

public static IDictionary<string, TimeSpan> GracePeriodValidData => new Dictionary<string, TimeSpan>
{
Heartbeat.Interval + TimeSpan.FromTicks(1),
TimeSpan.MaxValue
{ "HeartbeatIntervalPlusOneTick", Heartbeat.Interval + TimeSpan.FromTicks(1) },
{ "MaxValue", TimeSpan.MaxValue },
};

public static TheoryData<TimeSpan> GracePeriodInvalidData => new TheoryData<TimeSpan>
public static IEnumerable<object[]> GracePeriodInvalidDataNames => GracePeriodInvalidData.Keys.Select(key => new object[] { key });

public static IDictionary<string, TimeSpan> GracePeriodInvalidData => new Dictionary<string, TimeSpan>
{
TimeSpan.MinValue,
TimeSpan.FromTicks(-1),
TimeSpan.Zero,
Heartbeat.Interval
{ "MinValue", TimeSpan.MinValue },
{ "NegativeOneTicks", TimeSpan.FromTicks(-1) },
{ "Zero", TimeSpan.Zero },
{ "HeartbeatInterval", Heartbeat.Interval },
};
}
}