using System; using System.Linq; using System.Reflection; using NUnit.Framework.Interfaces; using NUnit.Framework.Internal; using NUnit.Framework.Internal.Builders; using Unity.Burst; using UnityEngine; namespace Burst.Compiler.IL.Tests { internal class TestCompilerAttribute : TestCompilerAttributeBase { public TestCompilerAttribute(params object[] arguments) : base(arguments) { } protected override bool IsCommandLine() { return false; } protected override bool IsMono() { return true; } protected override bool SupportException { get { // We don't support exception in Unity editor return false; } } protected override TestCompilerCommandBase GetTestCommand(TestCompilerAttributeBase attribute, Test test, TestMethod originalMethod) { return new TestCompilerCommand(attribute, test, originalMethod); } public class TestCompilerCommand : TestCompilerCommandBase { public TestCompilerCommand(TestCompilerAttributeBase attribute, Test test, TestMethod originalMethod) : base(attribute, test, originalMethod) { } protected override int GetRunCount() { return 1; } protected override void CompleteTest(ITestExecutionContext context) { context.CurrentResult.SetResult(ResultState.Success); } protected override int GetULP() { return 512; } protected override object[] GetArgumentsArray(TestMethod method) { return method.parms.Arguments.ToArray(); } protected unsafe Delegate CompileDelegate(ITestExecutionContext context, MethodInfo methodInfo, Type delegateType, byte* returnBox, out Type returnBoxType) { return CompileDelegate(context, methodInfo, delegateType, returnBox, out returnBoxType, out _); } protected unsafe override Delegate CompileDelegate(ITestExecutionContext context, MethodInfo methodInfo, Type delegateType, byte* returnBox, out Type returnBoxType, out Delegate interpretDelegate) { interpretDelegate = null; returnBoxType = null; var functionDelegate = Delegate.CreateDelegate(delegateType, methodInfo); var compiledFunction = BurstCompiler.CompileDelegate(functionDelegate); return compiledFunction; } protected override void GoldFileTestForOtherPlatforms(MethodInfo methodInfo, bool testWasRun) { // This is a no-op here. } protected override bool TestOnCurrentHostEnvironment(MethodInfo methodInfo) { // Query architecture via burst to avoid mono bug in detecting processor architecture if (BurstCompiler.IsHostEditorArm()) return !methodInfo.CustomAttributes.Any((e) => e.AttributeType.Name == "TestCpuAttribute"); return true; } protected override object CompileFunctionPointer(MethodInfo methodInfo, Type functionType) { throw new NotImplementedException(); } protected override bool InterpretMethod(Delegate interpretDelegate, MethodInfo methodInfo, object[] args, Type returnType, out string reason, out object result) { reason = null; result = null; return false; } protected override void Setup() { } protected override TestResult HandleCompilerException(ITestExecutionContext context, MethodInfo methodInfo) { var arguments = GetArgumentsArray(_originalMethod); Type[] nativeArgTypes = new Type[arguments.Length]; for (var i = 0; i < arguments.Length; ++i) { nativeArgTypes[i] = arguments[i].GetType(); } bool isInRegistry; Func caller; var delegateType = CreateNativeDelegateType(methodInfo.ReturnType, nativeArgTypes, out isInRegistry, out caller); var functionDelegate = Delegate.CreateDelegate(delegateType, methodInfo); Delegate compiledFunction = BurstCompiler.CompileDelegate(functionDelegate); if (functionDelegate == compiledFunction) context.CurrentResult.SetResult(ResultState.Success); else context.CurrentResult.SetResult(ResultState.Failure, $"The function have been compiled successfully, but an error was expected."); return context.CurrentResult; } string cachedLog = null; bool logPresent = false; protected override string GetLinesFromDeterminismLog() { if (cachedLog==null) { try { TextAsset txtData = (TextAsset)Resources.Load("btests_deterministic"); cachedLog = txtData.text; logPresent = true; } catch { logPresent = false; } } return cachedLog; } protected override bool IsDeterministicTest(TestMethod method) { return logPresent && (method.Method.ReturnType.IsType(typeof(double)) || method.Method.ReturnType.IsType(typeof(float))); } protected override TestCompilerBaseExtensions GetExtension() { return null; } protected override bool TargetIs32Bit() { return false; } } } }