From 277e52f7018d5ac138224385267f80c08ca7b085 Mon Sep 17 00:00:00 2001 From: mlemanczyk Date: Mon, 20 Mar 2023 23:51:23 +0100 Subject: [PATCH] RecyclableArrayList.Contains fixed to not throw exception when the list is empty. RecyclableArrayList tests sorted alphabetically, simplified & extended to use the test data & validate various combinations of item counts & block sizes. --- Recyclable.Collections/RecyclableArrayList.cs | 2 +- .../RecyclableArrayListTests.cs | 299 +++++++++--------- 2 files changed, 149 insertions(+), 152 deletions(-) diff --git a/Recyclable.Collections/RecyclableArrayList.cs b/Recyclable.Collections/RecyclableArrayList.cs index 7b83164..5d32b43 100644 --- a/Recyclable.Collections/RecyclableArrayList.cs +++ b/Recyclable.Collections/RecyclableArrayList.cs @@ -372,7 +372,7 @@ namespace Recyclable.Collections _count = 0; } - public bool Contains(T item) => _memoryBlock.Contains(item); + public bool Contains(T item) => Array.IndexOf(_memoryBlock, 0, _count) >= 0; public void CopyTo(T[] array, int arrayIndex) => Array.Copy(_memoryBlock, 0, array, arrayIndex, _count); diff --git a/Recyclable.CollectionsTests/RecyclableArrayListTests.cs b/Recyclable.CollectionsTests/RecyclableArrayListTests.cs index 1a9ce13..709de94 100644 --- a/Recyclable.CollectionsTests/RecyclableArrayListTests.cs +++ b/Recyclable.CollectionsTests/RecyclableArrayListTests.cs @@ -167,32 +167,116 @@ namespace Recyclable.CollectionsTests } [Fact] - public void InsertAtTheBeginningShouldMoveItems() + public void ContainsShouldNotFindAnythingWhenListEmpty() { // Prepare - var testData = _testData.ToArray(); - var list = new RecyclableArrayList(); + using var list = new RecyclableArrayList(); + + // Validate + _ = list.Contains(0).Should().BeFalse(); + _ = list.Contains(1).Should().BeFalse(); + } + + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void ContainsShouldNotFindNonExistingItems(string testCase, IEnumerable testData, long itemsCount) + { + if (itemsCount == 0) + { + return; + } + + // Prepare + using var list = new RecyclableArrayList(testData); + _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); + + // Act + foreach (var item in testData) + { + // Validate + _ = list.Contains(-item).Should().BeFalse(); + } + + // Validate + _ = list.Contains(0).Should().BeFalse(); + } + + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void CopyToShouldCopyAllItemsInTheCorrectOrder(string testCase, IEnumerable testData, long itemsCount) + { + // Prepare + var list = new RecyclableArrayList(testData); + long[] copiedItems = new long[itemsCount]; + + // Act + list.CopyTo(copiedItems, 0); + + // Validate + _ = copiedItems.Length.Should().Be((int)itemsCount); + _ = copiedItems.Should().ContainInConsecutiveOrder(testData); + } + + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void EnumerateShouldYieldAllItemsInCorrectOrder(string testCase, IEnumerable testData, long itemsCount) + { + // Prepare + var list = new RecyclableArrayList(testData); + + // Act + var yieldedItems = new List((int)itemsCount); + foreach (var item in list) + { + yieldedItems.Add(item); + } + + // Validate + _ = yieldedItems.Count.Should().Be((int)itemsCount); + _ = yieldedItems.Should().ContainInConsecutiveOrder(testData); + } + + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void IndexOfShouldFindTheIndexes(string testCase, IEnumerable testData, long itemsCount) + { + // Prepare + using var list = new RecyclableArrayList(testData); + + // Act & Validate + foreach (var index in testData) + { + var actual = list.IndexOf(index); + _ = actual.Should().Be((int)(index - 1)); + } + } + + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void InsertAtTheBeginningShouldMoveItems(string testCase, IEnumerable testData, long itemsCount) + { + // Prepare + var list = new RecyclableArrayList(); // Act foreach (var item in testData) { list.Insert(0, item); - _ = list.Count.Should().Be(item); + _ = list.Count.Should().Be((int)item); } // Validate - _ = list.Capacity.Should().Be(32); - _ = list.Should().HaveCount(testData.Length) - .And.ContainInConsecutiveOrder(testData.Reverse()) - .And.BeEquivalentTo(testData); + _ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount); + _ = list.Count.Should().Be((int)itemsCount); + _ = list.Should().ContainInConsecutiveOrder(testData.Reverse()); } - [Fact] - public void LongIndexOfShouldReturnCorrectIndexes() + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void LongIndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable testData, long itemsCount) { // Prepare - var testData = _testData.ToArray(); - var list = new RecyclableArrayList(testData); + var list = new RecyclableArrayList(testData); // Act & Validate foreach (var item in testData) @@ -201,27 +285,70 @@ namespace Recyclable.CollectionsTests var index = list.IndexOf(item); // Validate - _ = index.Should().Be(item - 1); + _ = index.Should().Be((int)(item - 1)); } } - [Fact] - public void RemoveFromTheBeginningShouldRemoveTheCorrectItem() + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void RemoveAtFromTheBeginningShouldSucceed(string testCase, IEnumerable testData, long itemsCount) { // Prepare - var testData = _testData.ToArray(); - var list = new RecyclableArrayList(testData); + var list = new RecyclableArrayList(testData); // Act & Validate - for (var deleted = 1; deleted <= testData.LongLength; deleted++) + for (var deleted = 1; deleted <= itemsCount; deleted++) + { + // Act + list.RemoveAt(0); + + // Validate + _ = list.Count.Should().Be((int)(itemsCount - deleted)); + _ = list.Should().ContainInConsecutiveOrder(testData.Skip(deleted)); + } + + _ = list.Should().BeEmpty(); + _ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount); + } + + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void RemoveAtFromTheEndShouldSucceed(string testCase, IEnumerable testData, long itemsCount) + { + // Prepare + var list = new RecyclableArrayList(testData); + + // Act & Validate + for (var deleted = 1; deleted <= itemsCount; deleted++) + { + // Act + list.RemoveAt(list.Count - 1); + + // Validate + _ = list.Count.Should().Be((int)(itemsCount - deleted)); + _ = list.Should().ContainInConsecutiveOrder(testData.Take((int)(itemsCount - deleted))); + } + + _ = list.Should().BeEmpty(); + _ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount); + } + + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void RemoveFromTheBeginningShouldRemoveTheCorrectItem(string testCase, IEnumerable testData, long itemsCount) + { + // Prepare + var list = new RecyclableArrayList(testData); + + // Act & Validate + for (var deleted = 1; deleted <= itemsCount; deleted++) { // Act _ = list.Remove(deleted).Should().BeTrue(); // Validate - _ = list.Should().HaveCount(testData.Length - deleted) - .And.ContainInConsecutiveOrder(testData.Skip(deleted)) - .And.BeEquivalentTo(testData.Skip(deleted)); + _ = list.Count.Should().Be((int)(itemsCount - deleted)); + _ = list.Should().ContainInConsecutiveOrder(testData.Skip(deleted)); } } @@ -244,135 +371,5 @@ namespace Recyclable.CollectionsTests .And.BeEquivalentTo(testData.Take(testData.Length - deleted)); } } - - [Fact] - public void RemoveAtFromTheBeginningShouldSucceed() - { - // Prepare - var testData = _testData.ToArray(); - var list = new RecyclableArrayList(testData); - - // Act & Validate - for (var deleted = 1; deleted <= testData.LongLength; deleted++) - { - // Act - list.RemoveAt(0); - - // Validate - _ = list.Should().HaveCount(testData.Length - deleted) - .And.ContainInConsecutiveOrder(testData.Skip(deleted)) - .And.BeEquivalentTo(testData.Skip(deleted)); - } - - _ = list.Should().BeEmpty(); - _ = list.Capacity.Should().Be(20); - } - - [Fact] - public void RemoveAtFromTheEndShouldSucceed() - { - // Prepare - var testData = _testData.ToArray(); - var list = new RecyclableArrayList(testData); - - // Act & Validate - for (var deleted = 1; deleted <= testData.LongLength; deleted++) - { - // Act - list.RemoveAt(list.Count - 1); - - // Validate - _ = list.Should().HaveCount(testData.Length - deleted) - .And.ContainInConsecutiveOrder(testData.Take(testData.Length - deleted)) - .And.BeEquivalentTo(testData.Take(testData.Length - deleted)); - } - - _ = list.Should().BeEmpty(); - _ = list.Capacity.Should().Be(20); - } - - [Fact] - public void EnumerateShouldYieldAllItemsInCorrectOrder() - { - // Prepare - var testData = _testData.ToArray(); - var list = new RecyclableArrayList(testData); - - // Act - var yieldedItems = new List(); - foreach (var item in list) - { - yieldedItems.Add(item); - } - - // Validate - _ = yieldedItems.Should().HaveCount(testData.Length) - .And.ContainInConsecutiveOrder(testData) - .And.BeEquivalentTo(testData); - } - - [Fact] - public void CopyToShouldCopyAllItemsInTheCorrectOrder() - { - // Prepare - var testData = _testData.ToArray(); - var list = new RecyclableArrayList(testData); - int[] yieldedItems = new int[testData.Length]; - - // Act - list.CopyTo(yieldedItems, 0); - - // Validate - _ = yieldedItems.Should().HaveCount(testData.Length) - .And.ContainInConsecutiveOrder(testData) - .And.BeEquivalentTo(testData); - } - - [Fact] - public void IndexOfShouldFindTheIndexes() - { - // Prepare - var testData = _testData.ToArray(); - using var list = new RecyclableArrayList(testData); - - // Act & Validate - foreach (var index in _testData.ToArray()) - { - var actual = list.IndexOf(index); - _ = actual.Should().Be(index - 1); - } - } - - [Fact] - public void ContainsShouldNotFindNonExistingItems() - { - // Prepare - var testData = _testData.ToArray(); - using var list = new RecyclableArrayList(testData); - _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); - - // Act - foreach (var item in testData) - { - // Validate - _ = list.Contains(-item).Should().BeFalse(); - } - - // Validate - _ = list.Contains(0).Should().BeFalse(); - } - - [Fact] - public void ContainsShouldNotFindAnythingWhenListEmpty() - { - // Prepare - var testData = _testData.ToArray(); - using var list = new RecyclableArrayList(testData); - - // Validate - _ = list.Contains(0).Should().BeFalse(); - _ = list.Contains(1).Should().BeTrue(); - } - } } \ No newline at end of file