diff --git a/Recyclable.Collections.Compatibility.List.Tests/RecyclableLongListCompatibilityListTests.cs b/Recyclable.Collections.Compatibility.List.Tests/RecyclableLongListCompatibilityListTests.cs index a730b40..b99d9ae 100644 --- a/Recyclable.Collections.Compatibility.List.Tests/RecyclableLongListCompatibilityListTests.cs +++ b/Recyclable.Collections.Compatibility.List.Tests/RecyclableLongListCompatibilityListTests.cs @@ -47,7 +47,13 @@ namespace Recyclable.CollectionsTests foreach (var (itemIndex, rangedItemsCount) in itemRanges) { - var expectedItem = expectedData[(int)itemIndex]; + TestWith(list, comparer, expectedData, itemIndex, rangedItemsCount, expectedData[(int)itemIndex]); + TestWith(list, comparer, expectedData, itemIndex, rangedItemsCount, expectedData[Math.Min((int)(itemIndex + rangedItemsCount), itemsCount - 1)]); + TestWith(list, comparer, expectedData, itemIndex, rangedItemsCount, expectedData[(int)(itemIndex + (rangedItemsCount >> 1))]); + } + + static void TestWith(RecyclableLongList list, Comparer comparer, List expectedData, long itemIndex, long rangedItemsCount, long expectedItem) + { var expected = expectedData.BinarySearch((int)itemIndex, (int)rangedItemsCount, expectedItem, comparer); // Act @@ -138,8 +144,8 @@ namespace Recyclable.CollectionsTests } [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void BinarySearchShouldNotFindNonExistingItemsWhenOutsideRange(string testCase, IEnumerable testData, int itemsCount, int minBlockSize, in long[] itemIndexes) + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexWithRangeVariants), MemberType = typeof(RecyclableLongListTestData))] + public void BinarySearchShouldNotFindNonExistingItemsWhenOutsideRange(string testCase, IEnumerable testData, int itemsCount, int minBlockSize, in (long ItemIndex, long RangedItemsCount)[] itemRanges) { _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); @@ -148,7 +154,7 @@ namespace Recyclable.CollectionsTests var comparer = Comparer.Default; var expectedData = testData.ToList(); - foreach (var itemIndex in itemIndexes) + foreach (var (itemIndex, rangedItemsCount) in itemRanges) { var expectedItem = expectedData[(int)itemIndex]; @@ -158,6 +164,10 @@ namespace Recyclable.CollectionsTests expected = expectedData.BinarySearch((int)itemIndex + 1, itemsCount - (int)itemIndex - 1, expectedItem, comparer); _ = list.BinarySearch((int)itemIndex + 1, itemsCount - (int)itemIndex - 1, expectedItem, comparer).Should().Be(expected); + + expectedItem--; + expected = expectedData.BinarySearch((int)itemIndex, (int)rangedItemsCount, expectedItem, comparer); + _ = list.BinarySearch((int)itemIndex, (int)rangedItemsCount, expectedItem, comparer).Should().Be(expected); } } @@ -457,44 +467,55 @@ namespace Recyclable.CollectionsTests } [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindIndexShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexWithRangeVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindIndexShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable testData, int itemsCount, int minBlockSize, in (long ItemIndex, long RangedItemsCount)[] itemRanges) { // Prepare using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); var expectedData = testData.ToList(); - foreach (var itemIndex in itemIndexes) + foreach (var (itemIndex, rangedItemsCount) in itemRanges) { - var expectedItem = expectedData[(int)itemIndex]; - var expected = expectedData.FindIndex((int)itemIndex, (int)(itemsCount - itemIndex), item => item == expectedItem); + TestWith(itemsCount, list, expectedData, itemIndex, rangedItemsCount, expectedData[(int)itemIndex]); + TestWith(itemsCount, list, expectedData, itemIndex, rangedItemsCount, expectedData[Math.Min((int)(itemIndex + rangedItemsCount), itemsCount - 1)]); + TestWith(itemsCount, list, expectedData, itemIndex, rangedItemsCount, expectedData[(int)(itemIndex + (rangedItemsCount >> 1))]); + } + + static void TestWith(int itemsCount, RecyclableLongList list, List expectedData, long itemIndex, long rangedItemsCount, long expectedItem) + { + var expected = expectedData.FindIndex((int)itemIndex, (int)rangedItemsCount, item => item == expectedItem); // Act - var actual = list.FindIndex((int)itemIndex, (int)(itemsCount - itemIndex), item => item == expectedItem); + var actual = list.FindIndex((int)itemIndex, (int)rangedItemsCount, item => item == expectedItem); // Validate - _ = actual.Should().Be((int)itemIndex).And.Be(expected); + _ = actual.Should().Be(expected); } } [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindIndexShouldNotAnythingWhenRangeExcludesItem(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexWithRangeVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindIndexShouldNotAnythingWhenRangeExcludesItem(string testCase, IEnumerable testData, int itemsCount, int minBlockSize, in (long ItemIndex, long RangedItemsCount)[] itemRanges) { // Prepare using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); var expectedData = testData.ToList(); - foreach (var itemIndex in itemIndexes) + foreach (var (itemIndex, rangedItemsCount) in itemRanges) { - var expectedItem = expectedData[(int)itemIndex]; - var expected = expectedData.FindIndex((int)itemIndex + 1, (int)(itemsCount - itemIndex - 1), item => item == expectedItem); + TestWith(itemsCount, list, expectedData, itemIndex, rangedItemsCount, expectedData[Math.Max((int)(itemIndex - 1), 0)]); + TestWith(itemsCount, list, expectedData, itemIndex, rangedItemsCount, expectedData[Math.Min((int)(itemIndex + rangedItemsCount), itemsCount - 1)]); + } + + static void TestWith(int itemsCount, RecyclableLongList list, List expectedData, long itemIndex, long rangedItemsCount, long expectedItem) + { + var expected = expectedData.FindIndex((int)itemIndex, (int)rangedItemsCount, item => item == expectedItem); // Act - var actual = list.FindIndex((int)itemIndex + 1, (int)(itemsCount - itemIndex - 1), item => item == expectedItem); + var actual = list.FindIndex((int)itemIndex, (int)rangedItemsCount, item => item == expectedItem); // Validate - _ = actual.Should().Be(-1).And.Be(expected); + _ = actual.Should().Be(expected); } } @@ -541,18 +562,22 @@ namespace Recyclable.CollectionsTests } [Theory] - [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] - public void FindLastIndexShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexWithRangeVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindLastIndexShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable testData, int itemsCount, int minBlockSize, in (long ItemIndex, long RangedItemsCount)[] itemRanges) { // Prepare using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); var expectedData = testData.ToList(); - foreach (var itemIndex in itemIndexes) + foreach (var (itemIndex, rangedItemsCount) in itemRanges) { - var expectedItem = expectedData[(int)itemIndex]; - // Act & Validate + TestWith(itemsCount, list, expectedData, itemIndex, expectedData[(int)itemIndex]); + TestWith(itemsCount, list, expectedData, itemIndex, expectedData[Math.Min((int)(itemIndex + rangedItemsCount), itemsCount - 1)]); + } + + static void TestWith(int itemsCount, RecyclableLongList list, List expectedData, long itemIndex, long expectedItem) + { var expected = expectedData.FindLastIndex(itemsCount - 1, itemsCount, x => x == expectedItem); _ = list.FindLastIndex(itemsCount - 1, itemsCount, x => x == expectedItem).Should().Be((int)itemIndex).And.Be(expected); } diff --git a/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.Find.cs b/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.Find.cs index d366e23..a8c22f3 100644 --- a/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.Find.cs +++ b/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.Find.cs @@ -305,7 +305,7 @@ namespace Recyclable.Collections public static int FindIndex(this RecyclableLongList list, int startIndex, int count, Predicate match) { - if (list._longCount == 0) + if (list._longCount == 0 || count == 0) { return RecyclableDefaults.ItemNotFoundIndex; }