diff --git a/Recyclable.CollectionsTests/RecyclableArrayListTests.cs b/Recyclable.CollectionsTests/RecyclableArrayListTests.cs index da390ce..7d236d8 100644 --- a/Recyclable.CollectionsTests/RecyclableArrayListTests.cs +++ b/Recyclable.CollectionsTests/RecyclableArrayListTests.cs @@ -5,26 +5,6 @@ namespace Recyclable.CollectionsTests { public class RecyclableArrayListTests { - [Theory] - [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] - public void AddCountShouldSucceed(string testCase, IEnumerable testData, long itemsCount) - { - // Prepare - using var list = new RecyclableArrayList(); - - // Act - foreach (var item in testData) - { - list.Add(item); - _ = list.Count.Should().Be((int)item); - } - - // Validate - _ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount); - _ = list.Count.Should().Be((int)itemsCount); - _ = list.Should().ContainInConsecutiveOrder(testData); - } - [Theory] [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] public void AddRangeShouldAddItemsInCorrectOrder(string testCase, IEnumerable testData, long itemsCount) @@ -68,24 +48,157 @@ namespace Recyclable.CollectionsTests _ = list.Should().ContainInConsecutiveOrder(testData); } + [Theory] + [MemberData(nameof(RecyclableListTestData.EmptySourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void AddRangeShouldDoNothingWhenSourceIsEmpty(string testCase, IEnumerable testData) + { + // Prepare + using var list = new RecyclableArrayList(); + + // Act + if (testData is long[] testDataArray) + { + list.AddRange(testDataArray); + } + else if (testData is List testDataList) + { + list.AddRange(testDataList); + } + else if (testData is RecyclableArrayList testDataRecyclableArrayList) + { + list.AddRange(testDataRecyclableArrayList); + } + else if (testData is RecyclableList testDataRecyclableList) + { + list.AddRange(testDataRecyclableList); + } + else if (testData is IList testDataIList) + { + list.AddRange(testDataIList); + } + else if (testData is IEnumerable testDataIEnumerable) + { + list.AddRange(testDataIEnumerable); + } + else + { + throw new InvalidCastException("Unknown type of test data"); + } + + // Validate + _ = list.Capacity.Should().Be(0); + _ = list.Count.Should().Be(0); + _ = list.Should().BeEmpty(); + } + + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void AddRangeShouldNotOverrideItems(string testCase, IEnumerable testData, long itemsCount) + { + // Prepare + using var list = new RecyclableArrayList(); + + // Act + if (testData is long[] testDataArray) + { + list.AddRange(testDataArray); + list.AddRange(testDataArray); + } + else if (testData is List testDataList) + { + list.AddRange(testDataList); + list.AddRange(testDataList); + } + else if (testData is RecyclableArrayList testDataRecyclableArrayList) + { + list.AddRange(testDataRecyclableArrayList); + list.AddRange(testDataRecyclableArrayList); + } + else if (testData is RecyclableList testDataRecyclableList) + { + list.AddRange(testDataRecyclableList); + list.AddRange(testDataRecyclableList); + } + else if (testData is IList testDataIList) + { + list.AddRange(testDataIList); + list.AddRange(testDataIList); + } + else if (testData is IEnumerable testDataIEnumerable) + { + list.AddRange(testDataIEnumerable); + list.AddRange(testDataIEnumerable); + } + else + { + throw new InvalidCastException("Unknown type of test data"); + } + + // Validate + var expectedData = testData.Concat(testData).ToArray(); + + if (itemsCount > 0) + { + _ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount * 2); + } + + _ = list.Count.Should().Be(expectedData.Length); + _ = list.Should().ContainInConsecutiveOrder(expectedData); + } + [Theory] [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] public void AddShouldAcceptDuplicates(string testCase, IEnumerable testData, long itemsCount) { - // Act - using var list = new RecyclableArrayList((int)itemsCount * 2); - foreach (var index in testData) - { - list.Add(index); - } + // Prepare + testData = testData.Concat(testData).ToArray(); + // Act + using var list = new RecyclableArrayList(); foreach (var index in testData) { list.Add(index); } // Validate - _ = list.Count.Should().Be((int)itemsCount * 2); + _ = list.Count.Should().Be((int)(itemsCount * 2)); + _ = list.Should().ContainInConsecutiveOrder(testData); + } + + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void AddShouldAddItems(string testCase, IEnumerable testData, long itemsCount) + { + // Prepare + using var list = new RecyclableArrayList(); + + // Act + foreach (var item in testData) + { + list.Add(item); + _ = list.Count.Should().Be((int)item); + } + + // Validate + _ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount); + _ = list.Count.Should().Be((int)itemsCount); + _ = list.Should().ContainInConsecutiveOrder(testData); + } + + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void AddShouldAddItemWhenAfterAddRange(string testCase, IEnumerable testData, long itemsCount) + { + // Act + using var list = new RecyclableArrayList(); + list.AddRange(testData); + foreach (var index in testData) + { + list.Add(index); + } + + // Validate + _ = list.Count.Should().Be((int)(itemsCount * 2)); _ = list.Should().ContainInConsecutiveOrder(testData.Concat(testData)); } @@ -99,6 +212,7 @@ namespace Recyclable.CollectionsTests // Act list.Clear(); + list.Clear(); // Validate _ = list.Count.Should().Be(0); @@ -106,6 +220,18 @@ namespace Recyclable.CollectionsTests } + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void ConsecutiveDisposeShouldSucceed(string testCase, IEnumerable testData, long itemsCount) + { + // Prepare + using var list = new RecyclableArrayList(testData); + list.Dispose(); + + // Act + list.Dispose(); + } + [Theory] [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] public void ConstructorShouldAcceptDuplicates(string testCase, IEnumerable testData, long itemsCount) @@ -234,9 +360,46 @@ namespace Recyclable.CollectionsTests _ = yieldedItems.Should().ContainInConsecutiveOrder(testData); } + [Fact] + public void IndexOfShouldNotFindAnythingWhenListEmpty() + { + // Prepare + using var list = new RecyclableArrayList(); + + // Validate + _ = list.IndexOf(0).Should().Be(-1); + _ = list.IndexOf(1).Should().Be(-1); + } + [Theory] [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] - public void IndexOfShouldFindTheIndexes(string testCase, IEnumerable testData, long itemsCount) + public void IndexOfShouldNotFindNonExistingItems(string testCase, IEnumerable testData, long itemsCount) + { + // Prepare + if (itemsCount == 0) + { + // There is nothing to search for when our lists are empty + 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.IndexOf(-item).Should().Be(-1); + } + + // Validate + _ = list.IndexOf(0).Should().Be(-1); + } + + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void IndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable testData, long itemsCount) { // Prepare using var list = new RecyclableArrayList(testData); @@ -249,6 +412,44 @@ namespace Recyclable.CollectionsTests } } + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] + public void InitializeSortClearAddRangeRemoveShouldSucceed(string testCase, IEnumerable testData, long itemsCount) + { + if (itemsCount == 0) + { + return; + } + + // Act + using RecyclableArrayList list = new(testData); + list.QuickSort(); + + // Validate + _ = list.Count.Should().Be((int)itemsCount); + _ = list.Should().Equal(testData); + + // Act + list.Clear(); + + // Validate + _ = list.Count.Should().Be(0); + _ = list.Should().BeEmpty(); + + // Act + list.AddRange(testData); + + // Validate + _ = list.Count.Should().Be((int)itemsCount); + _ = list.Should().ContainInConsecutiveOrder(testData); + + // Act + foreach (var item in testData.Reverse()) + { + _ = list.Remove(item).Should().BeTrue(); + } + } + [Theory] [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] public void InsertAtTheBeginningShouldMoveItems(string testCase, IEnumerable testData, long itemsCount) @@ -269,24 +470,6 @@ namespace Recyclable.CollectionsTests _ = list.Should().ContainInConsecutiveOrder(testData.Reverse()); } - [Theory] - [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] - public void LongIndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable testData, long itemsCount) - { - // Prepare - using var list = new RecyclableArrayList(testData); - - // Act & Validate - foreach (var item in testData) - { - // Act - var index = list.IndexOf(item); - - // Validate - _ = index.Should().Be((int)(item - 1)); - } - } - [Theory] [MemberData(nameof(RecyclableListTestData.SourceDataVariants), MemberType = typeof(RecyclableListTestData))] public void RemoveAtFromTheBeginningShouldSucceed(string testCase, IEnumerable testData, long itemsCount) diff --git a/Recyclable.CollectionsTests/RecyclableListTests.cs b/Recyclable.CollectionsTests/RecyclableListTests.cs index 231838d..e229d6d 100644 --- a/Recyclable.CollectionsTests/RecyclableListTests.cs +++ b/Recyclable.CollectionsTests/RecyclableListTests.cs @@ -246,6 +246,19 @@ namespace Recyclable.CollectionsTests _ = list.Should().Equal(testData); } + [Theory] + [MemberData(nameof(RecyclableListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableListTestData))] + public void ConstructorShouldAddItemsInCorrectOrderWhenSourceIsIEnumerable(string testCase, IEnumerable testData, long itemsCount, int targetBlockSize) + { + // Act + using var list = new RecyclableList(testData, minBlockSize: targetBlockSize); + + // Validate + _ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount, "when we succeed in taking count without enumerating, then we allocate as much memory as needed, only"); + _ = list.LongCount.Should().Be(itemsCount); + _ = list.Should().ContainInConsecutiveOrder(testData); + } + [Theory] [MemberData(nameof(RecyclableListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableListTestData))] public void ConstructorSourceShouldInitializeList(string testCase, IEnumerable testData, long itemsCount, int targetBlockSize) @@ -320,7 +333,7 @@ namespace Recyclable.CollectionsTests [Theory] [MemberData(nameof(RecyclableListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableListTestData))] //[InlineData("Debuging case", new[] { 1L, 2, }, 2, 2)] - public void CopyToShouldCopyAllItems(string testCase, IEnumerable testData, long itemsCount, int targetBlockSize) + public void CopyToShouldCopyAllItemsInTheCorrectOrder(string testCase, IEnumerable testData, long itemsCount, int targetBlockSize) { // Prepare using var list = new RecyclableList(testData, minBlockSize: targetBlockSize); @@ -348,7 +361,7 @@ namespace Recyclable.CollectionsTests [Theory] [MemberData(nameof(RecyclableListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableListTestData))] - public void EnumeratorShouldYieldAllItems(string testCase, IEnumerable testData, long itemsCount, int targetBlockSize) + public void EnumerateShouldYieldAllItemsInCorrectOrder(string testCase, IEnumerable testData, long itemsCount, int targetBlockSize) { // Prepare using var list = new RecyclableList(testData, minBlockSize: targetBlockSize); @@ -564,7 +577,7 @@ namespace Recyclable.CollectionsTests [Theory] [MemberData(nameof(RecyclableListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableListTestData))] - public void RemoveShouldRemoveLastItem(string testCase, IEnumerable testData, long itemsCount, int targetBlockSize) + public void RemoveFromTheEndShouldRemoveTheCorrectItem(string testCase, IEnumerable testData, long itemsCount, int targetBlockSize) { // Prepare using var list = new RecyclableList(testData, minBlockSize: targetBlockSize);