A game about forced loneliness, made by TACStudios
at master 275 lines 9.3 kB view raw
1using System; 2using NUnit.Framework; 3using Unity.Collections; 4using Unity.Collections.LowLevel.Unsafe; 5using Unity.Collections.Tests; 6using Unity.Mathematics; 7 8[TestFixture] 9internal class UnsafeUtilityTests : CollectionsTestCommonBase 10{ 11#pragma warning disable 649 12 struct DummyVec 13 { 14 public uint A, B, C, D; 15 } 16#pragma warning restore 17 18 private NativeArray<T> MakeTestArray<T>(params T[] data) 19 where T : unmanaged 20 { 21 return CollectionHelper.CreateNativeArray<T>(data, CommonRwdAllocator.Handle); 22 } 23 24 [Test] 25 public void ReinterpretUIntFloat() 26 { 27 using (var src = MakeTestArray(1.0f, 2.0f, 3.0f)) 28 { 29 var dst = src.Reinterpret<float, uint>(); 30 Assert.AreEqual(src.Length, dst.Length); 31 Assert.AreEqual(0x3f800000u, dst[0]); 32 Assert.AreEqual(0x40000000u, dst[1]); 33 Assert.AreEqual(0x40400000u, dst[2]); 34 } 35 } 36 37 [Test] 38 public void ReinterpretUInt4Float() 39 { 40 using (var src = MakeTestArray(1.0f, 2.0f, 3.0f, -1.0f)) 41 { 42 var dst = src.Reinterpret<float, DummyVec>(); 43 Assert.AreEqual(1, dst.Length); 44 45 var e = dst[0]; 46 Assert.AreEqual(0x3f800000u, e.A); 47 Assert.AreEqual(0x40000000u, e.B); 48 Assert.AreEqual(0x40400000u, e.C); 49 Assert.AreEqual(0xbf800000u, e.D); 50 } 51 } 52 53 [Test] 54 public void ReinterpretFloatUint4() 55 { 56 var dummies = new DummyVec[] 57 { 58 new DummyVec { A = 0x3f800000u, B = 0x40000000u, C = 0x40400000u, D = 0xbf800000u }, 59 new DummyVec { A = 0xbf800000u, B = 0xc0000000u, C = 0xc0400000u, D = 0x3f800000u }, 60 }; 61 62 using (var src = MakeTestArray(dummies)) 63 { 64 var dst = src.Reinterpret<DummyVec, float>(); 65 Assert.AreEqual(8, dst.Length); 66 67 Assert.AreEqual(1.0f, dst[0]); 68 Assert.AreEqual(2.0f, dst[1]); 69 Assert.AreEqual(3.0f, dst[2]); 70 Assert.AreEqual(-1.0f, dst[3]); 71 Assert.AreEqual(-1.0f, dst[4]); 72 Assert.AreEqual(-2.0f, dst[5]); 73 Assert.AreEqual(-3.0f, dst[6]); 74 Assert.AreEqual(1.0f, dst[7]); 75 } 76 } 77 78 [Test] 79 [TestRequiresDotsDebugOrCollectionChecks] 80 public void MismatchThrows1() 81 { 82 using (var src = MakeTestArray(0.0f, 1.0f, 2.0f)) 83 { 84 Assert.Throws<InvalidOperationException>(() => src.Reinterpret<float, DummyVec>()); 85 } 86 } 87 88 [Test] 89 [TestRequiresDotsDebugOrCollectionChecks] 90 public void MismatchThrows2() 91 { 92 using (var src = MakeTestArray(12)) 93 { 94 Assert.Throws<InvalidOperationException>(() => src.Reinterpret<int, double>()); 95 } 96 } 97 98 [Test] 99 public void AliasCanBeDisposed() 100 { 101 using (var src = MakeTestArray(12)) 102 { 103 using (var dst = src.Reinterpret<int, float>()) 104 { 105 } 106 } 107 } 108 109 [Test] 110 [TestRequiresCollectionChecks] 111 public void CannotUseAliasAfterSourceIsDisposed() 112 { 113 NativeArray<float> alias; 114 var src = MakeTestArray(12); 115 alias = src.Reinterpret<int, float>(); 116 117 // `Free` of memory allocated by world update allocator is an no-op. 118 // World update allocator needs to be rewound in order to free the memory. 119 CommonRwdAllocator.Rewind(); 120 121 Assert.Throws<ObjectDisposedException>( 122 () => alias[0] = 1.0f); 123 } 124 125 [Test] 126 public void MutabilityWorks() 127 { 128 using (var src = MakeTestArray(0.0f, -1.0f)) 129 { 130 var alias = src.Reinterpret<float, uint>(); 131 alias[0] = 0x3f800000; 132 Assert.AreEqual(1.0f, src[0]); 133 Assert.AreEqual(-1.0f, src[1]); 134 } 135 } 136 137#pragma warning disable 0169 // field is never used 138 struct AlignOfX 139 { 140 float x; 141 bool y; 142 } 143 144 struct AlignOfY 145 { 146 float x; 147 bool y; 148 float z; 149 bool w; 150 } 151 152 struct AlignOfZ 153 { 154 float4 x; 155 bool y; 156 } 157 158 struct AlignOfW 159 { 160 float4 x; 161 bool y; 162 float4x4 z; 163 bool w; 164 } 165 166 struct BoolLong 167 { 168 bool x; 169 long y; 170 } 171 172 struct BoolPtr 173 { 174 bool x; 175 unsafe void* y; 176 } 177#pragma warning restore 0169 // field is never used 178 179 [Test] 180 public void UnsafeUtility_AlignOf() 181 { 182 Assert.AreEqual(UnsafeUtility.SizeOf<byte>(), UnsafeUtility.AlignOf<byte>()); 183 Assert.AreEqual(UnsafeUtility.SizeOf<short>(), UnsafeUtility.AlignOf<short>()); 184 Assert.AreEqual(UnsafeUtility.SizeOf<ushort>(), UnsafeUtility.AlignOf<ushort>()); 185 Assert.AreEqual(UnsafeUtility.SizeOf<int>(), UnsafeUtility.AlignOf<int>()); 186 Assert.AreEqual(UnsafeUtility.SizeOf<uint>(), UnsafeUtility.AlignOf<uint>()); 187 Assert.AreEqual(UnsafeUtility.SizeOf<long>(), UnsafeUtility.AlignOf<long>()); 188 Assert.AreEqual(UnsafeUtility.SizeOf<ulong>(), UnsafeUtility.AlignOf<ulong>()); 189 Assert.AreEqual(4, UnsafeUtility.AlignOf<float4>()); 190 191 Assert.AreEqual(4, UnsafeUtility.AlignOf<AlignOfX>()); 192 Assert.AreEqual(4, UnsafeUtility.AlignOf<AlignOfY>()); 193 Assert.AreEqual(4, UnsafeUtility.AlignOf<AlignOfZ>()); 194 Assert.AreEqual(4, UnsafeUtility.AlignOf<AlignOfW>()); 195 Assert.AreEqual(8, UnsafeUtility.AlignOf<BoolLong>()); 196 Assert.AreEqual(UnsafeUtility.SizeOf<IntPtr>(), UnsafeUtility.AlignOf<BoolPtr>()); 197 } 198 199 [Test] 200 public unsafe void UnsafeUtility_MemSwap() 201 { 202 using (var array0 = MakeTestArray(0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678)) 203 using (var array1 = MakeTestArray(0x21436587, 0x21436587, 0x21436587, 0x21436587, 0x21436587, 0x21436587)) 204 { 205 UnsafeUtilityExtensions.MemSwap(NativeArrayUnsafeUtility.GetUnsafePtr(array0), NativeArrayUnsafeUtility.GetUnsafePtr(array1), array0.Length*UnsafeUtility.SizeOf<int>()); 206 207 foreach (var b in array0) { Assert.AreEqual(0x21436587, b); } 208 foreach (var b in array1) { Assert.AreEqual(0x12345678, b); } 209 } 210 } 211 212 [Test] 213 [TestRequiresCollectionChecks] 214 public unsafe void UnsafeUtility_MemSwap_DoesThrow_Overlapped() 215 { 216 using (var array0 = MakeTestArray(0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678)) 217 { 218 var mem = (byte*)NativeArrayUnsafeUtility.GetUnsafePtr(array0); 219 var len = array0.Length * UnsafeUtility.SizeOf<int>(); 220 221 Assert.DoesNotThrow(() => { UnsafeUtilityExtensions.MemSwap(mem + 10, mem, 10); }); 222 Assert.Throws<InvalidOperationException>(() => { UnsafeUtilityExtensions.MemSwap(mem + 10, mem, len - 10); }); 223 224 Assert.DoesNotThrow(() => { UnsafeUtilityExtensions.MemSwap(mem, mem + 10, 10); }); 225 Assert.Throws<InvalidOperationException>(() => { UnsafeUtilityExtensions.MemSwap(mem, mem + 10, len - 10); }); 226 } 227 } 228 229 [Test] 230 [TestRequiresDotsDebugOrCollectionChecks] 231 public unsafe void UnsafeUtility_ReadArrayElementBoundsChecked_Works() 232 { 233 using (var array0 = MakeTestArray(0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678)) 234 { 235 var mem = (byte*)NativeArrayUnsafeUtility.GetUnsafePtr(array0); 236 var len = array0.Length; 237 238 Assert.DoesNotThrow(() => { UnsafeUtilityExtensions.ReadArrayElementBoundsChecked<int>(mem, 5, len); }); 239 Assert.Throws<IndexOutOfRangeException>(() => { UnsafeUtilityExtensions.ReadArrayElementBoundsChecked<int>(mem, 6, len); }); 240 Assert.Throws<IndexOutOfRangeException>(() => { UnsafeUtilityExtensions.ReadArrayElementBoundsChecked<int>(mem, -1, len); }); 241 } 242 } 243 244 245 [Test] 246 [TestRequiresDotsDebugOrCollectionChecks] 247 public unsafe void UnsafeUtility_WriteArrayElementBoundsChecked_Works() 248 { 249 using (var array0 = MakeTestArray(0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678, 0x12345678)) 250 { 251 var mem = (byte*)NativeArrayUnsafeUtility.GetUnsafePtr(array0); 252 var len = array0.Length; 253 254 Assert.DoesNotThrow(() => { UnsafeUtilityExtensions.WriteArrayElementBoundsChecked(mem, 5, -98765432, len); }); 255 Assert.Throws<IndexOutOfRangeException>(() => { UnsafeUtilityExtensions.WriteArrayElementBoundsChecked(mem, 6, -98765432, len); }); 256 Assert.Throws<IndexOutOfRangeException>(() => { UnsafeUtilityExtensions.WriteArrayElementBoundsChecked(mem, -1, -98765432, len); }); 257 } 258 } 259 260 [Test] 261 public unsafe void UnsafeUtility_AsRefAddressOfIn_Works() 262 { 263 DummyVec thing = default; 264 265 void* thingInPtr = UnsafeUtilityExtensions.AddressOf(in thing); 266 ref DummyVec thingRef = ref UnsafeUtilityExtensions.AsRef(in thing); 267 void* thingInRefPtr = UnsafeUtility.AddressOf(ref thingRef); 268 void* thingRefPtr = UnsafeUtility.AddressOf(ref thing); 269 void* thingPtr = &thing; 270 271 Assert.AreEqual((IntPtr) thingPtr, (IntPtr) thingInPtr); 272 Assert.AreEqual((IntPtr) thingPtr, (IntPtr) thingRefPtr); 273 Assert.AreEqual((IntPtr) thingPtr, (IntPtr) thingInRefPtr); 274 } 275}