public void Contains_Invoke_ReturnsExpected(IEqualityComparer <string> comparer, string key, bool expected)
        {
            var collection = new StringKeyedCollection <string>(comparer, 3);

            collection.GetKeyForItemHandler = item => item + "_key";

            // Without dictionary.
            collection.InsertItem(0, "first");
            Assert.Equal(expected, collection.Contains(key));

            // With dictionary.
            collection.InsertItem(0, "second");
            collection.InsertItem(0, "third");
            collection.InsertItem(0, "fourth");
            Assert.Equal(expected, collection.Contains(key));
        }
        public void InsertItem_AddSameKey_ThrowsArgumentException(IEqualityComparer <string> comparer, int dictionaryCreationThreshold, string key)
        {
            var collection = new StringKeyedCollection <string>(comparer, dictionaryCreationThreshold);

            collection.GetKeyForItemHandler = item => item + "_key";
            collection.InsertItem(0, "first");
            AssertExtensions.Throws <ArgumentException>(dictionaryCreationThreshold > 1 ? "key" : null, null, () => collection.InsertItem(0, key));
        }
        public void TryGetValue_Invoke_ReturnsExpected(IEqualityComparer <string> comparer, string key, bool expected, string expectedItem)
        {
            var collection = new StringKeyedCollection <string>(comparer, 3);

            collection.GetKeyForItemHandler = i => i + "_key";

            // Without dictionary.
            collection.InsertItem(0, "first");
            Assert.Equal(expected, collection.TryGetValue(key, out string item));
            Assert.Equal(expectedItem, item);

            // With dictionary.
            collection.InsertItem(0, "second");
            collection.InsertItem(0, "third");
            collection.InsertItem(0, "fourth");
            Assert.Equal(expected, collection.TryGetValue(key, out item));
            Assert.Equal(expectedItem, item);
        }
        public void InsertItem_InvokeSeveralTimesWithoutCustomThreshold_Success()
        {
            var collection = new StringKeyedCollection <int>();

            collection.GetKeyForItemHandler = item => (item * 2).ToString();

            // Add first.
            collection.InsertItem(0, 1);
            Assert.Equal(new int[] { 1 }, collection.Items.Cast <int>());
            Assert.Equal(new Dictionary <string, int>
            {
                { "2", 1 }
            }, collection.Dictionary
                         );
            Assert.Equal(1, collection["2"]);

            // Add another - end.
            collection.InsertItem(1, 3);
            Assert.Equal(new int[] { 1, 3 }, collection.Items.Cast <int>());
            Assert.Equal(new Dictionary <string, int>
            {
                { "2", 1 },
                { "6", 3 }
            }, collection.Dictionary
                         );
            Assert.Equal(1, collection["2"]);
            Assert.Equal(3, collection["6"]);

            // Add another - middle.
            collection.InsertItem(1, 2);
            Assert.Equal(new int[] { 1, 2, 3 }, collection.Items.Cast <int>());
            Assert.Equal(new Dictionary <string, int>
            {
                { "2", 1 },
                { "4", 2 },
                { "6", 3 }
            }, collection.Dictionary
                         );
            Assert.Equal(1, collection["2"]);
            Assert.Equal(2, collection["4"]);
            Assert.Equal(3, collection["6"]);
        }
        public void InsertItem_NullKeyForItemResult_Success()
        {
            var collection = new StringKeyedCollection <int>(null, 0);

            // Don't add even numbers.
            collection.GetKeyForItemHandler = item => item % 2 == 0 ? null : item.ToString();

            // Add null without dictionary - not added.
            collection.InsertItem(0, 2);
            Assert.Equal(new int[] { 2 }, collection.Items.Cast <int>());
            Assert.Null(collection.Dictionary);

            // Add non null without dictionary - added.
            collection.InsertItem(0, 1);
            Assert.Equal(new int[] { 1, 2 }, collection.Items.Cast <int>());
            Assert.Equal(new Dictionary <string, int>
            {
                { "1", 1 }
            }, collection.Dictionary
                         );

            // Add null with dictionary - not added.
            collection.InsertItem(0, 4);
            Assert.Equal(new int[] { 4, 1, 2 }, collection.Items.Cast <int>());
            Assert.Equal(new Dictionary <string, int>
            {
                { "1", 1 }
            }, collection.Dictionary
                         );

            // Add non null with dictionary - added.
            collection.InsertItem(0, 3);
            Assert.Equal(new int[] { 3, 4, 1, 2 }, collection.Items.Cast <int>());
            Assert.Equal(new Dictionary <string, int>
            {
                { "1", 1 },
                { "3", 3 }
            }, collection.Dictionary
                         );
        }
        public void InsertItem_InvokeSeveralTimesWithCustomThreshold_Success()
        {
            var collection = new StringKeyedCollection <int>(null, 3);

            collection.GetKeyForItemHandler = item => (item * 2).ToString();

            // Add first.
            collection.InsertItem(0, 1);
            Assert.Equal(new int[] { 1 }, collection.Items.Cast <int>());
            Assert.Null(collection.Dictionary);
            Assert.Equal(1, collection["2"]);

            // Add another.
            collection.InsertItem(1, 3);
            Assert.Equal(new int[] { 1, 3 }, collection.Items.Cast <int>());
            Assert.Null(collection.Dictionary);
            Assert.Equal(1, collection["2"]);
            Assert.Equal(3, collection["6"]);

            // Meet threshold.
            collection.InsertItem(1, 2);
            Assert.Equal(new int[] { 1, 2, 3 }, collection.Items.Cast <int>());
            Assert.Null(collection.Dictionary);
            Assert.Equal(1, collection["2"]);
            Assert.Equal(2, collection["4"]);
            Assert.Equal(3, collection["6"]);

            // Exceed threshold.
            collection.InsertItem(3, 4);
            Assert.Equal(new int[] { 1, 2, 3, 4 }, collection.Items.Cast <int>());
            Assert.Equal(new Dictionary <string, int>
            {
                { "2", 1 },
                { "4", 2 },
                { "6", 3 },
                { "8", 4 }
            }, collection.Dictionary
                         );
            Assert.Equal(1, collection["2"]);
            Assert.Equal(2, collection["4"]);
            Assert.Equal(3, collection["6"]);
            Assert.Equal(4, collection["8"]);

            // Add another.
            collection.InsertItem(4, 5);
            Assert.Equal(new int[] { 1, 2, 3, 4, 5 }, collection.Items.Cast <int>());
            Assert.Equal(new Dictionary <string, int>
            {
                { "2", 1 },
                { "4", 2 },
                { "6", 3 },
                { "8", 4 },
                { "10", 5 }
            }, collection.Dictionary
                         );
            Assert.Equal(1, collection["2"]);
            Assert.Equal(2, collection["4"]);
            Assert.Equal(3, collection["6"]);
            Assert.Equal(4, collection["8"]);
            Assert.Equal(5, collection["10"]);
        }