303 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			303 lines
		
	
	
		
			8.6 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using NUnit.Framework; | ||
|  | using System; | ||
|  | using Unity.Burst; | ||
|  | using Unity.Collections; | ||
|  | using Unity.Collections.LowLevel.Unsafe; | ||
|  | using Unity.Collections.Tests; | ||
|  | using Unity.Jobs; | ||
|  | 
 | ||
|  | class NativeReferenceTests : CollectionsTestCommonBase | ||
|  | { | ||
|  |     [Test] | ||
|  |     public void NativeReference_AllocateDeallocate_ReadWrite() | ||
|  |     { | ||
|  |         var reference = new NativeReference<int>(Allocator.Persistent); | ||
|  |         reference.Value = 1; | ||
|  | 
 | ||
|  |         Assert.That(reference.Value, Is.EqualTo(1)); | ||
|  | 
 | ||
|  |         reference.Dispose(); | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public void NativeReference_CopyFrom() | ||
|  |     { | ||
|  |         var referenceA = new NativeReference<TestData>(Allocator.Persistent); | ||
|  |         var referenceB = new NativeReference<TestData>(Allocator.Persistent); | ||
|  | 
 | ||
|  |         referenceA.Value = new TestData { Integer = 42, Float = 3.1416f }; | ||
|  |         referenceB.CopyFrom(referenceA); | ||
|  | 
 | ||
|  |         Assert.That(referenceB.Value, Is.EqualTo(referenceA.Value)); | ||
|  | 
 | ||
|  |         referenceA.Dispose(); | ||
|  |         referenceB.Dispose(); | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public void NativeReference_CopyTo() | ||
|  |     { | ||
|  |         var referenceA = new NativeReference<TestData>(Allocator.Persistent); | ||
|  |         var referenceB = new NativeReference<TestData>(Allocator.Persistent); | ||
|  | 
 | ||
|  |         referenceA.Value = new TestData { Integer = 42, Float = 3.1416f }; | ||
|  |         referenceA.CopyTo(referenceB); | ||
|  | 
 | ||
|  |         Assert.That(referenceB.Value, Is.EqualTo(referenceA.Value)); | ||
|  | 
 | ||
|  |         referenceA.Dispose(); | ||
|  |         referenceB.Dispose(); | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     [TestRequiresCollectionChecks] | ||
|  |     public void NativeReference_NullThrows() | ||
|  |     { | ||
|  |         var reference = new NativeReference<int>(); | ||
|  |         Assert.Throws<NullReferenceException>(() => reference.Value = 5); | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public void NativeReference_CopiedIsKeptInSync() | ||
|  |     { | ||
|  |         var reference = new NativeReference<int>(Allocator.Persistent); | ||
|  |         var referenceCopy = reference; | ||
|  |         reference.Value = 42; | ||
|  | 
 | ||
|  |         Assert.That(reference.Value, Is.EqualTo(referenceCopy.Value)); | ||
|  | 
 | ||
|  |         reference.Dispose(); | ||
|  |     } | ||
|  | 
 | ||
|  |     struct TestData | ||
|  |     { | ||
|  |         public int Integer; | ||
|  |         public float Float; | ||
|  |     } | ||
|  | 
 | ||
|  |     [BurstCompile(CompileSynchronously = true)] | ||
|  |     struct TempNativeReferenceInJob : IJob | ||
|  |     { | ||
|  |         public NativeReference<int> Output; | ||
|  | 
 | ||
|  |         public void Execute() | ||
|  |         { | ||
|  |             var reference = new NativeReference<int>(Allocator.Temp); | ||
|  |             reference.Value = 42; | ||
|  |             Output.Value = reference.Value; | ||
|  |             reference.Dispose(); | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public void NativeReference_TempInBurstJob() | ||
|  |     { | ||
|  |         var job = new TempNativeReferenceInJob() { Output = new NativeReference<int>(CommonRwdAllocator.Handle) }; | ||
|  |         job.Schedule().Complete(); | ||
|  | 
 | ||
|  |         Assert.That(job.Output.Value, Is.EqualTo(42)); | ||
|  | 
 | ||
|  |         job.Output.Dispose(); | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public unsafe void NativeReference_UnsafePtr() | ||
|  |     { | ||
|  |         var reference = new NativeReference<int>(CommonRwdAllocator.Handle); | ||
|  |         var job = new TempNativeReferenceInJob() { Output = reference }; | ||
|  |         var jobHandle = job.Schedule(); | ||
|  | 
 | ||
|  | #if ENABLE_UNITY_COLLECTIONS_CHECKS | ||
|  |         Assert.Throws<InvalidOperationException>(() => reference.GetUnsafePtr()); | ||
|  |         Assert.Throws<InvalidOperationException>(() => reference.GetUnsafeReadOnlyPtr()); | ||
|  | #endif | ||
|  |         Assert.DoesNotThrow(() => reference.GetUnsafePtrWithoutChecks()); | ||
|  | 
 | ||
|  |         jobHandle.Complete(); | ||
|  | 
 | ||
|  |         Assert.AreEqual(*reference.GetUnsafePtr(), 42); | ||
|  |         Assert.AreEqual(*reference.GetUnsafeReadOnlyPtr(), 42); | ||
|  |         Assert.AreEqual(*reference.GetUnsafePtrWithoutChecks(), 42); | ||
|  | 
 | ||
|  |         Assert.That(job.Output.Value, Is.EqualTo(42)); | ||
|  | 
 | ||
|  |         job.Output.Dispose(); | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public void NativeReference_DisposeJob() | ||
|  |     { | ||
|  |         var reference = new NativeReference<int>(Allocator.Persistent); | ||
|  |         Assert.That(reference.IsCreated, Is.True); | ||
|  |         Assert.DoesNotThrow(() => reference.Value = 99); | ||
|  | 
 | ||
|  |         var disposeJob = reference.Dispose(default); | ||
|  |         Assert.That(reference.IsCreated, Is.False); | ||
|  | 
 | ||
|  | #if ENABLE_UNITY_COLLECTIONS_CHECKS | ||
|  |         Assert.Throws<ObjectDisposedException>(() => reference.Value = 3); | ||
|  | #endif | ||
|  | 
 | ||
|  |         disposeJob.Complete(); | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public void NativeReference_NoGCAllocations() | ||
|  |     { | ||
|  |         var reference = new NativeReference<int>(Allocator.Persistent); | ||
|  | 
 | ||
|  |         GCAllocRecorder.ValidateNoGCAllocs(() => | ||
|  |         { | ||
|  |             reference.Value = 1; | ||
|  |             reference.Value++; | ||
|  |         }); | ||
|  | 
 | ||
|  |         Assert.That(reference.Value, Is.EqualTo(2)); | ||
|  | 
 | ||
|  |         reference.Dispose(); | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public void NativeReference_Equals() | ||
|  |     { | ||
|  |         var referenceA = new NativeReference<int>(12345, Allocator.Persistent); | ||
|  |         var referenceB = new NativeReference<int>(Allocator.Persistent) { Value = 12345 }; | ||
|  |         Assert.That(referenceA, Is.EqualTo(referenceB)); | ||
|  | 
 | ||
|  |         referenceB.Value = 54321; | ||
|  |         Assert.AreNotEqual(referenceA, referenceB); | ||
|  | 
 | ||
|  |         referenceA.Dispose(); | ||
|  |         referenceB.Dispose(); | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public void NativeReference_ReadOnly() | ||
|  |     { | ||
|  |         var referenceA = new NativeReference<int>(12345, Allocator.Persistent); | ||
|  |         var referenceB = new NativeReference<int>(Allocator.Persistent) { Value = 12345 }; | ||
|  | 
 | ||
|  |         var referenceARO = referenceA.AsReadOnly(); | ||
|  |         Assert.AreEqual(referenceARO.Value, referenceB.Value); | ||
|  | 
 | ||
|  |         referenceA.Dispose(); | ||
|  |         referenceB.Dispose(); | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public void NativeReference_GetHashCode() | ||
|  |     { | ||
|  |         var integer = 42; | ||
|  |         var reference = new NativeReference<int>(integer, Allocator.Persistent); | ||
|  |         Assert.That(reference.GetHashCode(), Is.EqualTo(integer.GetHashCode())); | ||
|  | 
 | ||
|  |         reference.Dispose(); | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public void NativeReference_CustomAllocatorTest() | ||
|  |     { | ||
|  |         AllocatorManager.Initialize(); | ||
|  |         var allocatorHelper = new AllocatorHelper<CustomAllocatorTests.CountingAllocator>(AllocatorManager.Persistent); | ||
|  |         ref var allocator = ref allocatorHelper.Allocator; | ||
|  |         allocator.Initialize(); | ||
|  | 
 | ||
|  |         using (var container = new NativeReference<int>(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 NativeReference<int>(Allocator->Handle)) | ||
|  |                 { | ||
|  |                 } | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public unsafe void NativeReference_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(); | ||
|  |     } | ||
|  | 
 | ||
|  |     public struct NestedContainer | ||
|  |     { | ||
|  |         public NativeReference<int> data; | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     public void NativeReference_Nested() | ||
|  |     { | ||
|  |         var inner = new NativeReference<int>(CommonRwdAllocator.Handle); | ||
|  |         NestedContainer nestedStruct = new NestedContainer { data = inner }; | ||
|  | 
 | ||
|  |         var containerNestedStruct = new NativeReference<NestedContainer>(CommonRwdAllocator.Handle); | ||
|  |         var containerNested = new NativeReference<NativeReference<int>>(CommonRwdAllocator.Handle); | ||
|  | 
 | ||
|  |         containerNested.Value = inner; | ||
|  |         containerNestedStruct.Value = nestedStruct; | ||
|  | 
 | ||
|  |         containerNested.Dispose(); | ||
|  |         containerNestedStruct.Dispose(); | ||
|  |         inner.Dispose(); | ||
|  |     } | ||
|  | 
 | ||
|  |     struct NestedContainerJob : IJob | ||
|  |     { | ||
|  |         public NativeReference<NativeReference<int>> nestedContainer; | ||
|  | 
 | ||
|  |         public void Execute() | ||
|  |         { | ||
|  |             nestedContainer.Value = default; | ||
|  |         } | ||
|  |     } | ||
|  | 
 | ||
|  |     [Test] | ||
|  |     [TestRequiresCollectionChecks] | ||
|  |     public void NativeReference_NestedJob_Error() | ||
|  |     { | ||
|  |         var container = new NativeReference<NativeReference<int>>(CommonRwdAllocator.Handle); | ||
|  | 
 | ||
|  |         var nestedJob = new NestedContainerJob | ||
|  |         { | ||
|  |             nestedContainer = container | ||
|  |         }; | ||
|  | 
 | ||
|  |         JobHandle job = default; | ||
|  |         Assert.Throws<System.InvalidOperationException>(() => { job = nestedJob.Schedule(); }); | ||
|  |         job.Complete(); | ||
|  | 
 | ||
|  |         container.Dispose(); | ||
|  |     } | ||
|  | } |