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

527 lines
19 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using NUnit.Framework;
using Unity.Collections;
using Unity.Collections.LowLevel.Unsafe;
using System.Text;
using Unity.Burst;
using Unity.Jobs;
namespace Unity.Collections.Tests
{
internal class UnsafeTextTests
{
void AssertAreEqualInTest(string expected, in UnsafeText actual)
{
var actualString = actual.ToString();
Assert.AreEqual(expected, actualString);
}
// NOTE: If you call this function from Mono and T is not marshalable - your app (Editor or the player built with Mono scripting backend) could/will crash.
bool IsMarshalable<T>() where T : unmanaged
{
try
{
unsafe
{
var size = System.Runtime.InteropServices.Marshal.SizeOf(typeof(T));
IntPtr memoryIntPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(size);
try
{
var obj = new T();
System.Runtime.InteropServices.Marshal.StructureToPtr(obj, memoryIntPtr, false);
System.Runtime.InteropServices.Marshal.DestroyStructure<T>(memoryIntPtr);
}
finally
{
System.Runtime.InteropServices.Marshal.FreeHGlobal(memoryIntPtr);
}
return true;
}
}
catch (Exception e)
{
UnityEngine.Debug.LogError("ERROR in IsMarshalable<" + typeof(T).FullName + "> " + e);
return false;
}
}
[Test]
public void UnsafeTextIsMarshalable()
{
var result = IsMarshalable<UnsafeText>();
Assert.IsTrue(result);
}
[Test]
public unsafe void UnsafeTextCorrectBinaryHeader()
{
var text = new UnsafeText(42, Allocator.Persistent);
var ptr = text.GetUnsafePtr();
Assert.AreEqual(0 + 1, text.m_UntypedListData.m_length);
Assert.AreEqual(Allocator.Persistent, text.m_UntypedListData.Allocator.ToAllocator);
Assert.IsTrue(ptr == text.m_UntypedListData.Ptr, "ptr != text.m_UntypedListData.Ptr");
var listOfBytesCast = text.AsUnsafeListOfBytes();
Assert.AreEqual(0 + 1, listOfBytesCast.Length);
Assert.AreEqual(Allocator.Persistent, listOfBytesCast.Allocator.ToAllocator);
Assert.IsTrue(ptr == listOfBytesCast.Ptr, "ptr != listOfBytesCast.Ptr");
Assert.AreEqual(text.m_UntypedListData.m_capacity, listOfBytesCast.Capacity);
text.Dispose();
}
[Test]
public void UnsafeTextCorrectLengthAfterClear()
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
Assert.True(aa.IsCreated);
Assert.AreEqual(0, aa.Length, "Length after creation is not 0");
aa.AssertNullTerminated();
aa.Junk();
aa.Clear();
Assert.AreEqual(0, aa.Length, "Length after clear is not 0");
aa.AssertNullTerminated();
aa.Dispose();
}
[Test]
public void UnsafeTextFormatExtension1Params()
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
Assert.True(aa.IsCreated);
aa.Junk();
FixedString32Bytes format = "{0}";
FixedString32Bytes arg0 = "a";
aa.AppendFormat(format, arg0);
aa.Append('a');
aa.AssertNullTerminated();
AssertAreEqualInTest("aa", aa);
aa.Dispose();
}
[Test]
public void UnsafeTextFormatExtension2Params()
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
aa.Junk();
FixedString32Bytes format = "{0} {1}";
FixedString32Bytes arg0 = "a";
FixedString32Bytes arg1 = "b";
aa.AppendFormat(format, arg0, arg1);
AssertAreEqualInTest("a b", aa);
aa.AssertNullTerminated();
aa.Dispose();
}
[Test]
public void UnsafeTextFormatExtension3Params()
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
aa.Junk();
FixedString32Bytes format = "{0} {1} {2}";
FixedString32Bytes arg0 = "a";
FixedString32Bytes arg1 = "b";
FixedString32Bytes arg2 = "c";
aa.AppendFormat(format, arg0, arg1, arg2);
AssertAreEqualInTest("a b c", aa);
aa.AssertNullTerminated();
aa.Dispose();
}
[Test]
public void UnsafeTextFormatExtension4Params()
{
UnsafeText aa = new UnsafeText(512, Allocator.Temp);
aa.Junk();
FixedString32Bytes format = "{0} {1} {2} {3}";
FixedString32Bytes arg0 = "a";
FixedString32Bytes arg1 = "b";
FixedString32Bytes arg2 = "c";
FixedString32Bytes arg3 = "d";
aa.AppendFormat(format, arg0, arg1, arg2, arg3);
AssertAreEqualInTest("a b c d", aa);
aa.AssertNullTerminated();
aa.Dispose();
}
[Test]
public void UnsafeTextFormatExtension5Params()
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
aa.Junk();
FixedString32Bytes format = "{0} {1} {2} {3} {4}";
FixedString32Bytes arg0 = "a";
FixedString32Bytes arg1 = "b";
FixedString32Bytes arg2 = "c";
FixedString32Bytes arg3 = "d";
FixedString32Bytes arg4 = "e";
aa.AppendFormat(format, arg0, arg1, arg2, arg3, arg4);
AssertAreEqualInTest("a b c d e", aa);
aa.AssertNullTerminated();
aa.Dispose();
}
[Test]
public void UnsafeTextFormatExtension6Params()
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
aa.Junk();
FixedString32Bytes format = "{0} {1} {2} {3} {4} {5}";
FixedString32Bytes arg0 = "a";
FixedString32Bytes arg1 = "b";
FixedString32Bytes arg2 = "c";
FixedString32Bytes arg3 = "d";
FixedString32Bytes arg4 = "e";
FixedString32Bytes arg5 = "f";
aa.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5);
AssertAreEqualInTest("a b c d e f", aa);
aa.AssertNullTerminated();
aa.Dispose();
}
[Test]
public void UnsafeTextFormatExtension7Params()
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
aa.Junk();
FixedString32Bytes format = "{0} {1} {2} {3} {4} {5} {6}";
FixedString32Bytes arg0 = "a";
FixedString32Bytes arg1 = "b";
FixedString32Bytes arg2 = "c";
FixedString32Bytes arg3 = "d";
FixedString32Bytes arg4 = "e";
FixedString32Bytes arg5 = "f";
FixedString32Bytes arg6 = "g";
aa.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5, arg6);
AssertAreEqualInTest("a b c d e f g", aa);
aa.AssertNullTerminated();
aa.Dispose();
}
[Test]
public void UnsafeTextFormatExtension8Params()
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
aa.Junk();
FixedString128Bytes format = "{0} {1} {2} {3} {4} {5} {6} {7}";
FixedString32Bytes arg0 = "a";
FixedString32Bytes arg1 = "b";
FixedString32Bytes arg2 = "c";
FixedString32Bytes arg3 = "d";
FixedString32Bytes arg4 = "e";
FixedString32Bytes arg5 = "f";
FixedString32Bytes arg6 = "g";
FixedString32Bytes arg7 = "h";
aa.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
AssertAreEqualInTest("a b c d e f g h", aa);
aa.AssertNullTerminated();
aa.Dispose();
}
[Test]
public void UnsafeTextFormatExtension9Params()
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
aa.Junk();
FixedString128Bytes format = "{0} {1} {2} {3} {4} {5} {6} {7} {8}";
FixedString32Bytes arg0 = "a";
FixedString32Bytes arg1 = "b";
FixedString32Bytes arg2 = "c";
FixedString32Bytes arg3 = "d";
FixedString32Bytes arg4 = "e";
FixedString32Bytes arg5 = "f";
FixedString32Bytes arg6 = "g";
FixedString32Bytes arg7 = "h";
FixedString32Bytes arg8 = "i";
aa.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
AssertAreEqualInTest("a b c d e f g h i", aa);
aa.AssertNullTerminated();
aa.Dispose();
}
[Test]
public void UnsafeTextFormatExtension10Params()
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
aa.Junk();
FixedString128Bytes format = "{0} {1} {2} {3} {4} {5} {6} {7} {8} {9}";
FixedString32Bytes arg0 = "a";
FixedString32Bytes arg1 = "b";
FixedString32Bytes arg2 = "c";
FixedString32Bytes arg3 = "d";
FixedString32Bytes arg4 = "e";
FixedString32Bytes arg5 = "f";
FixedString32Bytes arg6 = "g";
FixedString32Bytes arg7 = "h";
FixedString32Bytes arg8 = "i";
FixedString32Bytes arg9 = "j";
aa.AppendFormat(format, arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
AssertAreEqualInTest("a b c d e f g h i j", aa);
aa.AssertNullTerminated();
aa.Dispose();
}
[Test]
public void UnsafeTextAppendGrows()
{
UnsafeText aa = new UnsafeText(1, Allocator.Temp);
var origCapacity = aa.Capacity;
for (int i = 0; i < origCapacity; ++i)
aa.Append('a');
Assert.AreEqual(origCapacity, aa.Capacity);
aa.Append('b');
Assert.GreaterOrEqual(aa.Capacity, origCapacity);
Assert.AreEqual(new String('a', origCapacity) + "b", aa.ToString());
aa.Dispose();
}
[Test]
public void UnsafeTextAppendString()
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
aa.Append("aa");
Assert.AreEqual("aa", aa.ToString());
aa.Append("bb");
Assert.AreEqual("aabb", aa.ToString());
aa.Dispose();
}
[TestCase("Antidisestablishmentarianism")]
[TestCase("⁣🌹🌻🌷🌿🌵🌾⁣")]
public void UnsafeTextCopyFromBytesWorks(String a)
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
aa.Junk();
var utf8 = Encoding.UTF8.GetBytes(a);
unsafe
{
fixed (byte* b = utf8)
aa.Append(b, (ushort) utf8.Length);
}
Assert.AreEqual(a, aa.ToString());
aa.AssertNullTerminated();
aa.Append("tail");
Assert.AreEqual(a + "tail", aa.ToString());
aa.AssertNullTerminated();
aa.Dispose();
}
[TestCase("red")]
[TestCase("紅色", TestName = "{m}(Chinese-Red)")]
[TestCase("George Washington")]
[TestCase("村上春樹", TestName = "{m}(HarukiMurakami)")]
public void UnsafeTextToStringWorks(String a)
{
UnsafeText aa = new UnsafeText(4, Allocator.Temp);
aa.Append(new FixedString128Bytes(a));
Assert.AreEqual(a, aa.ToString());
aa.AssertNullTerminated();
aa.Dispose();
}
[Test]
public void UnsafeTextIndexOf()
{
UnsafeText a = new UnsafeText(16, Allocator.Temp);
a.Append((FixedString64Bytes) "bookkeeper bookkeeper");
UnsafeText b = new UnsafeText(8, Allocator.Temp);
b.Append((FixedString32Bytes) "ookkee");
Assert.AreEqual(1, a.IndexOf(b));
Assert.AreEqual(-1, b.IndexOf(a));
a.Dispose();
b.Dispose();
}
[Test]
public void UnsafeTextLastIndexOf()
{
UnsafeText a = new UnsafeText(16, Allocator.Temp);
a.Append((FixedString64Bytes) "bookkeeper bookkeeper");
UnsafeText b = new UnsafeText(8, Allocator.Temp);
b.Append((FixedString32Bytes) "ookkee");
Assert.AreEqual(12, a.LastIndexOf(b));
Assert.AreEqual(-1, b.LastIndexOf(a));
a.Dispose();
b.Dispose();
}
[Test]
public void UnsafeTextContains()
{
UnsafeText a = new UnsafeText(16, Allocator.Temp);
a.Append((FixedString64Bytes) "bookkeeper bookkeeper");
UnsafeText b = new UnsafeText(8, Allocator.Temp);
b.Append((FixedString32Bytes) "ookkee");
Assert.AreEqual(true, a.Contains(b));
a.Dispose();
b.Dispose();
}
[Test]
public void UnsafeTextComparisons()
{
UnsafeText a = new UnsafeText(16, Allocator.Temp);
a.Append((FixedString64Bytes) "apple");
UnsafeText b = new UnsafeText(8, Allocator.Temp);
b.Append((FixedString32Bytes) "banana");
Assert.AreEqual(false, a.Equals(b));
Assert.AreEqual(true, !b.Equals(a));
a.Dispose();
b.Dispose();
}
[Test]
public void UnsafeText_CustomAllocatorTest()
{
AllocatorManager.Initialize();
var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent);
ref var allocator = ref allocatorHelper.Allocator;
allocator.Initialize();
using (var container = new UnsafeText(1, allocator.Handle))
{
}
Assert.IsTrue(allocator.WasUsed);
allocator.Dispose();
allocatorHelper.Dispose();
AllocatorManager.Shutdown();
}
[BurstCompile]
struct BurstedCustomAllocatorJob : IJob
{
[NativeDisableUnsafePtrRestriction]
public unsafe CustomAllocatorTests.CountingAllocator* Allocator;
public void Execute()
{
unsafe
{
using (var container = new UnsafeText(1, Allocator->Handle))
{
}
}
}
}
[Test]
public unsafe void UnsafeText_BurstedCustomAllocatorTest()
{
AllocatorManager.Initialize();
var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent);
ref var allocator = ref allocatorHelper.Allocator;
allocator.Initialize();
var allocatorPtr = (CustomAllocatorTests.CountingAllocator*)UnsafeUtility.AddressOf<CustomAllocatorTests.CountingAllocator>(ref allocator);
unsafe
{
var handle = new BurstedCustomAllocatorJob {Allocator = allocatorPtr}.Schedule();
handle.Complete();
}
Assert.IsTrue(allocator.WasUsed);
allocator.Dispose();
allocatorHelper.Dispose();
AllocatorManager.Shutdown();
}
[TestCase("red", 'r', 'd')]
[TestCase("紅色", '紅', '色')]
[TestCase("црвена", 'ц', 'а')]
[TestCase("George Washington", 'G', 'n')]
[TestCase("村上春樹", '村', '樹')]
[TestCase("로마는 하루아침에 이루어진 것이 아니다", '로', '다')]
[TestCase("Лако ти је плитку воду замутити и будалу наљутити", 'Л', 'и')]
[TestCase("Үнэн үг хэлсэн хүнд ноёд өстэй, үхэр унасан хүнд ноход өстэй.", 'Ү', '.')]
public void UnsafeText_StartsEndsWithChar(String a, char starts, char ends)
{
UnsafeText actual = new UnsafeText(16, Allocator.Temp);
actual.Append(a);
Assert.True(actual.StartsWith(starts));
Assert.True(actual.EndsWith(ends));
}
[TestCase("red", "r", "d")]
[TestCase("紅色", "紅", "色")]
[TestCase("црвена", "црв", "ена")]
[TestCase("George Washington", "George", "Washington")]
[TestCase("村上春樹", "村上", "春樹")]
[TestCase("🌕🌖🌗🌘🌑🌒🌓🌔", "🌕🌖🌗", "🌒🌓🌔")]
[TestCase("𝒞𝒯𝒮𝒟𝒳𝒩𝒫𝒢", "𝒞𝒯𝒮", "𝒩𝒫𝒢")]
[TestCase("로마는 하루아침에 이루어진 것이 아니다", "로마는", "아니다")]
[TestCase("Лако ти је плитку воду замутити и будалу наљутити", "Лако", "наљутити")]
[TestCase("Үнэн үг хэлсэн хүнд ноёд өстэй, үхэр унасан хүнд ноход өстэй.", "Үнэн", "өстэй.")]
public void UnsafeText_StartsEndsWithString(String a, String starts, String ends)
{
UnsafeText actual = new UnsafeText(16, Allocator.Temp);
actual.Append(a);
Assert.True(actual.StartsWith((FixedString64Bytes)starts));
Assert.True(actual.EndsWith((FixedString64Bytes)ends));
}
[TestCase("red ", ' ', "red ", "red", "red")]
[TestCase(" red ", ' ', "red ", " red", "red")]
[TestCase(" ", ' ', "", "", "")]
public void UnsafeText_TrimStart(String a, char trim, String expectedStart, String expectedEnd, String expected)
{
UnsafeText actual = new UnsafeText(16, Allocator.Temp);
actual.Append(a);
Assert.AreEqual(expectedStart, actual.TrimStart(Allocator.Temp).ToString());
Assert.AreEqual(expectedEnd, actual.TrimEnd(Allocator.Temp).ToString());
Assert.AreEqual(expected, actual.Trim(Allocator.Temp).ToString());
}
[TestCase(" red ", "ed ", " red", "ed")]
[TestCase("црвена", "црвена", "црвена", "црвена")]
[TestCase(" ", "", "", "")]
public void UnsafeText_TrimStartWithRunes(String a, String expectedStart, String expectedEnd, String expected)
{
UnsafeText actual = new UnsafeText(16, Allocator.Temp);
actual.Append(a);
Assert.AreEqual(expectedStart, actual.TrimStart(Allocator.Temp, new Unicode.Rune[] { ' ', 'r' }).ToString());
Assert.AreEqual(expectedEnd, actual.TrimEnd(Allocator.Temp, new Unicode.Rune[] { ' ', 'r' }).ToString());
Assert.AreEqual(expected, actual.Trim(Allocator.Temp, new Unicode.Rune[] { ' ', 'r' }).ToString());
}
[TestCase("Red", "red", "RED")]
[TestCase("црвена", "црвена", "црвена")]
[TestCase(" ", " ", " ")]
public void UnsafeText_ToLowerUpperAscii(String a, String expectedLower, String expectedUpped)
{
UnsafeText actual = new UnsafeText(16, Allocator.Temp);
actual.Append(a);
Assert.AreEqual(expectedLower, actual.ToLowerAscii(Allocator.Temp).ToString());
Assert.AreEqual(expectedUpped, actual.ToUpperAscii(Allocator.Temp).ToString());
}
}
}