using NUnit.Framework; using System; using System.Collections.Generic; using Unity.Burst; using Unity.Burst.Editor; using Unity.Jobs; // This concrete generic type is only referenced in this assembly-level attribute, // not anywhere else in code. This is to test that such types can be picked up // by BurstReflection. [assembly: BurstReflectionTests.RegisterGenericJobType(typeof(BurstReflectionTests.GenericParallelForJob<int>))] [TestFixture] public class BurstReflectionTests { private List<System.Reflection.Assembly> _assemblies; [OneTimeSetUp] public void SetUp() { _assemblies = BurstReflection.EditorAssembliesThatCanPossiblyContainJobs; } [Test] public void CanGetAssemblyList() { Assert.That(_assemblies, Has.Count.GreaterThan(0)); } [Test] [TestCase("BurstReflectionTests.MyJob - (IJob)")] [TestCase("BurstReflectionTests.MyGenericJob`1[System.Int32] - (IJob)")] [TestCase("BurstReflectionTests.MyGenericJob2`1[System.Int32] - (BurstReflectionTests.IMyGenericJob`1[System.Int32])")] [TestCase("BurstReflectionTests.MyGenericJob2`1[System.Double] - (BurstReflectionTests.IMyGenericJob`1[System.Double])")] [TestCase("BurstReflectionTests.NonGenericType.TestMethod1()")] [TestCase("BurstReflectionTests.GenericType`1[System.Int32].TestMethod1()")] [TestCase("BurstReflectionTests.GenericType`1.NestedNonGeneric[System.Int32].TestMethod2()")] [TestCase("BurstReflectionTests.GenericType`1.NestedGeneric`1[System.Int32,System.Single].TestMethod3()")] [TestCase("BurstReflectionTests.MyGenericJobSeparateAssembly`1[System.Int32] - (BurstReflectionTestsSeparateAssembly.IMyGenericJobSeparateAssembly`1[System.Int32])")] [TestCase("BurstReflectionTests.GenericParallelForJob`1[System.Int32] - (IJobParallelFor)")] public void CanFindJobType(string compileTargetName) { var result = BurstReflection.FindExecuteMethods(_assemblies, BurstReflectionAssemblyOptions.None); Assert.That(result.LogMessages, Is.Empty); var compileTarget = result.CompileTargets.Find(x => x.GetDisplayName() == compileTargetName); Assert.That(compileTarget, Is.Not.Null); } [BurstCompile] private struct MyJob : IJob { public void Execute() { } } [BurstCompile] private struct MyGenericJob<T> : IJob { public void Execute() { } private static void UseConcreteType() { new MyGenericJob<int>().Execute(); } } [Unity.Jobs.LowLevel.Unsafe.JobProducerType(typeof(MyJobProducer<,>))] private interface IMyGenericJob<T> { void Execute(); } [BurstCompile] private struct MyGenericJob2<T> : IMyGenericJob<T> { public void Execute() { } private static void UseConcreteType() { new MyGenericJob2<int>().Execute(); } } private static class MyJobProducer<TJob, T> { public static void Execute(ref TJob job) { } } private struct MyGenericJob2Wrapper<T1, T2> { public MyGenericJob2<T2> Job; private static void UseConcreteType() { var x = new MyGenericJob2Wrapper<float, double>(); x.Job.Execute(); } } [BurstCompile] private struct NonGenericType { [BurstCompile] public static void TestMethod1() { } } [BurstCompile] private struct GenericType<T> { public static Action Delegate1; public static Action Delegate2; public static Action Delegate3; [BurstCompile] public static void TestMethod1() { } [BurstCompile] public class NestedNonGeneric { [BurstCompile] public static void TestMethod2() { } } [BurstCompile] public class NestedGeneric<T2> { [BurstCompile] public static void TestMethod3() { } } private static void UseConcreteType() { // Store the delegates to static fields to avoid // them being optimized-away in Release builds Delegate1 = GenericType<int>.TestMethod1; Delegate2 = GenericType<int>.NestedNonGeneric.TestMethod2; Delegate3 = GenericType<int>.NestedGeneric<float>.TestMethod3; } } [BurstCompile] private struct MyGenericJobSeparateAssembly<T> : BurstReflectionTestsSeparateAssembly.IMyGenericJobSeparateAssembly<T> { public void Execute() { } private static void UseConcreteType() { new MyGenericJobSeparateAssembly<int>().Execute(); } } [Test] [TestCase("BurstReflectionTests.GenericMethodContainer.GenericMethod(T)")] public void ExcludesGenericMethods(string compileTargetName) { var result = BurstReflection.FindExecuteMethods(_assemblies, BurstReflectionAssemblyOptions.None); Assert.That(result.LogMessages, Is.Empty); var compileTarget = result.CompileTargets.Find(x => x.GetDisplayName() == compileTargetName); Assert.That(compileTarget, Is.Null); } [BurstCompile] private static class GenericMethodContainer { [BurstCompile] private static void GenericMethod<T>(T p) { } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal class RegisterGenericJobTypeAttribute : Attribute { public Type ConcreteType; public RegisterGenericJobTypeAttribute(Type type) { ConcreteType = type; } } [BurstCompile] internal struct GenericParallelForJob<T> : IJobParallelFor where T : struct { public void Execute(int index) { throw new System.NotImplementedException(); } } }