File: AdaptiveCapacityDictionaryTests.cs
Web Access
Project: src\src\Shared\test\Shared.Tests\Microsoft.AspNetCore.Shared.Tests.csproj (Microsoft.AspNetCore.Shared.Tests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.AspNetCore.Internal;
using Microsoft.AspNetCore.InternalTesting;
using Xunit;
 
namespace Microsoft.AspNetCore.Internal.Tests;
 
public class AdaptiveCapacityDictionaryTests
{
    [Fact]
    public void DefaultCtor()
    {
        // Arrange
        // Act
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Assert
        Assert.Empty(dict);
        Assert.Empty(dict._arrayStorage);
        Assert.Null(dict._dictionaryStorage);
    }
 
    [Fact]
    public void CreateFromNull()
    {
        // Arrange
        // Act
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Assert
        Assert.Empty(dict);
        Assert.Empty(dict._arrayStorage);
        Assert.Null(dict._dictionaryStorage);
    }
 
    [Fact]
    public void CreateWithCapacityOverDefaultLimit()
    {
        // The default threshold between array and dictionary is 10. If we created one over that limit it should go directly to a dictionary.
        var dict = new AdaptiveCapacityDictionary<string, string>(capacity: 12, StringComparer.OrdinalIgnoreCase);
 
        Assert.Null(dict._arrayStorage);
        Assert.NotNull(dict._dictionaryStorage);
 
        for (var i = 0; i < 12; i++)
        {
            dict[i.ToString(CultureInfo.InvariantCulture)] = i.ToString(CultureInfo.InvariantCulture);
        }
 
        Assert.Null(dict._arrayStorage);
        Assert.NotNull(dict._dictionaryStorage);
        Assert.Equal(12, dict.Count);
    }
 
    [Fact]
    public void CreateFromIEnumerableKeyValuePair_ThrowsExceptionForDuplicateKey()
    {
        // Arrange, Act & Assert
        ExceptionAssert.ThrowsArgument(
            () => new AdaptiveCapacityDictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
            {
                    {  "name", "Billy" },
                    {  "Name", "Joey" }
            },
            "key",
            $"An element with the key 'Name' already exists in the {nameof(AdaptiveCapacityDictionary<string, object?>)}.");
    }
 
    [Fact]
    public void Comparer_IsOrdinalIgnoreCase()
    {
        // Arrange
        // Act
        var dict = new AdaptiveCapacityDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
 
        // Assert
        Assert.Same(StringComparer.OrdinalIgnoreCase, dict.Comparer);
    }
 
    // Our comparer is hardcoded to be IsReadOnly==false no matter what.
    [Fact]
    public void IsReadOnly_False()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>();
 
        // Act
        var result = ((ICollection<KeyValuePair<string, object?>>)dict).IsReadOnly;
 
        // Assert
        Assert.False(result);
    }
 
    [Fact]
    public void IndexGet_EmptyStringIsAllowed()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        var value = dict[""];
 
        // Assert
        Assert.Null(value);
    }
 
    [Fact]
    public void IndexGet_EmptyStorage_ReturnsNull()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        var value = dict["key"];
 
        // Assert
        Assert.Null(value);
    }
 
    [Fact]
    public void IndexGet_ArrayStorage_NoMatch_ReturnsNull()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>();
        dict.Add("age", 30);
 
        // Act
        var value = dict["key"];
 
        // Assert
        Assert.Null(value);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void IndexGet_ListStorage_Match_ReturnsValue()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        var value = dict["key"];
 
        // Assert
        Assert.Equal("value", value);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void IndexGet_ListStorage_MatchIgnoreCase_ReturnsValue()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>(StringComparer.OrdinalIgnoreCase)
            {
                { "key", "value" },
            };
 
        // Act
        var value = dict["kEy"];
 
        // Assert
        Assert.Equal("value", value);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void IndexSet_EmptyStringIsAllowed()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        dict[""] = "foo";
 
        // Assert
        Assert.Equal("foo", dict[""]);
    }
 
    [Fact]
    public void IndexSet_EmptyStorage_UpgradesToList()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>();
 
        // Act
        dict["key"] = "value";
 
        // Assert
        Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void IndexSet_ListStorage_NoMatch_AddsValue()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "age", 30 },
            };
 
        // Act
        dict["key"] = "value";
 
        // Assert
        Assert.Collection(
            dict.OrderBy(kvp => kvp.Key),
            kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); },
            kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void IndexSet_ListStorage_Match_SetsValue()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        dict["key"] = "value";
 
        // Assert
        Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void IndexSet_ListStorage_MatchIgnoreCase_SetsValue()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        dict["key"] = "value";
 
        // Assert
        Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Count_EmptyStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        var count = dict.Count;
 
        // Assert
        Assert.Equal(0, count);
    }
 
    [Fact]
    public void Count_ListStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        var count = dict.Count;
 
        // Assert
        Assert.Equal(1, count);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Keys_EmptyStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>();
 
        // Act
        var keys = dict.Keys;
 
        // Assert
        Assert.Empty(keys);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Keys_ListStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        var keys = dict.Keys;
 
        // Assert
        Assert.Equal(new[] { "key" }, keys);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Values_EmptyStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>();
 
        // Act
        var values = dict.Values;
 
        // Assert
        Assert.Empty(values);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Values_ListStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        var values = dict.Values;
 
        // Assert
        Assert.Equal(new object[] { "value" }, values);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Add_EmptyStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>();
 
        // Act
        dict.Add("key", "value");
 
        // Assert
        Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Add_EmptyStringIsAllowed()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        dict.Add("", "foo");
 
        // Assert
        Assert.Equal("foo", dict[""]);
    }
 
    [Fact]
    public void Add_ListStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "age", 30 },
            };
 
        // Act
        dict.Add("key", "value");
 
        // Assert
        Assert.Collection(
            dict.OrderBy(kvp => kvp.Key),
            kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); },
            kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Add_DuplicateKey()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        var message = $"An element with the key 'key' already exists in the {nameof(AdaptiveCapacityDictionary<string, string>)}";
 
        // Act & Assert
        ExceptionAssert.ThrowsArgument(() => dict.Add("key", "value2"), "key", message);
 
        // Assert
        Assert.Collection(
            dict.OrderBy(kvp => kvp.Key),
            kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Add_DuplicateKey_CaseInsensitive()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>(StringComparer.OrdinalIgnoreCase)
            {
                { "key", "value" },
            };
 
        var message = $"An element with the key 'kEy' already exists in the {nameof(AdaptiveCapacityDictionary<string, string>)}";
 
        // Act & Assert
        ExceptionAssert.ThrowsArgument(() => dict.Add("kEy", "value2"), "key", message);
 
        // Assert
        Assert.Collection(
            dict.OrderBy(kvp => kvp.Key),
            kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Add_KeyValuePair()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "age", 30 },
            };
 
        // Act
        ((ICollection<KeyValuePair<string, object?>>)dict).Add(new KeyValuePair<string, object?>("key", "value"));
 
        // Assert
        Assert.Collection(
            dict.OrderBy(kvp => kvp.Key),
            kvp => { Assert.Equal("age", kvp.Key); Assert.Equal(30, kvp.Value); },
            kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Clear_EmptyStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        dict.Clear();
 
        // Assert
        Assert.Empty(dict);
    }
 
    [Fact]
    public void Clear_ListStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        dict.Clear();
 
        // Assert
        Assert.Empty(dict);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
        Assert.Null(dict._dictionaryStorage);
    }
 
    [Fact]
    public void Contains_ListStorage_KeyValuePair_True()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        var input = new KeyValuePair<string, object?>("key", "value");
 
        // Act
        var result = ((ICollection<KeyValuePair<string, object?>>)dict).Contains(input);
 
        // Assert
        Assert.True(result);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Contains_ListStory_KeyValuePair_True_CaseInsensitive()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>(StringComparer.OrdinalIgnoreCase)
            {
                { "key", "value" },
            };
 
        var input = new KeyValuePair<string, object?>("KEY", "value");
 
        // Act
        var result = ((ICollection<KeyValuePair<string, object?>>)dict).Contains(input);
 
        // Assert
        Assert.True(result);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Contains_ListStorage_KeyValuePair_False()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        var input = new KeyValuePair<string, object?>("other", "value");
 
        // Act
        var result = ((ICollection<KeyValuePair<string, object?>>)dict).Contains(input);
 
        // Assert
        Assert.False(result);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    // Value comparisons use the default equality comparer.
    [Fact]
    public void Contains_ListStorage_KeyValuePair_False_ValueComparisonIsDefault()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        var input = new KeyValuePair<string, object?>("key", "valUE");
 
        // Act
        var result = ((ICollection<KeyValuePair<string, object?>>)dict).Contains(input);
 
        // Assert
        Assert.False(result);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void ContainsKey_EmptyStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        var result = dict.ContainsKey("key");
 
        // Assert
        Assert.False(result);
    }
 
    [Fact]
    public void ContainsKey_EmptyStringIsAllowed()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        var result = dict.ContainsKey("");
 
        // Assert
        Assert.False(result);
    }
 
    [Fact]
    public void ContainsKey_ListStorage_False()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        var result = dict.ContainsKey("other");
 
        // Assert
        Assert.False(result);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void ContainsKey_ListStorage_True()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        var result = dict.ContainsKey("key");
 
        // Assert
        Assert.True(result);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void ContainsKey_ListStorage_True_CaseInsensitive()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>(StringComparer.OrdinalIgnoreCase)
            {
                { "key", "value" },
            };
 
        // Act
        var result = dict.ContainsKey("kEy");
 
        // Assert
        Assert.True(result);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void CopyTo()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        var array = new KeyValuePair<string, object?>[2];
 
        // Act
        ((ICollection<KeyValuePair<string, object?>>)dict).CopyTo(array, 1);
 
        // Assert
        Assert.Equal(
            new KeyValuePair<string, object?>[]
            {
                    default(KeyValuePair<string, object?>),
                    new KeyValuePair<string, object?>("key", "value")
            },
            array);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Remove_KeyValuePair_True()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        var input = new KeyValuePair<string, object?>("key", "value");
 
        // Act
        var result = ((ICollection<KeyValuePair<string, object?>>)dict).Remove(input);
 
        // Assert
        Assert.True(result);
        Assert.Empty(dict);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Remove_KeyValuePair_True_CaseInsensitive()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>(StringComparer.OrdinalIgnoreCase)
            {
                { "key", "value" },
            };
 
        var input = new KeyValuePair<string, object?>("KEY", "value");
 
        // Act
        var result = ((ICollection<KeyValuePair<string, object?>>)dict).Remove(input);
 
        // Assert
        Assert.True(result);
        Assert.Empty(dict);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Remove_KeyValuePair_False()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        var input = new KeyValuePair<string, object?>("other", "value");
 
        // Act
        var result = ((ICollection<KeyValuePair<string, object?>>)dict).Remove(input);
 
        // Assert
        Assert.False(result);
        Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    // Value comparisons use the default equality comparer.
    [Fact]
    public void Remove_KeyValuePair_False_ValueComparisonIsDefault()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        var input = new KeyValuePair<string, object?>("key", "valUE");
 
        // Act
        var result = ((ICollection<KeyValuePair<string, object?>>)dict).Remove(input);
 
        // Assert
        Assert.False(result);
        Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Remove_EmptyStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        var result = dict.Remove("key");
 
        // Assert
        Assert.False(result);
    }
 
    [Fact]
    public void Remove_EmptyStringIsAllowed()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        var result = dict.Remove("");
 
        // Assert
        Assert.False(result);
    }
 
    [Fact]
    public void Remove_ListStorage_False()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        var result = dict.Remove("other");
 
        // Assert
        Assert.False(result);
        Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Remove_ListStorage_True()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        var result = dict.Remove("key");
 
        // Assert
        Assert.True(result);
        Assert.Empty(dict);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Remove_ListStorage_True_CaseInsensitive()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>(StringComparer.OrdinalIgnoreCase)
            {
                { "key", "value" },
            };
 
        // Act
        var result = dict.Remove("kEy");
 
        // Assert
        Assert.True(result);
        Assert.Empty(dict);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Remove_KeyAndOutValue_EmptyStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        var result = dict.Remove("key", out var removedValue);
 
        // Assert
        Assert.False(result);
        Assert.Null(removedValue);
    }
 
    [Fact]
    public void Remove_KeyAndOutValue_EmptyStringIsAllowed()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        var result = dict.Remove("", out var removedValue);
 
        // Assert
        Assert.False(result);
        Assert.Null(removedValue);
    }
 
    [Fact]
    public void Remove_KeyAndOutValue_ListStorage_False()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        var result = dict.Remove("other", out var removedValue);
 
        // Assert
        Assert.False(result);
        Assert.Null(removedValue);
        Assert.Collection(dict, kvp => { Assert.Equal("key", kvp.Key); Assert.Equal("value", kvp.Value); });
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Remove_KeyAndOutValue_ListStorage_True()
    {
        // Arrange
        object value = "value";
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", value }
            };
 
        // Act
        var result = dict.Remove("key", out var removedValue);
 
        // Assert
        Assert.True(result);
        Assert.Same(value, removedValue);
        Assert.Empty(dict);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Remove_KeyAndOutValue_ListStorage_True_CaseInsensitive()
    {
        // Arrange
        object value = "value";
        var dict = new AdaptiveCapacityDictionary<string, object>(StringComparer.OrdinalIgnoreCase)
            {
                { "key", value }
            };
 
        // Act
        var result = dict.Remove("kEy", out var removedValue);
 
        // Assert
        Assert.True(result);
        Assert.Same(value, removedValue);
        Assert.Empty(dict);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Remove_KeyAndOutValue_ListStorage_KeyExists_First()
    {
        // Arrange
        object value = "value";
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", value },
                { "other", 5 },
                { "dotnet", "rocks" }
            };
 
        // Act
        var result = dict.Remove("key", out var removedValue);
 
        // Assert
        Assert.True(result);
        Assert.Same(value, removedValue);
        Assert.Equal(2, dict.Count);
        Assert.False(dict.ContainsKey("key"));
        Assert.True(dict.ContainsKey("other"));
        Assert.True(dict.ContainsKey("dotnet"));
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Remove_KeyAndOutValue_ListStorage_KeyExists_Middle()
    {
        // Arrange
        object value = "value";
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "other", 5 },
                { "key", value },
                { "dotnet", "rocks" }
            };
 
        // Act
        var result = dict.Remove("key", out var removedValue);
 
        // Assert
        Assert.True(result);
        Assert.Same(value, removedValue);
        Assert.Equal(2, dict.Count);
        Assert.False(dict.ContainsKey("key"));
        Assert.True(dict.ContainsKey("other"));
        Assert.True(dict.ContainsKey("dotnet"));
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void Remove_KeyAndOutValue_ListStorage_KeyExists_Last()
    {
        // Arrange
        object value = "value";
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "other", 5 },
                { "dotnet", "rocks" },
                { "key", value }
            };
 
        // Act
        var result = dict.Remove("key", out var removedValue);
 
        // Assert
        Assert.True(result);
        Assert.Same(value, removedValue);
        Assert.Equal(2, dict.Count);
        Assert.False(dict.ContainsKey("key"));
        Assert.True(dict.ContainsKey("other"));
        Assert.True(dict.ContainsKey("dotnet"));
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void TryAdd_EmptyStringIsAllowed()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        var result = dict.TryAdd("", "foo");
 
        // Assert
        Assert.True(result);
    }
 
    [Fact]
    public void TryAdd_EmptyStorage_CanAdd()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>();
 
        // Act
        var result = dict.TryAdd("key", "value");
 
        // Assert
        Assert.True(result);
        Assert.Collection(
            dict._arrayStorage,
            kvp => Assert.Equal(new KeyValuePair<string, object?>("key", "value"), kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp));
    }
 
    [Fact]
    public void TryAdd_ArrayStorage_CanAdd()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key0", "value0" },
            };
 
        // Act
        var result = dict.TryAdd("key1", "value1");
 
        // Assert
        Assert.True(result);
        Assert.Collection(
            dict._arrayStorage,
            kvp => Assert.Equal(new KeyValuePair<string, object?>("key0", "value0"), kvp),
            kvp => Assert.Equal(new KeyValuePair<string, object?>("key1", "value1"), kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp));
    }
 
    [Fact]
    public void TryAdd_ArrayStorage_DoesNotAddWhenKeyIsPresent()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key0", "value0" },
            };
 
        // Act
        var result = dict.TryAdd("key0", "value1");
 
        // Assert
        Assert.False(result);
        Assert.Collection(
            dict._arrayStorage,
            kvp => Assert.Equal(new KeyValuePair<string, object?>("key0", "value0"), kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp),
            kvp => Assert.Equal(default, kvp));
    }
 
    [Fact]
    public void TryGetValue_EmptyStorage()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        var result = dict.TryGetValue("key", out var value);
 
        // Assert
        Assert.False(result);
        Assert.Null(value);
    }
 
    [Fact]
    public void TryGetValue_EmptyStringIsAllowed()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, string>();
 
        // Act
        var result = dict.TryGetValue("", out var value);
 
        // Assert
        Assert.False(result);
        Assert.Null(value);
    }
 
    [Fact]
    public void TryGetValue_ListStorage_False()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        var result = dict.TryGetValue("other", out var value);
 
        // Assert
        Assert.False(result);
        Assert.Null(value);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void TryGetValue_ListStorage_True()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>()
            {
                { "key", "value" },
            };
 
        // Act
        var result = dict.TryGetValue("key", out var value);
 
        // Assert
        Assert.True(result);
        Assert.Equal("value", value);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void TryGetValue_ListStorage_True_CaseInsensitive()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>(StringComparer.OrdinalIgnoreCase)
            {
                { "key", "value" },
            };
 
        // Act
        var result = dict.TryGetValue("kEy", out var value);
 
        // Assert
        Assert.True(result);
        Assert.Equal("value", value);
        Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
    }
 
    [Fact]
    public void ListStorage_SwitchesToDictionaryAfter10_Add()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>();
 
        // Act 1
        dict.Add("key", "value");
 
        // Assert 1
        var storage = Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
        Assert.Equal(10, storage.Length);
 
        // Act 2
        dict.Add("key2", "value2");
        dict.Add("key3", "value3");
        dict.Add("key4", "value4");
        dict.Add("key5", "value5");
        dict.Add("key6", "value2");
        dict.Add("key7", "value3");
        dict.Add("key8", "value4");
        dict.Add("key9", "value5");
        dict.Add("key10", "value2");
        dict.Add("key11", "value3");
 
        // Assert 2
        Assert.Null(dict._arrayStorage);
        Assert.Equal(11, dict.Count);
    }
 
    [Fact]
    public void ListStorage_SwitchesToDictionaryAfter10_TryAdd()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>();
 
        // Act 1
        dict.TryAdd("key", "value");
 
        // Assert 1
        var storage = Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
        Assert.Equal(10, storage.Length);
 
        // Act 2
        dict.TryAdd("key2", "value2");
        dict.TryAdd("key3", "value3");
        dict.TryAdd("key4", "value4");
        dict.TryAdd("key5", "value5");
        dict.TryAdd("key6", "value2");
        dict.TryAdd("key7", "value3");
        dict.TryAdd("key8", "value4");
        dict.TryAdd("key9", "value5");
        dict.TryAdd("key10", "value2");
        dict.TryAdd("key11", "value3");
 
        // Assert 2
        Assert.Null(dict._arrayStorage);
        Assert.Equal(11, dict.Count);
    }
 
    [Fact]
    public void ListStorage_SwitchesToDictionaryAfter10_Index()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>();
 
        // Act 1
        dict["key"] = "value";
 
        // Assert 1
        var storage = Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
        Assert.Equal(10, storage.Length);
 
        // Act 2
        dict["key1"] = "value";
        dict["key2"] = "value";
        dict["key3"] = "value";
        dict["key4"] = "value";
        dict["key5"] = "value";
        dict["key6"] = "value";
        dict["key7"] = "value";
        dict["key8"] = "value";
        dict["key9"] = "value";
        dict["key10"] = "value";
 
        // Assert 2
        Assert.Null(dict._arrayStorage);
        Assert.Equal(11, dict.Count);
    }
 
    [Fact]
    public void ListStorage_RemoveAt_RearrangesInnerArray()
    {
        // Arrange
        var dict = new AdaptiveCapacityDictionary<string, object>();
        dict.Add("key", "value");
        dict.Add("key2", "value2");
        dict.Add("key3", "value3");
 
        // Assert 1
        var storage = Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
        Assert.Equal(3, dict.Count);
 
        // Act
        dict.Remove("key2");
 
        // Assert 2
        storage = Assert.IsType<KeyValuePair<string, object?>[]>(dict._arrayStorage);
        Assert.Equal(2, dict.Count);
        Assert.Equal("key", storage[0].Key);
        Assert.Equal("value", storage[0].Value);
        Assert.Equal("key3", storage[1].Key);
        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(CultureInfo.InvariantCulture)] = 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);
    }
 
    private class RegularType
    {
        public bool IsAwesome { get; set; }
 
        public int CoolnessFactor { get; set; }
    }
 
    private class Visibility
    {
        private string? PrivateYo { get; set; }
 
        internal int ItsInternalDealWithIt { get; set; }
 
        public bool IsPublic { get; set; }
    }
 
    private class StaticProperty
    {
        public static bool IsStatic { get; set; }
    }
 
    private class SetterOnly
    {
        private bool _coolSetOnly;
 
        public bool CoolSetOnly { set { _coolSetOnly = value; } }
    }
 
    private class Base
    {
        public bool DerivedProperty { get; set; }
    }
 
    private class Derived : Base
    {
        public bool TotallySweetProperty { get; set; }
    }
 
    private class DerivedHiddenProperty : Base
    {
        public new int DerivedProperty { get; set; }
    }
 
    private class IndexerProperty
    {
        public bool this[string key]
        {
            get { return false; }
            set { }
        }
    }
 
    private class Address
    {
        public string? City { get; set; }
 
        public string? State { get; set; }
    }
}