Skip to content

Commit 4987f4b

Browse files
committed
Fix AdaptiveCapacityDictionary assert with 11 elements dotnet#34307
1 parent 12c57a5 commit 4987f4b

File tree

4 files changed

+32
-2
lines changed

4 files changed

+32
-2
lines changed

src/Http/Http/src/Internal/RequestCookieCollection.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ internal static RequestCookieCollection ParseInternal(StringValues values, bool
7070
{
7171
return Empty;
7272
}
73-
var collection = new RequestCookieCollection(values.Count);
73+
74+
// Do not set the collection capacity based on StringValues.Count, the Cookie header is supposed to be a single combine value.
75+
var collection = new RequestCookieCollection();
7476
var store = collection.Store!;
7577

7678
if (CookieHeaderParserShared.TryParseValues(values, store, enableCookieNameEncoding, supportsMultipleValues: true))

src/Http/Http/test/RequestCookiesCollectionTests.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,13 @@ public void AppContextSwitchUnEscapesKeysAndValues(string input, string expected
3838
Assert.Equal(expectedKey, cookies.Keys.Single());
3939
Assert.Equal(expectedValue, cookies[expectedKey]);
4040
}
41+
42+
[Fact]
43+
public void ParseManyCookies()
44+
{
45+
var cookies = RequestCookieCollection.Parse(new StringValues(new[] { "a=a", "b=b", "c=c", "d=d", "e=e", "f=f", "g=g", "h=h", "i=i", "j=j", "k=k", "l=l" }));
46+
47+
Assert.Equal(12, cookies.Count);
48+
}
4149
}
4250
}

src/Shared/Dictionary/AdaptiveCapacityDictionary.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,6 @@ public AdaptiveCapacityDictionary(int capacity, IEqualityComparer<TKey> comparer
7777
else
7878
{
7979
_dictionaryStorage = new Dictionary<TKey, TValue>(capacity);
80-
_arrayStorage = Array.Empty<KeyValuePair<TKey, TValue>>();
8180
}
8281
}
8382

@@ -95,6 +94,7 @@ internal AdaptiveCapacityDictionary(IEnumerable<KeyValuePair<TKey, TValue>> valu
9594
{
9695
_comparer = comparer ?? EqualityComparer<TKey>.Default;
9796

97+
Debug.Assert(capacity <= DefaultArrayThreshold);
9898
_arrayStorage = new KeyValuePair<TKey, TValue>[capacity];
9999

100100
foreach (var kvp in values)

src/Shared/test/Shared.Tests/AdaptiveCapacityDictionaryTests.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System;
55
using System.Collections.Generic;
6+
using System.Globalization;
67
using System.Linq;
78
using Microsoft.AspNetCore.Internal;
89
using Microsoft.AspNetCore.Testing;
@@ -100,6 +101,25 @@ public void CreateFromIEnumerableStringValuePair_CopiesValues()
100101
kvp => { Assert.Equal("Middle Name", kvp.Key); Assert.Equal("Bob", kvp.Value); });
101102
}
102103

104+
[Fact]
105+
public void CreateWithCapacityOverDefaultLimit()
106+
{
107+
// The default threshold between array and dictionary is 10. If we created one over that limit it should go directly to a dictionary.
108+
var dict = new AdaptiveCapacityDictionary<string, string>(capacity: 12, StringComparer.OrdinalIgnoreCase);
109+
110+
Assert.Null(dict._arrayStorage);
111+
Assert.NotNull(dict._dictionaryStorage);
112+
113+
for (var i = 0; i < 12; i++)
114+
{
115+
dict[i.ToString(CultureInfo.InvariantCulture)] = i.ToString(CultureInfo.InvariantCulture);
116+
}
117+
118+
Assert.Null(dict._arrayStorage);
119+
Assert.NotNull(dict._dictionaryStorage);
120+
Assert.Equal(12, dict.Count);
121+
}
122+
103123
[Fact]
104124
public void CreateFromIEnumerableKeyValuePair_ThrowsExceptionForDuplicateKey()
105125
{

0 commit comments

Comments
 (0)