123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- using System;
- using System.Diagnostics;
- using System.Runtime.InteropServices;
- using NUnit.Framework;
- using System.Text.RegularExpressions;
- using Unity.Burst;
- using Unity.Collections.LowLevel.Unsafe;
- using Unity.Jobs;
- using UnityEngine;
- using UnityEngine.TestTools;
- using System.Runtime.CompilerServices;
-
- namespace ExceptionsFromBurstJobs
- {
- [BurstCompile]
- class ManagedExceptionsBurstJobs
- {
- [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
- private static void ThrowNewArgumentException()
- {
- throw new ArgumentException("A");
- }
-
- [BurstCompile(CompileSynchronously = true)]
- struct ThrowArgumentExceptionJob : IJob
- {
- public void Execute()
- {
- ThrowNewArgumentException();
- }
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void ThrowArgumentException()
- {
- LogAssert.Expect(LogType.Exception, new Regex("ArgumentException: A"));
-
- var jobData = new ThrowArgumentExceptionJob();
- jobData.Run();
- }
-
- [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
- private static void ThrowNewArgumentNullException()
- {
- throw new ArgumentNullException("N");
- }
-
- [BurstCompile(CompileSynchronously = true)]
- struct ThrowArgumentNullExceptionJob : IJob
- {
- public void Execute()
- {
- ThrowNewArgumentNullException();
- }
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void ThrowArgumentNullException()
- {
- LogAssert.Expect(LogType.Exception, new Regex("System.ArgumentNullException: N"));
-
- var jobData = new ThrowArgumentNullExceptionJob();
- jobData.Run();
- }
-
- [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
- private static void ThrowNewNullReferenceException()
- {
- throw new NullReferenceException("N");
- }
-
- [BurstCompile(CompileSynchronously = true)]
- struct ThrowNullReferenceExceptionJob : IJob
- {
- public void Execute()
- {
- ThrowNewNullReferenceException();
- }
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void ThrowNullReferenceException()
- {
- LogAssert.Expect(LogType.Exception, new Regex("NullReferenceException: N"));
-
- var jobData = new ThrowNullReferenceExceptionJob();
- jobData.Run();
- }
-
- [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
- private static void ThrowNewInvalidOperationException()
- {
- throw new InvalidOperationException("IO");
- }
-
- [BurstCompile(CompileSynchronously = true)]
- struct ThrowInvalidOperationExceptionJob : IJob
- {
- public void Execute()
- {
- ThrowNewInvalidOperationException();
- }
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void ThrowInvalidOperationException()
- {
- LogAssert.Expect(LogType.Exception, new Regex("InvalidOperationException: IO"));
-
- var jobData = new ThrowInvalidOperationExceptionJob();
- jobData.Run();
- }
-
- [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
- private static void ThrowNewNotSupportedException()
- {
- throw new NotSupportedException("NS");
- }
-
- [BurstCompile(CompileSynchronously = true)]
- struct ThrowNotSupportedExceptionJob : IJob
- {
- public void Execute()
- {
- ThrowNewNotSupportedException();
- }
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void ThrowNotSupportedException()
- {
- LogAssert.Expect(LogType.Exception, new Regex("NotSupportedException: NS"));
-
- var jobData = new ThrowNotSupportedExceptionJob();
- jobData.Run();
- }
-
- [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
- private static void ThrowNewUnityException()
- {
- throw new UnityException("UE");
- }
-
- [BurstCompile(CompileSynchronously = true)]
- struct ThrowUnityExceptionJob : IJob
- {
- public void Execute()
- {
- ThrowNewUnityException();
- }
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void ThrowUnityException()
- {
- LogAssert.Expect(LogType.Exception, new Regex("UnityException: UE"));
-
- var jobData = new ThrowUnityExceptionJob();
- jobData.Run();
- }
-
- [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
- private static void ThrowNewIndexOutOfRangeException()
- {
- throw new IndexOutOfRangeException("IOOR");
- }
-
- [BurstCompile(CompileSynchronously = true)]
- struct ThrowIndexOutOfRangeExceptionJob : IJob
- {
- public void Execute()
- {
- ThrowNewIndexOutOfRangeException();
- }
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void ThrowIndexOutOfRange()
- {
- LogAssert.Expect(LogType.Exception, new Regex("IndexOutOfRangeException: IOOR"));
-
- var jobData = new ThrowIndexOutOfRangeExceptionJob();
- jobData.Run();
- }
-
- [BurstCompile(CompileSynchronously = true)]
- private unsafe struct ThrowFromDereferenceNullJob : IJob
- {
- [NativeDisableUnsafePtrRestriction]
- public int* Ptr;
-
- public void Execute()
- {
- *Ptr = 42;
- }
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void ThrowFromDereferenceNull()
- {
- LogAssert.Expect(LogType.Exception, new Regex("NullReferenceException: Object reference not set to an instance of an object"));
-
- var jobData = new ThrowFromDereferenceNullJob() { Ptr = null };
- jobData.Run();
- }
-
- [BurstCompile(CompileSynchronously = true)]
- private unsafe struct ThrowFromDivideByZeroJob : IJob
- {
- public int Int;
-
- public void Execute()
- {
- Int = 42 / Int;
- }
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void ThrowFromDivideByZero()
- {
- if (RuntimeInformation.OSArchitecture == Architecture.Arm64)
- {
- // Arm64 does not throw a divide-by-zero exception, instead it flushes the result to zero.
- return;
- }
-
- LogAssert.Expect(LogType.Exception, new Regex("DivideByZeroException: Attempted to divide by zero"));
-
- var jobData = new ThrowFromDivideByZeroJob() { Int = 0 };
- jobData.Run();
- }
-
- private unsafe delegate void ExceptionDelegate(int* a);
-
- [BurstCompile(CompileSynchronously = true)]
- private static unsafe void DereferenceNull(int* a)
- {
- *a = 42;
- }
-
- [BurstCompile(CompileSynchronously = true)]
- unsafe struct ThrowFromFunctionPointerJob : IJob
- {
- #pragma warning disable 649
- [NativeDisableUnsafePtrRestriction] public IntPtr FuncPtr;
- [NativeDisableUnsafePtrRestriction] public int* Ptr;
- #pragma warning restore 649
-
- public void Execute()
- {
- new FunctionPointer<ExceptionDelegate>(FuncPtr).Invoke(Ptr);
-
- // Set Ptr to non null which should never be hit because the above will throw.
- Ptr = (int*)0x42;
- }
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public unsafe void ThrowFromFunctionPointer()
- {
- var funcPtr = BurstCompiler.CompileFunctionPointer<ExceptionDelegate>(DereferenceNull);
- LogAssert.Expect(LogType.Exception, new Regex("NullReferenceException: Object reference not set to an instance of an object"));
- var job = new ThrowFromFunctionPointerJob { FuncPtr = funcPtr.Value, Ptr = null };
- job.Run();
- Assert.AreEqual((IntPtr)job.Ptr, (IntPtr)0);
- }
-
- [BurstCompile(CompileSynchronously = true)]
- private unsafe struct ThrowFromDereferenceNullParallelJob : IJobParallelFor
- {
- [NativeDisableUnsafePtrRestriction]
- public int* Ptr;
-
- public void Execute(int index)
- {
- *Ptr = index;
- }
- }
-
- [Test]
- // No RuntimePlatform.OSXEditor in this list because of a subtle Mojave only bug.
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void ThrowFromDereferenceNullParallel()
- {
- var messageCount = 0;
-
- void OnMessage(string message, string stackTrace, LogType type)
- {
- Assert.AreEqual(LogType.Exception, type);
- StringAssert.Contains("NullReferenceException: Object reference not set to an instance of an object", message);
- messageCount++;
- }
-
- LogAssert.ignoreFailingMessages = true;
- Application.logMessageReceivedThreaded += OnMessage;
-
- try
- {
- var jobData = new ThrowFromDereferenceNullParallelJob() { Ptr = null };
- jobData.Schedule(128, 1).Complete();
-
- Assert.GreaterOrEqual(messageCount, 1);
- }
- finally
- {
- Application.logMessageReceivedThreaded -= OnMessage;
- LogAssert.ignoreFailingMessages = false;
- }
- }
-
- private unsafe struct ThrowFromDereferenceNullManagedJob : IJob
- {
- [NativeDisableUnsafePtrRestriction]
- public int* Ptr;
-
- public void Execute()
- {
- *Ptr = 42;
- }
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void ThrowFromDereferenceNullManaged()
- {
- LogAssert.Expect(LogType.Exception, new Regex("NullReferenceException: Object reference not set to an instance of an object"));
-
- var jobData = new ThrowFromDereferenceNullManagedJob() { Ptr = null };
- jobData.Run();
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void ThrowFromDereferenceNullBurstDisabled()
- {
- var previous = BurstCompiler.Options.EnableBurstCompilation;
- BurstCompiler.Options.EnableBurstCompilation = false;
-
- LogAssert.Expect(LogType.Exception, new Regex("NullReferenceException: Object reference not set to an instance of an object"));
-
- var jobData = new ThrowFromDereferenceNullJob() { Ptr = null };
- jobData.Run();
-
- BurstCompiler.Options.EnableBurstCompilation = previous;
- }
-
-
- [BurstCompile]
- struct Thrower : IJob
- {
- public int X;
-
- [BurstCompile(CompileSynchronously = true)]
- [Conditional("ENABLE_UNITY_COLLECTIONS_CHECKS")]
- [MethodImpl(MethodImplOptions.NoInlining)]
- public static void ConditionalThrowWithSideEffect(int x)
- {
- if (x == -1)
- throw new InvalidOperationException();
-
- UnityEngine.Debug.Log("wow");
- throw new InvalidOperationException();
- }
-
- public void Execute()
- {
- ConditionalThrowWithSideEffect(X);
- }
- }
-
- [Test]
- [UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- [Description("Requires ENABLE_UNITY_COLLECTIONS_CHECKS which is currently only enabled in the Editor")]
- public void TestConditionalThrowWithSideEffect()
- {
- LogAssert.Expect(LogType.Log, "wow");
- LogAssert.Expect(LogType.Exception, new Regex(".+InvalidOperation.+"));
-
- new Thrower() { X = 0 }.Run();
- }
-
- private unsafe struct ThrowFromManagedStackOverflowJob : IJob
- {
- [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
- private static int DoStackOverflow(ref int x)
- {
- // Copy just to make the stack grow.
- var copy = x;
- return copy + DoStackOverflow(ref x);
- }
-
- public int Int;
-
- public void Execute()
- {
- Int = DoStackOverflow(ref Int);
- }
- }
-
- //[Test]
- //[UnityPlatform(RuntimePlatform.WindowsEditor, RuntimePlatform.OSXEditor, RuntimePlatform.LinuxEditor)]
- public void ThrowFromManagedStackOverflow()
- {
- LogAssert.Expect(LogType.Exception, new Regex("StackOverflowException: The requested operation caused a stack overflow"));
-
- var jobData = new ThrowFromManagedStackOverflowJob() { Int = 1 };
- jobData.Run();
- }
- }
- }
|