RecyclableLongList.Compatibility.List.CopyTo() implemented. Tests extended.
This commit is contained in:
1 parent
89626511d6
commit
f77d5024c3
4 files changed
+120
-28
No files matched your search
+1
-1
@@ -13,7 +13,7 @@
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
|
||||
<PackageReference Include="Recyclable.Collections" Version="0.0.6.1" />
|
||||
<PackageReference Include="Recyclable.Collections.TestData" Version="0.0.3.1" />
|
||||
<PackageReference Include="Recyclable.Collections.TestData" Version="0.0.3.2" />
|
||||
<PackageReference Include="xunit" Version="2.5.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
+65
-26
@@ -35,8 +35,8 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void BinarySearchShouldFindAllItemsWhenConstrainedRange(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in long[] itemIndexes)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexWithRangeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void BinarySearchShouldFindAllItemsWhenConstrainedRange(string testCase, IEnumerable<long> 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");
|
||||
|
||||
@@ -45,15 +45,13 @@ namespace Recyclable.CollectionsTests
|
||||
var comparer = Comparer<long>.Default;
|
||||
var expectedData = testData.ToList();
|
||||
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
foreach (var (itemIndex, rangedItemsCount) in itemRanges)
|
||||
{
|
||||
var rangeSize = (int)Math.Min(itemsCount - itemIndex, 4);
|
||||
var expectedItem = expectedData[(int)itemIndex];
|
||||
var startItemIndex = (int)(rangeSize > 2 ? Math.Max(0, itemIndex - 2) : itemIndex);
|
||||
var expected = expectedData.BinarySearch(startItemIndex, rangeSize, expectedItem, comparer);
|
||||
var expected = expectedData.BinarySearch((int)itemIndex, (int)rangedItemsCount, expectedItem, comparer);
|
||||
|
||||
// Act
|
||||
var actual = list.BinarySearch(startItemIndex, rangeSize, expectedItem, comparer);
|
||||
var actual = list.BinarySearch((int)itemIndex, (int)rangedItemsCount, expectedItem, comparer);
|
||||
|
||||
// Validate
|
||||
_ = actual.Should().Be(expected);
|
||||
@@ -111,8 +109,8 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void BinarySearchShouldNotFindNonExistingItemsWhenConstrainedRange(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in long[] itemIndexes)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexWithRangeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void BinarySearchShouldNotFindNonExistingItemsWhenConstrainedRange(string testCase, IEnumerable<long> 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");
|
||||
|
||||
@@ -120,20 +118,19 @@ namespace Recyclable.CollectionsTests
|
||||
var comparer = Comparer<long>.Default;
|
||||
var expectedData = testData.ToList();
|
||||
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
foreach (var (itemIndex, rangedItemsCount) in itemRanges)
|
||||
{
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize, initialCapacity: itemsCount);
|
||||
list.RemoveAt(itemIndex);
|
||||
var expectedItem = expectedData[(int)itemIndex];
|
||||
var expectedRangedData = testData.ToList();
|
||||
expectedRangedData.RemoveAt((int)itemIndex);
|
||||
var expectedRangeSize = itemIndex + rangedItemsCount < expectedRangedData.Count ? rangedItemsCount : expectedRangedData.Count - itemIndex;
|
||||
// Now we have 1 element less on the lists
|
||||
var rangeSize = (int)Math.Max(Math.Min(itemsCount - itemIndex - 2, 4), 0);
|
||||
int startItemIndex = (int)(rangeSize > 2 ? Math.Max(0, itemIndex - 2 - 1) : Math.Max(0, itemIndex - 1));
|
||||
var expected = expectedRangedData.BinarySearch(startItemIndex, rangeSize, expectedItem, comparer);
|
||||
var expected = expectedRangedData.BinarySearch((int)itemIndex, (int)expectedRangeSize, expectedItem, comparer);
|
||||
|
||||
// Act
|
||||
var actual = list.BinarySearch(startItemIndex, rangeSize, expectedItem, comparer);
|
||||
var actual = list.BinarySearch((int)itemIndex, (int)expectedRangeSize, expectedItem, comparer);
|
||||
|
||||
// Validate
|
||||
_ = actual.Should().Be(expected);
|
||||
@@ -212,6 +209,9 @@ namespace Recyclable.CollectionsTests
|
||||
|
||||
Assert.Throws<ArgumentException>(() => _ = expectedData.BinarySearch((int)itemIndex + 1, itemsCount, expectedItem, comparer));
|
||||
Assert.Throws<ArgumentException>(() => _ = list.BinarySearch((int)itemIndex + 1, itemsCount, expectedItem, comparer));
|
||||
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => _ = expectedData.BinarySearch((int)itemIndex + 1, -1, expectedItem, comparer));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => _ = list.BinarySearch((int)itemIndex + 1, -1, expectedItem, comparer));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,32 +232,41 @@ namespace Recyclable.CollectionsTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void CopyToShouldCopyAllItemsInTheCorrectOrderWhenConstrainedRange(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in long[] itemIndexes)
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexWithRangeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void CopyToShouldCopyAllItemsInTheCorrectOrderWhenConstrainedIndex(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in (long ItemIndex, long RangedItemsCount)[] itemIndexRanges)
|
||||
{
|
||||
// Prepare
|
||||
var expectedData = testData.ToList();
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
foreach (var (itemIndex, _) in itemIndexRanges)
|
||||
{
|
||||
var rangedItemsCount = (int)Math.Max(itemIndex, 1);
|
||||
TestCopyTo(0, rangedItemsCount);
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize, initialCapacity: itemsCount);
|
||||
long[] expectedItems = new long[expectedData.Count];
|
||||
expectedData.CopyTo((int)itemIndex, expectedItems, (int)itemIndex, (int)(expectedData.Count - itemIndex));
|
||||
long[] actualItems = new long[expectedData.Count];
|
||||
|
||||
rangedItemsCount = (int)(itemsCount - itemIndex);
|
||||
TestCopyTo((int)itemIndex, rangedItemsCount);
|
||||
// Act
|
||||
list.CopyTo((int)itemIndex, actualItems, (int)itemIndex);
|
||||
|
||||
rangedItemsCount = 1;
|
||||
TestCopyTo((int)itemIndex, rangedItemsCount);
|
||||
// Validate
|
||||
_ = actualItems.Should().Equal(expectedItems);
|
||||
}
|
||||
}
|
||||
|
||||
void TestCopyTo(int itemIndex, int rangedItemsCount)
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexWithRangeVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void CopyToShouldCopyAllItemsInTheCorrectOrderWhenConstrainedRange(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in (long ItemIndex, long RangedItemsCount)[] itemIndexRanges)
|
||||
{
|
||||
// Prepare
|
||||
var expectedData = testData.ToList();
|
||||
foreach (var (itemIndex, rangedItemsCount) in itemIndexRanges)
|
||||
{
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize, initialCapacity: itemsCount);
|
||||
long[] expectedItems = new long[rangedItemsCount + itemIndex];
|
||||
expectedData.CopyTo(itemIndex, expectedItems, itemIndex, rangedItemsCount);
|
||||
expectedData.CopyTo((int)itemIndex, expectedItems, (int)itemIndex, (int)rangedItemsCount);
|
||||
long[] actualItems = new long[rangedItemsCount + itemIndex];
|
||||
|
||||
// Act
|
||||
list.CopyTo(itemIndex, actualItems, itemIndex, rangedItemsCount);
|
||||
list.CopyTo((int)itemIndex, actualItems, (int)itemIndex, (int)rangedItemsCount);
|
||||
|
||||
// Validate
|
||||
_ = actualItems.Should().Equal(expectedItems);
|
||||
@@ -282,6 +291,36 @@ namespace Recyclable.CollectionsTests
|
||||
_ = copiedItems.Should().Equal(testData);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void CopyToShouldThrowArgumentOutOfRangeWhenOutsideRange(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in long[] itemIndexes)
|
||||
{
|
||||
_ = testData.Any().Should().BeTrue("we need items on the list that we can look for");
|
||||
|
||||
// Prepare
|
||||
using var list = new RecyclableLongList<long>(testData, minBlockSize, initialCapacity: itemsCount);
|
||||
var comparer = Comparer<long>.Default;
|
||||
var expectedData = testData.ToList();
|
||||
var actual = new long[itemsCount];
|
||||
|
||||
foreach (var itemIndex in itemIndexes)
|
||||
{
|
||||
|
||||
// Act && Validate
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => expectedData.CopyTo(-1, actual, 0, (int)itemIndex));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list.CopyTo(-1, actual, 0, (int)itemIndex));
|
||||
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => expectedData.CopyTo(0, actual, -1, (int)itemIndex));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list.CopyTo(0, actual, -1, (int)itemIndex));
|
||||
|
||||
Assert.Throws<ArgumentException>(() => expectedData.CopyTo(0, actual, (int)itemIndex + 1, itemsCount));
|
||||
Assert.Throws<ArgumentException>(() => list.CopyTo(0, actual, (int)itemIndex + 1, itemsCount));
|
||||
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => expectedData.CopyTo(0, actual, (int)itemIndex + 1, -1));
|
||||
Assert.Throws<ArgumentOutOfRangeException>(() => list.CopyTo(0, actual, (int)itemIndex + 1, -1));
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))]
|
||||
public void ExistsShouldFindAllItems(string testCase, IEnumerable<long> testData, int itemsCount, int minBlockSize, in long[] itemIndexes)
|
||||
|
||||
@@ -302,8 +302,36 @@ namespace Recyclable.Collections
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
//public static void CopyTo<T>(this RecyclableLongList<T> list, int index, T[] array, int arrayIndex, int count) => RecyclableLongList<T>.Helpers.CopyTo(list._memoryBlocks, index, list._blockSize, count, array, arrayIndex);
|
||||
public static void CopyTo<T>(this RecyclableLongList<T> list, int index, T[] array, int arrayIndex, int count) => DoCopyTo(list._memoryBlocks, index, list._blockSize, count, array, arrayIndex);
|
||||
public static void CopyTo<T>(this RecyclableLongList<T> list, int index, T[] array, int arrayIndex) => DoCopyTo(list._memoryBlocks, index, list._blockSize, list._longCount - index, array, arrayIndex);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
|
||||
public static void CopyTo<T>(this RecyclableLongList<T> list, int index, T[] array, int arrayIndex, int count)
|
||||
{
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException_Index();
|
||||
}
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException_Count();
|
||||
}
|
||||
|
||||
if (arrayIndex < 0)
|
||||
{
|
||||
ThrowHelper.ThrowArgumentOutOfRangeException(nameof(arrayIndex), "Parameter `arrayIndex` has invalid value. It must be within the no. of elements in the collection");
|
||||
}
|
||||
|
||||
if (index + count > list._longCount || arrayIndex + count > list._longCount)
|
||||
{
|
||||
Compatibility.List.ThrowHelper.ThrowArgumentException_Count();
|
||||
}
|
||||
|
||||
DoCopyTo(list._memoryBlocks, index, list._blockSize, count, array, arrayIndex);
|
||||
|
||||
}
|
||||
|
||||
public static void ForEach<T>(this RecyclableLongList<T> list, Action<T> action)
|
||||
{
|
||||
//int sourceItemsCount = list._count;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma warning disable IDE0022, CA2208
|
||||
|
||||
namespace Recyclable.Collections.Compatibility.List
|
||||
{
|
||||
[Obsolete("This class is temporary until new Recyclable.Collections is released")]
|
||||
internal static class ThrowHelper
|
||||
{
|
||||
public static void ThrowArgumentException(string argumentName) => throw new ArgumentException("Parameter has invalid value. ", argumentName);
|
||||
public static void ThrowArgumentException(string argumentName, Exception? innerException) => throw new ArgumentException("Parameter has invalid value. ", argumentName, innerException);
|
||||
public static void ThrowArgumentException(string argumentName, string message) => throw new ArgumentException(message, argumentName);
|
||||
public static void ThrowArgumentException(string argumentName, string message, Exception? innerException) => throw new ArgumentException(message, argumentName, innerException);
|
||||
public static void ThrowArgumentException_Index() => throw new ArgumentException("Parameter has invalid value", "index");
|
||||
public static void ThrowArgumentException_Index(Exception? innerException) => throw new ArgumentException("Parameter has invalid value", "index", innerException);
|
||||
public static void ThrowArgumentException_Count() => throw new ArgumentException("Parameter has invalid value", "count");
|
||||
public static void ThrowArgumentException_Count(Exception? innerException) => throw new ArgumentException("Parameter has invalid value", "count", innerException);
|
||||
public static void ThrowArgumentOutOfRangeException(string argumentName) => throw new ArgumentOutOfRangeException(argumentName);
|
||||
public static void ThrowArgumentOutOfRangeException(string argumentName, Exception? innerException) => throw new ArgumentOutOfRangeException($"Argument {argumentName} is out of range", innerException);
|
||||
public static void ThrowArgumentOutOfRangeException(string argumentName, string message) => throw new ArgumentOutOfRangeException(argumentName, message);
|
||||
public static void ThrowWrongReturnedArraySizeException(int returnedLength, int blockSize) => throw new InvalidOperationException($"The array size {returnedLength} doesn't match the size {blockSize} of the pool buffer and cannot be returned to this pool.");
|
||||
public static void ThrowArgumentOutOfRangeException_Index() => throw new ArgumentOutOfRangeException("index", "Parameter `index` has invalid value. It must be within the no. of elements in the collection");
|
||||
public static void ThrowArgumentOutOfRangeException_Index(Exception? innerException) => throw new ArgumentOutOfRangeException("Parameter `index` has invalid value. It must be within the no. of elements in the collection", innerException);
|
||||
public static void ThrowArgumentOutOfRangeException_Count() => throw new ArgumentOutOfRangeException("count", "Parameter `count` has invalid value. Combined with index, it must be within the no. of elements in the collection");
|
||||
public static void ThrowArgumentOutOfRangeException_Count(Exception? innerException) => throw new ArgumentOutOfRangeException("Parameter `count` has invalid value. Combined with index, it must be within the no. of elements in the collection", innerException);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user