UnityGame/Library/PackageCache/com.unity.collections/Unity.Collections.Tests/NativeArraySortTests.cs
2024-10-27 10:53:47 +03:00

576 lines
16 KiB
C#

using System;
using System.Collections.Generic;
using NUnit.Framework;
using Unity.Collections;
using Unity.Collections.Tests;
using Unity.Jobs;
using Assert = FastAssert;
internal class MathTests : CollectionsTestCommonBase
{
[Test]
public void Tests()
{
Assert.AreEqual(0, CollectionHelper.Log2Floor(1));
Assert.AreEqual(1, CollectionHelper.Log2Floor(2));
Assert.AreEqual(1, CollectionHelper.Log2Floor(3));
Assert.AreEqual(2, CollectionHelper.Log2Floor(4));
Assert.AreEqual(3, CollectionHelper.Log2Floor(15));
Assert.AreEqual(4, CollectionHelper.Log2Floor(16));
Assert.AreEqual(4, CollectionHelper.Log2Floor(19));
Assert.AreEqual(30, CollectionHelper.Log2Floor(int.MaxValue));
Assert.AreEqual(16, CollectionHelper.Log2Floor(1 << 16));
Assert.AreEqual(-1, CollectionHelper.Log2Floor(0));
}
}
internal class NativeArraySortTests : CollectionsTestCommonBase
{
[Test]
public void SortNativeArray_RandomInts_ReturnSorted([Values(0, 1, 10, 1000, 10000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<int> array = new NativeArray<int>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = random.NextInt(int.MinValue, int.MaxValue);
}
array.Sort();
int min = int.MinValue;
foreach (var i in array)
{
Assert.LessOrEqual(min, i);
min = i;
}
array.Dispose();
}
[Test]
public void SortNativeArray_SortedInts_ReturnSorted([Values(0, 1, 10, 1000, 10000)] int size)
{
NativeArray<int> array = new NativeArray<int>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = i;
}
array.Sort();
int min = int.MinValue;
foreach (var i in array)
{
Assert.LessOrEqual(min, i);
min = i;
}
array.Dispose();
}
[Test]
public void SortNativeArray_RandomBytes_ReturnSorted([Values(0, 1, 10, 1000, 10000, 100000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<byte> array = new NativeArray<byte>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = (byte)random.NextInt(byte.MinValue, byte.MinValue);
}
array.Sort();
int min = int.MinValue;
foreach (var i in array)
{
Assert.LessOrEqual(min, i);
min = i;
}
array.Dispose();
}
[Test]
public void SortNativeArray_RandomShorts_ReturnSorted([Values(0, 1, 10, 1000, 10000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<short> array = new NativeArray<short>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = (short)random.NextInt(short.MinValue, short.MaxValue);
}
array.Sort();
int min = int.MinValue;
foreach (var i in array)
{
Assert.LessOrEqual(min, i);
min = i;
}
array.Dispose();
}
[Test]
public void SortNativeArray_RandomFloats_ReturnSorted([Values(0, 1, 10, 1000, 10000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<float> array = new NativeArray<float>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = (float)random.NextDouble();
}
array.Sort();
float min = float.MinValue;
foreach (var i in array)
{
Assert.LessOrEqual(min, i);
min = i;
}
array.Dispose();
}
struct ComparableType : IComparable<ComparableType>
{
public int value;
public int CompareTo(ComparableType other) => value.CompareTo(other.value);
}
[Test]
public void SortNativeArray_RandomComparableType_ReturnSorted([Values(0, 1, 10, 1000, 10000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<ComparableType> array = new NativeArray<ComparableType>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = new ComparableType
{
value = random.NextInt(int.MinValue, int.MaxValue)
};
}
array.Sort();
int min = int.MinValue;
foreach (var i in array)
{
Assert.LessOrEqual(min, i.value);
min = i.value;
}
array.Dispose();
}
struct NonComparableType
{
public int value;
}
struct NonComparableTypeComparator : IComparer<NonComparableType>
{
public int Compare(NonComparableType lhs, NonComparableType rhs)
{
return lhs.value.CompareTo(rhs.value);
}
}
[Test]
public void SortNativeArray_RandomNonComparableType_ReturnSorted([Values(0, 1, 10, 1000, 10000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<NonComparableType> array = new NativeArray<NonComparableType>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = new NonComparableType
{
value = random.NextInt(int.MinValue, int.MaxValue)
};
}
array.Sort(new NonComparableTypeComparator());
int min = int.MinValue;
foreach (var i in array)
{
Assert.LessOrEqual(min, i.value);
min = i.value;
}
array.Dispose();
}
[Test]
public void SortNativeSlice_ReturnSorted()
{
var random = new Unity.Mathematics.Random(1);
NativeArray<int> array = new NativeArray<int>(1000, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; ++i)
{
array[i] = random.NextInt(int.MinValue, int.MaxValue);
}
var slice = new NativeSlice<int>(array, 200, 600);
slice.Sort();
int min = int.MinValue;
foreach (var i in slice)
{
Assert.LessOrEqual(min, i);
min = i;
}
array.Dispose();
}
[Test]
public void SortNativeSlice_DoesNotChangeArrayBeyondLimits()
{
var random = new Unity.Mathematics.Random(1);
NativeArray<int> array = new NativeArray<int>(1000, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; ++i)
{
array[i] = random.NextInt(int.MinValue, int.MaxValue);
}
var backupArray = new NativeArray<int>(array.Length, Allocator.Persistent);
backupArray.CopyFrom(array);
var slice = new NativeSlice<int>(array, 200, 600);
slice.Sort();
for (var i = 0; i < 200; ++i)
{
Assert.AreEqual(backupArray[i], array[i]);
}
for (var i = 800; i < 1000; ++i)
{
Assert.AreEqual(backupArray[i], array[i]);
}
array.Dispose();
backupArray.Dispose();
}
[Test]
[TestRequiresDotsDebugOrCollectionChecks]
public void SortNativeSlice_WithCustomStride_ThrowsInvalidOperationException()
{
var random = new Unity.Mathematics.Random(1);
NativeArray<int> array = new NativeArray<int>(10, Allocator.Persistent);
for (int i = 0; i < array.Length; ++i)
{
array[i] = random.NextInt(int.MinValue, int.MaxValue);
}
var slice = new NativeSlice<int>(array, 2, 6);
var sliceWithCustomStride = slice.SliceWithStride<short>();
Assert.DoesNotThrow(() => slice.Sort());
Assert.Throws<InvalidOperationException>(() => sliceWithCustomStride.Sort());
array.Dispose();
}
}
internal class NativeSliceTests : CollectionsTestCommonBase
{
[Test]
public void NativeSlice_CopyTo()
{
NativeArray<int> array = new NativeArray<int>(1000, Allocator.Persistent);
for (int i = 0; i < array.Length; ++i)
{
array[i] = i;
}
var copyToArray = new int[600];
for (int i = 0; i < copyToArray.Length; ++i)
{
copyToArray[i] = 0x12345678;
}
var slice = new NativeSlice<int>(array, 200, 600);
slice.CopyTo(copyToArray);
for (var i = 0; i < 600; ++i)
{
Assert.AreEqual(copyToArray[i], array[i + 200]);
}
array.Dispose();
}
[Test]
public void NativeSlice_CopyFrom()
{
NativeArray<int> array = new NativeArray<int>(1000, Allocator.Persistent);
for (int i = 0; i < array.Length; ++i)
{
array[i] = i;
}
var copyFromArray = new int[600];
for (int i = 0; i < copyFromArray.Length; ++i)
{
copyFromArray[i] = 0x12345678;
}
var slice = new NativeSlice<int>(array, 200, 600);
slice.CopyFrom(copyFromArray);
for (var i = 0; i < 600; ++i)
{
Assert.AreEqual(slice[i], 0x12345678);
}
array.Dispose();
}
[Test]
public void SortJobNativeArray_RandomInts_ReturnSorted([Values(0, 1, 10, 1000, 10000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<int> array = new NativeArray<int>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = random.NextInt(int.MinValue, int.MaxValue);
}
array.SortJob().Schedule().Complete();
int min = int.MinValue;
foreach (var i in array)
{
Assert.LessOrEqual(min, i);
min = i;
}
array.Dispose();
}
[Test]
public void SortJobNativeArray_SortedInts_ReturnSorted([Values(0, 1, 10, 1000, 10000)] int size)
{
NativeArray<int> array = new NativeArray<int>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = i;
}
array.SortJob().Schedule().Complete();
int min = int.MinValue;
foreach (var i in array)
{
Assert.LessOrEqual(min, i);
min = i;
}
array.Dispose();
}
[Test]
public void SortJobNativeArray_RandomBytes_ReturnSorted([Values(0, 1, 10, 1000, 10000, 100000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<byte> array = new NativeArray<byte>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = (byte)random.NextInt(byte.MinValue, byte.MinValue);
}
array.SortJob().Schedule().Complete();
int min = int.MinValue;
foreach (var i in array)
{
Assert.LessOrEqual(min, i);
min = i;
}
array.Dispose();
}
struct DescendingComparer<T> : IComparer<T> where T : IComparable<T>
{
public int Compare(T x, T y) => y.CompareTo(x);
}
[Test]
public void SortJobNativeArray_RandomBytes_ReturnSorted_Descending([Values(0, 1, 10, 1000, 10000, 100000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<byte> array = new NativeArray<byte>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = (byte)random.NextInt(byte.MinValue, byte.MinValue);
}
array.SortJob(new DescendingComparer<byte>()).Schedule().Complete();
int max = int.MaxValue;
foreach (var i in array)
{
Assert.GreaterOrEqual(max, i);
max = i;
}
array.Dispose();
}
[Test]
public void SortJobNativeArray_RandomShorts_ReturnSorted([Values(0, 1, 10, 1000, 10000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<short> array = new NativeArray<short>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = (short)random.NextInt(short.MinValue, short.MaxValue);
}
array.SortJob().Schedule().Complete();
int min = int.MinValue;
foreach (var i in array)
{
Assert.LessOrEqual(min, i);
min = i;
}
array.Dispose();
}
[Test]
public void SortNativeArrayByJob_RandomShorts_ReturnSorted_Descending([Values(0, 1, 10, 1000, 10000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<short> array = new NativeArray<short>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = (short)random.NextInt(short.MinValue, short.MaxValue);
}
array.SortJob(new DescendingComparer<short>()).Schedule().Complete();
int max = int.MaxValue;
foreach (var i in array)
{
Assert.GreaterOrEqual(max, i);
max = i;
}
array.Dispose();
}
[Test]
public void SortJobNativeArray_RandomFloats_ReturnSorted([Values(0, 1, 10, 1000, 10000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<float> array = new NativeArray<float>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = (float)random.NextDouble();
}
array.SortJob().Schedule().Complete();
float min = float.MinValue;
foreach (var i in array)
{
Assert.LessOrEqual(min, i);
min = i;
}
array.Dispose();
}
[Test]
public void SortJobNativeArray_RandomFloats_ReturnSorted_Descending([Values(0, 1, 10, 1000, 10000)] int size)
{
var random = new Unity.Mathematics.Random(1);
NativeArray<float> array = new NativeArray<float>(size, Allocator.Persistent);
Assert.IsTrue(array.IsCreated);
for (int i = 0; i < array.Length; i++)
{
array[i] = (float)random.NextDouble();
}
array.SortJob(new DescendingComparer<float>()).Schedule().Complete();
float max = float.MaxValue;
foreach (var i in array)
{
Assert.GreaterOrEqual(max, i);
max = i;
}
array.Dispose();
}
struct FilterOdd : IJobFilter
{
public bool Execute(int index) => index % 2 == 0;
}
[Test]
public void SortJobNativeList_UseInPreviousJob()
{
var rng = new Unity.Mathematics.Random(123);
NativeList<int> indices = new NativeList<int>(10, Allocator.TempJob);
for (int i = 0; i < 10; i++)
{
indices.Add(rng.NextInt(100));
}
var handle = new FilterOdd().ScheduleFilter(indices);
var sortJob = indices.SortJobDefer(new DescendingComparer<int>());
handle = sortJob.Schedule(handle);
handle.Complete();
float max = float.MaxValue;
foreach (var i in indices)
{
Assert.IsTrue(0 == (i & 1));
Assert.GreaterOrEqual(max, i);
max = i;
}
indices.Dispose();
}
}