Răsfoiți Sursa

Fix key comparison for more than 10 elements in AdaptiveCapacityDictionary (#35685)

Brennan 4 ani în urmă
părinte
comite
52de4ad8f1

+ 34 - 0
src/Http/Http/test/Features/QueryFeatureTests.cs

@@ -220,5 +220,39 @@ namespace Microsoft.AspNetCore.Http.Features
             Assert.Single(queryCollection);
             Assert.Equal(new[] { "[ 1 ]", "[ 2 ]" }, queryCollection["fields [todoItems]"]);
         }
+
+        [Fact]
+        public void CaseInsensitiveWithManyKeys()
+        {
+            // need to use over 10 keys to test dictionary storage code path
+            var features = new FeatureCollection();
+            features[typeof(IHttpRequestFeature)] = new HttpRequestFeature
+            {
+                QueryString = "?a=0&b=0&c=1&d=2&e=3&f=4&g=5&h=6&i=7&j=8&k=9&" +
+                    "key=1&Key=2&key=3&Key=4&KEy=5&KEY=6&kEY=7&KeY=8&kEy=9&keY=10"
+            };
+
+            var provider = new QueryFeature(features);
+
+            var queryCollection = provider.Query;
+
+            Assert.Equal(12, queryCollection.Count);
+            Assert.Equal(new[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" }, queryCollection["KEY"]);
+        }
+
+        [Fact]
+        public void CaseInsensitiveWithFewKeys()
+        {
+            // need to use less than 10 keys to test array storage code path
+            var features = new FeatureCollection();
+            features[typeof(IHttpRequestFeature)] = new HttpRequestFeature { QueryString = "?key=1&Key=2&key=3&Key=4&KEy=5" };
+
+            var provider = new QueryFeature(features);
+
+            var queryCollection = provider.Query;
+
+            Assert.Equal(1, queryCollection.Count);
+            Assert.Equal(new[] { "1", "2", "3", "4", "5" }, queryCollection["KEY"]);
+        }
     }
 }

+ 2 - 2
src/Shared/Dictionary/AdaptiveCapacityDictionary.cs

@@ -76,7 +76,7 @@ namespace Microsoft.AspNetCore.Internal
             }
             else
             {
-                _dictionaryStorage = new Dictionary<TKey, TValue>(capacity);
+                _dictionaryStorage = new Dictionary<TKey, TValue>(capacity, _comparer);
             }
         }
 
@@ -519,7 +519,7 @@ namespace Microsoft.AspNetCore.Internal
 
             if (capacity > DefaultArrayThreshold)
             {
-                _dictionaryStorage = new Dictionary<TKey, TValue>(capacity);
+                _dictionaryStorage = new Dictionary<TKey, TValue>(capacity, _comparer);
                 foreach (var item in _arrayStorage)
                 {
                     _dictionaryStorage[item.Key] = item.Value;

+ 36 - 0
src/Shared/test/Shared.Tests/AdaptiveCapacityDictionaryTests.cs

@@ -1279,6 +1279,42 @@ namespace Microsoft.AspNetCore.Internal.Tests
             Assert.Equal("value3", storage[1].Value);
         }
 
+        [Fact]
+        public void UpgradeToDictionary_KeepsComparer()
+        {
+            // Arrange
+            var comparer = StringComparer.OrdinalIgnoreCase;
+            var dict = new AdaptiveCapacityDictionary<string, object>(StringComparer.OrdinalIgnoreCase);
+            for (var i = 0; i < 11; i++)
+            {
+                dict[i.ToString()] = i;
+            }
+
+            Assert.NotNull(dict._dictionaryStorage);
+            Assert.Equal(comparer, dict._dictionaryStorage.Comparer);
+
+            dict["K"] = 1;
+            dict["k"] = 2;
+
+            Assert.Equal(2, dict["K"]);
+        }
+
+        [Fact]
+        public void StartAsDictionary_UsesComparer()
+        {
+            // Arrange
+            var comparer = StringComparer.OrdinalIgnoreCase;
+            var dict = new AdaptiveCapacityDictionary<string, object>(11, StringComparer.OrdinalIgnoreCase);
+
+            Assert.NotNull(dict._dictionaryStorage);
+            Assert.Equal(comparer, dict._dictionaryStorage.Comparer);
+
+            dict["K"] = 1;
+            dict["k"] = 2;
+
+            Assert.Equal(2, dict["K"]);
+        }
+
         private void AssertEmptyArrayStorage(AdaptiveCapacityDictionary<string, string> value)
         {
             Assert.Same(Array.Empty<KeyValuePair<string, object?>>(), value._arrayStorage);