Tests reworked for better coverage & more targeted scenarios.
This commit is contained in:
1 parent
aeb0ee23f1
commit
1202225162
4 files changed
+542
-468
No files matched your search
@@ -16,6 +16,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Open.Numeric.Primes" Version="3.0.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.5.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Recyclable.CollectionsTests
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.EmptySourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void AddRangeShouldDoNothingWhenSourceIsEmpty(string testCase, IEnumerable<long> testData)
|
||||
public void AddRangeShouldDoNothingWhenSourceIsEmpty(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>();
|
||||
@@ -217,7 +217,8 @@ namespace Recyclable.CollectionsTests
|
||||
list.Clear();
|
||||
list.Clear();
|
||||
|
||||
// Validate
|
||||
// Validate
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
_ = list.Count.Should().Be(0);
|
||||
_ = list.Should().BeEmpty();
|
||||
}
|
||||
@@ -260,23 +261,17 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ContainsShouldFindAllItems(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ContainsShouldFindAllItems(string testCase, IEnumerable<long> testData, long itemsCount, in long[] itemIndexes)
|
||||
{
|
||||
if (itemsCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>(testData, (int)itemsCount);
|
||||
_ = testData.Any().Should().BeTrue("we need items on the list that we can look for");
|
||||
|
||||
// Act
|
||||
foreach (var item in testData)
|
||||
// Act & Validate
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Validate
|
||||
_ = list.Contains(item).Should().BeTrue();
|
||||
_ = list.Contains(list[(int)itemIndex]).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,27 +287,18 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ContainsShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ContainsShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, in long[] itemIndexes)
|
||||
{
|
||||
if (itemsCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>(testData, (int)itemsCount);
|
||||
_ = testData.Any().Should().BeTrue("we need items on the list that we can look for");
|
||||
|
||||
// Act
|
||||
foreach (var item in testData)
|
||||
// Act & Validate
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Validate
|
||||
_ = list.Contains(-item).Should().BeFalse();
|
||||
_ = list.Contains(-list[(int)itemIndex]).Should().BeFalse();
|
||||
}
|
||||
|
||||
// Validate
|
||||
_ = list.Contains(0).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -362,198 +348,130 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void IndexOfShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void IndexOfShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
if (itemsCount == 0)
|
||||
{
|
||||
// There is nothing to search for when our lists are empty
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>(testData, (int)itemsCount);
|
||||
_ = testData.Any().Should().BeTrue("we need items on the list that we can look for");
|
||||
|
||||
// Act
|
||||
foreach (var item in testData)
|
||||
// Act & Validate
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Validate
|
||||
_ = list.IndexOf(-item).Should().Be(-1);
|
||||
_ = list.IndexOf(-list[(int)itemIndex]).Should().Be(-1);
|
||||
}
|
||||
|
||||
// Validate
|
||||
_ = list.IndexOf(0).Should().Be(-1);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void IndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void IndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable<long> testData, long itemsCount, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>(testData, (int)itemsCount);
|
||||
|
||||
// Act & Validate
|
||||
foreach (var index in testData)
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
var actual = list.IndexOf(index);
|
||||
_ = actual.Should().Be((int)(index - 1));
|
||||
_ = list.IndexOf(list[(int)itemIndex]).Should().Be((int)itemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void InitializeSortClearAddRangeRemoveShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void InitializeSortClearAddRangeRemoveShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount, in long[] itemIndexes)
|
||||
{
|
||||
if (itemsCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Act
|
||||
using RecyclableList<long> list = new(testData, (int)itemsCount);
|
||||
QuickSortExtensions<long>.QuickSort(list);
|
||||
|
||||
// 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().Equal(testData);
|
||||
|
||||
// Act
|
||||
foreach (var item in testData.Reverse())
|
||||
{
|
||||
_ = list.Remove(item).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void InsertAtTheBeginningShouldMoveItems(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>((int)itemsCount);
|
||||
|
||||
// Act
|
||||
foreach (var item in testData)
|
||||
{
|
||||
list.Insert(0, item);
|
||||
_ = list.Count.Should().Be((int)item);
|
||||
}
|
||||
|
||||
// Validate
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
_ = list.Count.Should().Be((int)itemsCount);
|
||||
_ = list.Should().Equal(testData.Reverse());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void InsertAtTheEndShouldAppend(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>(testData);
|
||||
|
||||
// Act
|
||||
list.Insert((int)itemsCount, -1);
|
||||
|
||||
// Assert
|
||||
_ = list.Count.Should().Be((int)itemsCount + 1);
|
||||
_ = list[^1].Should().Be(-1);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void RemoveAtFromTheBeginningShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>(testData, (int)itemsCount);
|
||||
|
||||
// Act & Validate
|
||||
for (var deleted = 1; deleted <= itemsCount; deleted++)
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Act
|
||||
list.RemoveAt(0);
|
||||
using RecyclableList<long> list = new(testData, (int)itemsCount);
|
||||
QuickSortExtensions<long>.QuickSort(list);
|
||||
|
||||
// Validate
|
||||
_ = list.Count.Should().Be((int)(itemsCount - deleted));
|
||||
_ = list.Should().Equal(testData.Skip(deleted));
|
||||
}
|
||||
_ = list.Count.Should().Be((int)itemsCount);
|
||||
_ = list.Should().Equal(testData);
|
||||
|
||||
_ = list.Should().BeEmpty();
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void RemoveAtFromTheEndShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>(testData, (int)itemsCount);
|
||||
|
||||
// Act & Validate
|
||||
for (var deleted = 1; deleted <= itemsCount; deleted++)
|
||||
{
|
||||
// Act
|
||||
list.RemoveAt(list.Count - 1);
|
||||
list.Clear();
|
||||
|
||||
// Validate
|
||||
_ = list.Count.Should().Be((int)(itemsCount - deleted));
|
||||
_ = list.Should().Equal(testData.Take((int)(itemsCount - deleted)));
|
||||
}
|
||||
_ = list.Count.Should().Be(0);
|
||||
_ = list.Should().BeEmpty();
|
||||
|
||||
_ = list.Should().BeEmpty();
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void RemoveFromTheBeginningShouldRemoveTheCorrectItem(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>(testData, (int)itemsCount);
|
||||
|
||||
// Act & Validate
|
||||
for (var deleted = 1; deleted <= itemsCount; deleted++)
|
||||
{
|
||||
// Act
|
||||
_ = list.Remove(deleted).Should().BeTrue();
|
||||
list.AddRange(testData);
|
||||
|
||||
// Validate
|
||||
_ = list.Count.Should().Be((int)(itemsCount - deleted));
|
||||
_ = list.Should().Equal(testData.Skip(deleted));
|
||||
_ = list.Count.Should().Be((int)itemsCount);
|
||||
_ = list.Should().Equal(testData);
|
||||
|
||||
// Act
|
||||
_ = list.Remove(list[(int)itemIndex]).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void RemoveFromTheEndShouldRemoveTheCorrectItem(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void InsertShouldMoveItems(string testCase, IEnumerable<long> testData, long itemsCount, in long[] itemIndexes)
|
||||
{
|
||||
// Act & Validate
|
||||
using var list = new RecyclableList<long>(testData, (int)itemsCount);
|
||||
long deleted = 0;
|
||||
foreach (var item in testData.Reverse())
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>(testData, (int)itemsCount);
|
||||
var item = list[(int)itemIndex];
|
||||
var expectedItems = list.ToList();
|
||||
expectedItems.Insert(itemIndex, item);
|
||||
|
||||
// Act
|
||||
list.Insert((int)itemIndex, item);
|
||||
|
||||
// Validate
|
||||
_ = list.Count.Should().Be((int)itemsCount + 1);
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
_ = list[(int)itemIndex].Should().Be(item);
|
||||
_ = list[(int)itemIndex + 1].Should().Be(item);
|
||||
_ = list.Should().Equal(expectedItems);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void RemoveAtShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount, in long[] itemIndexes)
|
||||
{
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>(testData, (int)itemsCount);
|
||||
var expectedItems = testData.ToList();
|
||||
expectedItems.RemoveAt((int)itemIndex);
|
||||
|
||||
// Act
|
||||
list.RemoveAt((int)itemIndex);
|
||||
|
||||
// Validate
|
||||
_ = list.Count.Should().Be((int)(itemsCount - 1));
|
||||
_ = list.Should().Equal(expectedItems);
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void RemoveShouldRemoveTheCorrectItem(string testCase, IEnumerable<long> testData, long itemsCount, in long[] itemIndexes)
|
||||
{
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableList<long>(testData, (int)itemsCount);
|
||||
var item = list[(int)itemIndex];
|
||||
var expectedItems = testData.ToList();
|
||||
expectedItems.RemoveAt(itemIndex);
|
||||
|
||||
// Act
|
||||
_ = list.Remove(item).Should().BeTrue();
|
||||
deleted++;
|
||||
|
||||
// Validate
|
||||
_ = list.Count.Should().Be((int)(itemsCount - deleted));
|
||||
_ = list.Should().Equal(testData.Take((int)(itemsCount - deleted)));
|
||||
_ = list.Count.Should().Be((int)(itemsCount - 1));
|
||||
_ = list.Should().Equal(expectedItems);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
using Recyclable.Collections;
|
||||
using MoreLinq;
|
||||
using Open.Numeric.Primes;
|
||||
using Recyclable.Collections;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Recyclable.CollectionsTests
|
||||
{
|
||||
public static class RecyclableLongListTestData
|
||||
{
|
||||
private static IEnumerable<long> DoCreateTestData(long itemsCount)
|
||||
|
||||
private static readonly object[] _sourceRefData = Enumerable.Range(1, 100).Cast<object>().ToArray();
|
||||
public static object[] SourceRefData => _sourceRefData;
|
||||
|
||||
public static IEnumerable<long> CreateTestData(long itemsCount)
|
||||
{
|
||||
for (long index = 1; index <= itemsCount; index++)
|
||||
{
|
||||
@@ -12,26 +19,38 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<long> CreateTestData(long itemsCount) => DoCreateTestData(itemsCount);
|
||||
public static IEnumerable<object> CreateRefTestData(long itemsCount)
|
||||
{
|
||||
for (long index = 1; index <= itemsCount; index++)
|
||||
{
|
||||
yield return index;
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly IEnumerable<long> ItemsCountVariants = new long[]
|
||||
{
|
||||
0, 1, 2, 3, 10, 16, 32, 64, 128, 256, 333, 512, 1_024, 8_192, 16_384,
|
||||
100_000
|
||||
//RecyclableDefaults.MinPooledArrayLength - 5, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 5, 127, 128, 129, RecyclableDefaults.MinItemsCountForParallelization
|
||||
0, 1, 2, 3, 7, 10, 16, RecyclableDefaults.MinPooledArrayLength - 5, RecyclableDefaults.MinPooledArrayLength - 1, RecyclableDefaults.MinPooledArrayLength, RecyclableDefaults.MinPooledArrayLength + 1, RecyclableDefaults.MinPooledArrayLength + 5, RecyclableDefaults.MinPooledArrayLength * 100, RecyclableDefaults.MinItemsCountForParallelization
|
||||
};
|
||||
|
||||
public static readonly IEnumerable<int> BlockSizeVariants = new int[]
|
||||
{
|
||||
1, 2, 4, 8, 10, 16, 32, 64, 128, 256, 512, 1_024, 2_048, 4_096,
|
||||
8_192, 16_384
|
||||
1, 2, 4, 16, RecyclableDefaults.MinPooledArrayLength - 5, (int)BitOperations.RoundUpToPowerOf2(RecyclableDefaults.MinPooledArrayLength)
|
||||
};
|
||||
|
||||
private static bool IsValidBlockSize(long itemsCount, long blockSize) => itemsCount is < 1024 || blockSize is > 8;
|
||||
|
||||
private static IEnumerable<object[]> GetTargetDataVariants()
|
||||
{
|
||||
foreach (var itemsCount in ItemsCountVariants)
|
||||
{
|
||||
foreach (var targetBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize(itemsCount, targetBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[] { itemsCount, targetBlockSize };
|
||||
}
|
||||
}
|
||||
@@ -39,55 +58,244 @@ namespace Recyclable.CollectionsTests
|
||||
|
||||
public static IEnumerable<object[]> TargetDataVariants => GetTargetDataVariants();
|
||||
|
||||
private static IEnumerable<object[]> CreateSourceDataVariants()
|
||||
private static IEnumerable<object[]> CombineSourceDataWithBlockSize(IEnumerable<object[]> sourceData)
|
||||
{
|
||||
foreach (var itemsCount in ItemsCountVariants)
|
||||
{
|
||||
yield return new object[] { $"int[{itemsCount}]", CreateTestData(itemsCount).ToArray(), itemsCount };
|
||||
yield return new object[] { $"List<int>(itemsCount: {itemsCount}", CreateTestData(itemsCount).ToList(), itemsCount };
|
||||
yield return new object[] { $"RecyclableList<int>(itemsCount: {itemsCount})", CreateTestData(itemsCount).ToRecyclableList(), itemsCount };
|
||||
foreach (var sourceBlockSize in BlockSizeVariants)
|
||||
{
|
||||
yield return new object[]
|
||||
{
|
||||
$"RecyclableLongList<int>(itemsCount: {itemsCount}, minBlockSize: {sourceBlockSize})",
|
||||
CreateTestData(itemsCount).ToRecyclableLongList(sourceBlockSize),
|
||||
itemsCount
|
||||
};
|
||||
}
|
||||
|
||||
yield return new object[] { $"IList<int>(itemsCount: {itemsCount})", new CustomIList<long>(CreateTestData(itemsCount)), itemsCount };
|
||||
yield return new object[] { $"IEnumerable<int>(itemsCount: {itemsCount}) with non-enumerated count", CreateTestData(itemsCount), itemsCount };
|
||||
yield return new object[] { $"IEnumerable<int>(itemsCount: {itemsCount}) without non-enumerated count", new EnumerableWithoutCount<long>(CreateTestData(itemsCount)), itemsCount };
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceDataVariants => CreateSourceDataVariants();
|
||||
|
||||
private static IEnumerable<object[]> CreateSourceEmptyDataVariants() => new[]
|
||||
{
|
||||
new object[] { "int[]", Array.Empty<long>() },
|
||||
new object[] { "List<int>", Array.Empty<long>().ToList() },
|
||||
new object[] { "RecyclableList<int>", Array.Empty<long>().ToRecyclableList() },
|
||||
new object[] { "RecyclableLongList<int>", Array.Empty<long>().ToRecyclableLongList() },
|
||||
new object[] { "IList<int>", new CustomIList<long>(Array.Empty<long>()) },
|
||||
new object[] { "IEnumerable<int> with non-enumerated count", Array.Empty<long>().AsEnumerable() },
|
||||
new object[] { "IEnumerable<int> without non-enumerated count", new EnumerableWithoutCount<long>(Array.Empty<long>()) }
|
||||
};
|
||||
|
||||
public static IEnumerable<object[]> EmptySourceDataVariants => CreateSourceEmptyDataVariants();
|
||||
|
||||
private static IEnumerable<object[]> CreateSourceTargetDataVariants()
|
||||
{
|
||||
foreach (var testData in SourceDataVariants)
|
||||
foreach (var testData in sourceData)
|
||||
{
|
||||
foreach (var targetBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize((long)testData[2], targetBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[] { testData[0], testData[1], testData[2], targetBlockSize };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceTargetDataVariants => CreateSourceTargetDataVariants();
|
||||
private static IEnumerable<object[]> CreateSourceDataVariants(long itemsCount, bool refType)
|
||||
{
|
||||
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
IDisposable disposable;
|
||||
|
||||
switch (refType)
|
||||
{
|
||||
case false:
|
||||
IEnumerable<long> testData = CreateTestData(itemsCount).ToArray();
|
||||
|
||||
yield return new object[] { $"int[{itemsCount}]", testData, itemsCount };
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
yield return new object[] { $"List<int>(itemsCount: {itemsCount}", testData.ToList(), itemsCount };
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
yield return new object[] { $"RecyclableList<int>(itemsCount: {itemsCount})", disposable = testData.ToRecyclableList(), itemsCount };
|
||||
//disposable.Dispose();
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
foreach (var sourceBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize(itemsCount, sourceBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
$"RecyclableLongList<int>(itemsCount: {itemsCount}, minBlockSize: {sourceBlockSize})",
|
||||
disposable = testData.ToRecyclableLongList(sourceBlockSize),
|
||||
itemsCount
|
||||
};
|
||||
|
||||
//disposable.Dispose();
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
}
|
||||
|
||||
yield return new object[] { $"IList<int>(itemsCount: {itemsCount})", new CustomIList<long>(testData), itemsCount };
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
yield return new object[] { $"IEnumerable<int>(itemsCount: {itemsCount}) with non-enumerated count", testData, itemsCount };
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
yield return new object[] { $"IEnumerable<int>(itemsCount: {itemsCount}) without non-enumerated count", new EnumerableWithoutCount<long>(testData), itemsCount };
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
break;
|
||||
|
||||
case true:
|
||||
IEnumerable<object> testRefData = CreateRefTestData(itemsCount).ToArray();
|
||||
|
||||
yield return new object[] { $"int[{itemsCount}]", testRefData, itemsCount };
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
yield return new object[] { $"List<int>(itemsCount: {itemsCount}", testRefData.ToList(), itemsCount };
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
yield return new object[] { $"RecyclableList<int>(itemsCount: {itemsCount})", disposable = testRefData.ToRecyclableList(), itemsCount };
|
||||
|
||||
//disposable.Dispose();
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
foreach (var sourceBlockSize in BlockSizeVariants)
|
||||
{
|
||||
if (!IsValidBlockSize(itemsCount, sourceBlockSize))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
yield return new object[]
|
||||
{
|
||||
$"RecyclableLongList<int>(itemsCount: {itemsCount}, minBlockSize: {sourceBlockSize})",
|
||||
disposable = testRefData.ToRecyclableLongList(sourceBlockSize),
|
||||
itemsCount
|
||||
};
|
||||
|
||||
//disposable.Dispose();
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
}
|
||||
|
||||
yield return new object[] { $"IList<int>(itemsCount: {itemsCount})", new CustomIList<object>(testRefData), itemsCount };
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
yield return new object[] { $"IEnumerable<int>(itemsCount: {itemsCount}) with non-enumerated count", testRefData, itemsCount };
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
yield return new object[] { $"IEnumerable<int>(itemsCount: {itemsCount}) without non-enumerated count", new EnumerableWithoutCount<object>(testRefData), itemsCount };
|
||||
//GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<object[]> CreateSourceDataVariants(bool refType)
|
||||
{
|
||||
foreach (var itemsCount in ItemsCountVariants)
|
||||
{
|
||||
foreach (var variant in CreateSourceDataVariants(itemsCount, refType))
|
||||
{
|
||||
yield return variant;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> EmptySourceDataVariants => CreateSourceDataVariants(0, false);
|
||||
public static IEnumerable<object[]> SourceDataVariants => CreateSourceDataVariants(false);
|
||||
public static IEnumerable<object[]> SourceDataWithItemIndexVariants
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var testCase in CreateSourceDataVariants(false).Where(testCase => (long)testCase[2] > 0))
|
||||
{
|
||||
var itemIndexes = CreateItemIndexVariants((long)testCase[2], RecyclableDefaults.BlockSize).ToArray();
|
||||
yield return new object[] { testCase[0], testCase[1], testCase[2], itemIndexes };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceRefDataWithItemIndexVariants
|
||||
{
|
||||
get
|
||||
{
|
||||
IEnumerable<object[]> testCases = CreateSourceDataVariants(true).Where(testCase => (long)testCase[2] > 0);
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
var itemIndexes = CreateItemIndexVariants((long)testCase[2], RecyclableDefaults.BlockSize).ToArray();
|
||||
|
||||
yield return new object[] { testCase[0], testCase[1], testCase[2], itemIndexes };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceDataWithBlockSizeVariants => CombineSourceDataWithBlockSize(SourceDataVariants);
|
||||
public static IEnumerable<object[]> SourceRefDataVariants => CreateSourceDataVariants(true);
|
||||
public static IEnumerable<object[]> SourceRefDataWithBlockSizeVariants { get; } = CombineSourceDataWithBlockSize(SourceRefDataVariants);
|
||||
|
||||
private static IEnumerable<long> _initialItemIndexVariants => new long[] { 0, 1, 2, 3, 4, 5 };
|
||||
private static IEnumerable<long> CreateItemIndexVariants(long itemsCount, int blockSize)
|
||||
{
|
||||
IEnumerable<long> primes = _initialItemIndexVariants.Concat(
|
||||
_initialItemIndexVariants.SelectMany(index => new long[] { blockSize - index, blockSize + index })
|
||||
//new long[] { blockSize - 3, blockSize - 2, blockSize - 1, blockSize, blockSize + 1, blockSize + 2, blockSize + 3 }
|
||||
).ToArray();
|
||||
|
||||
IEnumerable<long> second = Prime.Numbers.StartingAt(7)
|
||||
.TakeUntil(prime =>
|
||||
prime > ((blockSize * 2) - 1) ||
|
||||
prime >= itemsCount
|
||||
);
|
||||
|
||||
primes = primes.Concat(second).ToArray();
|
||||
|
||||
primes = primes.Concat(
|
||||
primes.Select(index => itemsCount - index - 1)
|
||||
)
|
||||
.Where(index => itemsCount > 0 && index >= 0 && index < itemsCount).ToArray()
|
||||
.Distinct().ToArray();
|
||||
|
||||
return primes;
|
||||
|
||||
//IEnumerable<long> CreateItemIndexVariants()
|
||||
//{
|
||||
//if (itemsCount > 0)
|
||||
//{
|
||||
// yield return 0;
|
||||
//}
|
||||
|
||||
//foreach (long prime in primes)
|
||||
//{
|
||||
// yield return prime;
|
||||
|
||||
// long index = itemsCount - prime;
|
||||
// if (index >= 0)
|
||||
// {
|
||||
// yield return index;
|
||||
// }
|
||||
//}
|
||||
|
||||
//for (long index = itemsCount - (blockSize * 2) - 1; index < itemsCount; index++)
|
||||
//{
|
||||
// if (index >= 0)
|
||||
// {
|
||||
// yield return index;
|
||||
// }
|
||||
//}
|
||||
|
||||
//if ((blockSize / 16 * 16) + 1 < itemsCount)
|
||||
//{
|
||||
// yield return (blockSize / 16 * 16) + 1;
|
||||
//}
|
||||
//}
|
||||
|
||||
//return CreateItemIndexVariants();
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> CombineSourceRefDataWithBlockSizeWithItemIndex(bool refType)
|
||||
{
|
||||
IEnumerable<object[]> sourceData = refType switch
|
||||
{
|
||||
false => SourceDataWithBlockSizeVariants,
|
||||
true => SourceRefDataWithBlockSizeVariants
|
||||
};
|
||||
|
||||
foreach (var testCase in sourceData)
|
||||
{
|
||||
long itemsCount = (long)testCase[2];
|
||||
if (itemsCount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
long[] itemIndexes = CreateItemIndexVariants(itemsCount, (int)testCase[3])
|
||||
.Where(_ => IsValidBlockSize((long)testCase[2], (int)testCase[3]))
|
||||
.ToArray();
|
||||
|
||||
yield return new object[] { testCase[0], testCase[1], (long)testCase[2], (int)testCase[3], itemIndexes };
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> SourceDataWithBlockSizeWithItemIndexVariants { get; } = CombineSourceRefDataWithBlockSizeWithItemIndex(false);
|
||||
public static IEnumerable<object[]> SourceRefDataWithBlockSizeWithItemIndexVariants { get; } = CombineSourceRefDataWithBlockSizeWithItemIndex(true);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using FluentAssertions;
|
||||
using Recyclable.Collections;
|
||||
using Recyclable.Collections.Linq;
|
||||
using System.Numerics;
|
||||
|
||||
#pragma warning disable xUnit1026, RCS1163, IDE0060, RCS1235
|
||||
|
||||
@@ -8,8 +9,24 @@ namespace Recyclable.CollectionsTests
|
||||
{
|
||||
public class RecyclableLongListTests
|
||||
{
|
||||
private static long CalculateExpectedCapacity(string testCase, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
var expectedCapacity = (long)BitOperations.RoundUpToPowerOf2((uint)itemsCount + 1);
|
||||
if (testCase.Contains("non-enumerated"))
|
||||
{
|
||||
expectedCapacity = (long)BitOperations.RoundUpToPowerOf2((ulong)itemsCount + RecyclableDefaults.BlockSize);
|
||||
expectedCapacity = expectedCapacity >= RecyclableDefaults.InitialCapacity ? expectedCapacity : RecyclableDefaults.InitialCapacity;
|
||||
}
|
||||
else if (targetBlockSize > itemsCount)
|
||||
{
|
||||
expectedCapacity = ((itemsCount / targetBlockSize) + (itemsCount % targetBlockSize > 0 ? 1 : 0)) * targetBlockSize;
|
||||
}
|
||||
|
||||
return expectedCapacity;
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void AddRangeShouldAddItemsInCorrectOrder(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -55,7 +72,7 @@ namespace Recyclable.CollectionsTests
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.EmptySourceDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void AddRangeShouldDoNothingWhenSourceIsEmpty(string testCase, IEnumerable<long> testData)
|
||||
public void AddRangeShouldDoNothingWhenSourceIsEmpty(string testCase, IEnumerable<long> testData, long itemsCount)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>();
|
||||
@@ -98,7 +115,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void AddRangeShouldNotOverrideItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -154,7 +171,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void AddShouldAcceptDuplicates(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -174,7 +191,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void AddShouldAddItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -193,21 +210,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void GetByIndexShouldReturnCorrectItem(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
|
||||
// Act & Validate
|
||||
foreach (var item in testData)
|
||||
{
|
||||
_ = list[item - 1].Should().Be(item);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
//[InlineData("Debugging case", new long[1] { 1 }, 1, 2)]
|
||||
public void AddShouldAddItemWhenAfterAddRange(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
@@ -226,7 +229,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ClearShouldRemoveAllItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -243,7 +246,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ConsecutiveDisposeShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -255,7 +258,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ConstructorShouldAcceptDuplicates(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -270,7 +273,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ConstructorSourceShouldInitializeList(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Act
|
||||
@@ -283,8 +286,8 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ContainsShouldFindAllItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ContainsShouldFindAllItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
if (itemsCount == 0)
|
||||
@@ -296,11 +299,10 @@ namespace Recyclable.CollectionsTests
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
_ = testData.Any().Should().BeTrue("we need items on the list that we can look for");
|
||||
|
||||
// Act
|
||||
foreach (var item in testData)
|
||||
// Act & Validate
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Validate
|
||||
_ = list.Contains(item).Should().BeTrue($"we searched for {item}");
|
||||
_ = list.Contains(list[itemIndex]).Should().BeTrue($"we searched for {list[itemIndex]}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,8 +319,8 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ContainsShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ContainsShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
if (itemsCount == 0)
|
||||
@@ -330,19 +332,15 @@ namespace Recyclable.CollectionsTests
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
_ = testData.Any().Should().BeTrue("we need items on the list that we can look for");
|
||||
|
||||
// Act
|
||||
foreach (var item in testData)
|
||||
// Act & Validate
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Validate
|
||||
_ = list.Contains(-item).Should().BeFalse();
|
||||
_ = list.Contains(-list[itemIndex]).Should().BeFalse();
|
||||
}
|
||||
|
||||
// Validate - this case is special, because this is the default item value
|
||||
_ = list.Contains(0).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
//[InlineData("Debugging case", new[] { 1L, 2, }, 2, 2)]
|
||||
public void CopyToShouldCopyAllItemsInTheCorrectOrder(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
@@ -356,7 +354,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void DisposeShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -371,7 +369,7 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void EnumerateShouldYieldAllItemsInCorrectOrder(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
@@ -390,21 +388,17 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void VersionedEnumerateShouldYieldAllItemsInCorrectOrder(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void GetByIndexShouldReturnCorrectItem(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
|
||||
// Act
|
||||
var actual = new List<long>((int)itemsCount);
|
||||
foreach(var item in (IRecyclableVersionedLongList<long>)list)
|
||||
// Act & Validate
|
||||
foreach (var item in testData)
|
||||
{
|
||||
actual.Add(item);
|
||||
_ = list[item - 1].Should().Be(item);
|
||||
}
|
||||
|
||||
// Validate
|
||||
_ = actual.Should().Equal(testData);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -419,8 +413,8 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void IndexOfShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void IndexOfShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
if (itemsCount == 0)
|
||||
@@ -433,104 +427,101 @@ namespace Recyclable.CollectionsTests
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
_ = testData.Any().Should().BeTrue("we need items on the list that we can look for");
|
||||
|
||||
// Act
|
||||
foreach (var item in testData)
|
||||
// Act & Validate
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Validate
|
||||
_ = list.IndexOf(-item).Should().Be(-1);
|
||||
_ = list.IndexOf(-list[itemIndex]).Should().Be(-1);
|
||||
}
|
||||
|
||||
// Validate
|
||||
_ = list.IndexOf(0).Should().Be(-1);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void IndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void IndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
|
||||
// Act & Validate
|
||||
foreach (var item in testData)
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
var actual = list.IndexOf(item);
|
||||
_ = actual.Should().Be((int)item - 1);
|
||||
_ = list.IndexOf(list[itemIndex]).Should().Be((int)itemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void InitializeSortClearAddRangeRemoveShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void InitializeSortClearAddRangeRemoveShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
if (itemsCount == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Act
|
||||
using RecyclableLongList<long> list = new(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
QuickSortExtensions<long>.QuickSort(list);
|
||||
|
||||
// Validate
|
||||
_ = list.LongCount.Should().Be(itemsCount);
|
||||
_ = list.Should().Equal(testData);
|
||||
|
||||
// Act
|
||||
list.Clear();
|
||||
|
||||
// Validate
|
||||
_ = list.LongCount.Should().Be(0);
|
||||
_ = list.Should().BeEmpty();
|
||||
|
||||
// Act
|
||||
list.AddRange(testData);
|
||||
|
||||
// Validate
|
||||
_ = list.LongCount.Should().Be(itemsCount);
|
||||
_ = list.Should().Equal(testData);
|
||||
|
||||
// Act
|
||||
foreach (var item in testData.Reverse())
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
using var testDataList = testData.ToRecyclableList();
|
||||
var item = testDataList[(int)itemIndex];
|
||||
|
||||
// Act
|
||||
using RecyclableLongList<long> list = new(testData, minBlockSize: targetBlockSize);
|
||||
QuickSortExtensions<long>.QuickSort(list);
|
||||
|
||||
// Validate
|
||||
_ = list.LongCount.Should().Be(itemsCount);
|
||||
_ = list.Should().Equal(testDataList);
|
||||
|
||||
// Act
|
||||
list.Clear();
|
||||
|
||||
// Validate
|
||||
_ = list.LongCount.Should().Be(0);
|
||||
_ = list.Should().BeEmpty();
|
||||
|
||||
// Act
|
||||
list.AddRange(testData);
|
||||
|
||||
// Validate
|
||||
_ = list.LongCount.Should().Be(itemsCount);
|
||||
_ = list.Should().Equal(testDataList);
|
||||
|
||||
// Prepare
|
||||
testDataList.RemoveAt((int)itemIndex);
|
||||
|
||||
// Act
|
||||
_ = list.Remove(item).Should().BeTrue();
|
||||
_ = list.LongIndexOf(item).Should().Be(RecyclableDefaults.ItemNotFoundIndexLong);
|
||||
_ = list.Contains(item).Should().BeFalse();
|
||||
_ = list.LongCount.Should().Be(itemsCount - 1);
|
||||
_ = list.Should().Equal(testDataList);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void InsertAtTheBeginningShouldMoveItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void InsertShouldMoveItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, targetBlockSize, itemsCount);
|
||||
|
||||
// Act
|
||||
foreach (var item in testData)
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
list.Insert(0, item);
|
||||
_ = list.Count.Should().Be((int)item);
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, targetBlockSize, itemsCount);
|
||||
long expectedCapacity = CalculateExpectedCapacity(testCase, itemsCount, targetBlockSize);
|
||||
|
||||
var item = list[itemIndex];
|
||||
var expectedItems = list.ToList();
|
||||
expectedItems.Insert((int)itemIndex, item);
|
||||
|
||||
// Act
|
||||
list.Insert(itemIndex, item);
|
||||
|
||||
// Validate
|
||||
|
||||
_ = list[itemIndex].Should().Be(item);
|
||||
_ = list[itemIndex + 1].Should().Be(item);
|
||||
_ = list.Capacity.Should().Be(expectedCapacity);
|
||||
_ = list.Count.Should().Be((int)itemsCount + 1);
|
||||
_ = list.Should().Equal(expectedItems);
|
||||
}
|
||||
|
||||
// Validate
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
_ = list.Count.Should().Be((int)itemsCount);
|
||||
_ = list.Should().Equal(testData.Reverse());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void InsertAtTheEndShouldAppend(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize);
|
||||
|
||||
// Act
|
||||
list.Insert(itemsCount, -1);
|
||||
|
||||
// Assert
|
||||
_ = list.LongCount.Should().Be(itemsCount + 1);
|
||||
_ = list.LongCount.Should().Be(list.Count);
|
||||
_ = list[list.LongCount - 1].Should().Be(-1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -545,8 +536,8 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void LongIndexOfShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void LongIndexOfShouldNotFindNonExistingItems(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
if (itemsCount == 0)
|
||||
{
|
||||
@@ -557,132 +548,88 @@ namespace Recyclable.CollectionsTests
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
_ = testData.Any().Should().BeTrue("we need items on the list that we can look for");
|
||||
|
||||
// Act
|
||||
foreach (var item in testData)
|
||||
// Act & Validate
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
_ = list.LongIndexOf(-list[itemIndex]).Should().Be(-1);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void LongIndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
|
||||
// Act & Validate
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
_ = list.LongIndexOf(list[itemIndex]).Should().Be(itemIndex);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void RemoveAtShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize);
|
||||
var expectedItems = list.ToList();
|
||||
expectedItems.RemoveAt((int)itemIndex);
|
||||
|
||||
// Act
|
||||
list.RemoveAt(itemIndex);
|
||||
|
||||
// Validate
|
||||
_ = list.LongIndexOf(-item).Should().Be(-1);
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
_ = list.LastBlockWithData.Should().Be((int)(list.LongCount >> list.BlockSizePow2BitShift) - ((list.LongCount & list.BlockSizeMinus1) != 0 ? 0 : 1));
|
||||
_ = list.LongCount.Should().Be(itemsCount - 1);
|
||||
_ = list.Should().Equal(expectedItems);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void RemoveShouldRemoveTheCorrectItem(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize);
|
||||
var expectedItems = list.ToList();
|
||||
var item = expectedItems[(int)itemIndex];
|
||||
expectedItems.RemoveAt((int)itemIndex);
|
||||
|
||||
// Act
|
||||
_ = list.Remove(item).Should().BeTrue();
|
||||
|
||||
// Validate
|
||||
_ = list.LongCount.Should().Be(itemsCount - 1);
|
||||
_ = list.LastBlockWithData.Should().Be((int)(list.LongCount >> list.BlockSizePow2BitShift) - ((list.LongCount & list.BlockSizeMinus1) != 0 ? 0 : 1));
|
||||
_ = list.Should().Equal(expectedItems);
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void VersionedEnumerateShouldYieldAllItemsInCorrectOrder(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
|
||||
// Act
|
||||
using var actual = new RecyclableList<long>((int)itemsCount);
|
||||
foreach (var item in (IRecyclableVersionedLongList<long>)list)
|
||||
{
|
||||
actual.Add(item);
|
||||
}
|
||||
|
||||
// Validate
|
||||
_ = list.LongIndexOf(0).Should().Be(-1);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void LongIndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
|
||||
// Act & Validate
|
||||
foreach (var item in testData)
|
||||
{
|
||||
// Act
|
||||
var index = list.LongIndexOf(item);
|
||||
|
||||
// Validate
|
||||
_ = index.Should().Be(item - 1);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void RemoveAtFromTheBeginningShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
var listAsArray = list.ToArray();
|
||||
|
||||
// Act & Validate
|
||||
for (var deleted = 1; deleted <= itemsCount; deleted++)
|
||||
{
|
||||
// Act
|
||||
list.RemoveAt(0);
|
||||
|
||||
// Validate
|
||||
_ = list.Count.Should().Be((int)(itemsCount - deleted));
|
||||
_ = list.LastBlockWithData.Should().Be((int)(list.LongCount >> list.BlockSizePow2BitShift) - ((list.LongCount & list.BlockSizeMinus1) != 0 ? 0 : 1));
|
||||
_ = list.Should().Equal(listAsArray[deleted..]);
|
||||
}
|
||||
|
||||
_ = list.Should().BeEmpty();
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
_ = list.LastBlockWithData.Should().Be(RecyclableDefaults.ItemNotFoundIndex);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void RemoveAtFromTheEndShouldSucceed(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
var listAsArray = list.ToArray();
|
||||
|
||||
// Act & Validate
|
||||
for (var deleted = 1; deleted <= itemsCount; deleted++)
|
||||
{
|
||||
// Act
|
||||
list.RemoveAt(list.Count - 1);
|
||||
|
||||
// Validate
|
||||
_ = list.Count.Should().Be((int)(itemsCount - deleted));
|
||||
_ = list.LastBlockWithData.Should().Be((int)(list.LongCount >> list.BlockSizePow2BitShift) - ((list.LongCount & list.BlockSizeMinus1) != 0 ? 0 : 1));
|
||||
_ = list.Should().Equal(listAsArray[..(int)(itemsCount - deleted)]);
|
||||
}
|
||||
|
||||
_ = list.Should().BeEmpty();
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
_ = list.LastBlockWithData.Should().Be(RecyclableDefaults.ItemNotFoundIndex);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void RemoveFromTheBeginningShouldRemoveTheCorrectItem(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, targetBlockSize, itemsCount)
|
||||
var listAsArray = list.ToArray();
|
||||
|
||||
// Act & Validate
|
||||
for (var deleted = 1; deleted <= itemsCount; deleted++)
|
||||
{
|
||||
// Act
|
||||
_ = list.Remove(deleted).Should().BeTrue();
|
||||
|
||||
// Validate
|
||||
_ = list.Count.Should().Be((int)(itemsCount - deleted));
|
||||
_ = list.LastBlockWithData.Should().Be((int)(list.LongCount >> list.BlockSizePow2BitShift) - ((list.LongCount & list.BlockSizeMinus1) != 0 ? 0 : 1));
|
||||
_ = list.Should().Equal(listAsArray[deleted..]);
|
||||
}
|
||||
|
||||
_ = list.Should().BeEmpty();
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
_ = list.LastBlockWithData.Should().Be(RecyclableDefaults.ItemNotFoundIndex);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceTargetDataVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void RemoveFromTheEndShouldRemoveTheCorrectItem(string testCase, IEnumerable<long> testData, long itemsCount, int targetBlockSize)
|
||||
{
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize: targetBlockSize, itemsCount);
|
||||
var listAsArray = testData.ToArray();
|
||||
int removedCount = 0;
|
||||
foreach (var item in testData.Reverse())
|
||||
{
|
||||
// Act & Validate
|
||||
_ = list.Remove(item).Should().BeTrue($"we search for {item} which should exist");
|
||||
removedCount++;
|
||||
var expectedList = listAsArray[..((int)itemsCount - removedCount)];
|
||||
_ = list.LastBlockWithData.Should().Be((int)(list.LongCount >> list.BlockSizePow2BitShift) - ((list.LongCount & list.BlockSizeMinus1) != 0 ? 0 : 1));
|
||||
_ = list.LongCount.Should().Be(expectedList.Length);
|
||||
_ = list.Should().Equal(expectedList);
|
||||
}
|
||||
|
||||
_ = list.Should().BeEmpty();
|
||||
_ = list.Capacity.Should().BeGreaterThanOrEqualTo((int)itemsCount);
|
||||
_ = list.LastBlockWithData.Should().Be(RecyclableDefaults.ItemNotFoundIndex);
|
||||
_ = actual.Should().Equal(testData);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user