aboutsummaryrefslogtreecommitdiff
path: root/runtime/VMProtect.Runtime/Tests/UnitTestProject/MsilToVmTestCompiler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/VMProtect.Runtime/Tests/UnitTestProject/MsilToVmTestCompiler.cs')
-rw-r--r--runtime/VMProtect.Runtime/Tests/UnitTestProject/MsilToVmTestCompiler.cs100
1 files changed, 100 insertions, 0 deletions
diff --git a/runtime/VMProtect.Runtime/Tests/UnitTestProject/MsilToVmTestCompiler.cs b/runtime/VMProtect.Runtime/Tests/UnitTestProject/MsilToVmTestCompiler.cs
new file mode 100644
index 0000000..1e205c5
--- /dev/null
+++ b/runtime/VMProtect.Runtime/Tests/UnitTestProject/MsilToVmTestCompiler.cs
@@ -0,0 +1,100 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.ExceptionServices;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace UnitTestProject
+{
+ public abstract class MsilToVmTestCompiler
+ {
+ public enum LongEnum : long { Eval1 = 1, Evalm1 = -1 }
+ public enum ULongEnum : ulong { Evalm1 = 0xFFFFFFFFFFFFFFFF }
+ public enum ByteEnum : byte {}
+ public enum SByteEnum : sbyte { }
+ public enum IntEnum /*: int*/ { }
+ public enum UIntEnum : uint { }
+ public enum ShortEnum : short { }
+ public enum UShortEnum : ushort { }
+
+ public static byte[] GetIlBytes(DynamicMethod dynamicMethod)
+ {
+ // ReSharper disable once PossibleNullReferenceException
+ var resolver = typeof(DynamicMethod).GetField("m_resolver", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(dynamicMethod);
+ if (resolver == null) throw new ArgumentException("The dynamic method's IL has not been finalized.");
+ // ReSharper disable once PossibleNullReferenceException
+ return (byte[])resolver.GetType().GetField("m_code", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(resolver);
+ }
+
+ public abstract Stream CreateVmStream(Type rt, ParameterInfo[] pi, Type[] locals, byte[] ilBytes);
+
+ public enum InvokeTestCombineError
+ {
+ NoError,
+ NoErrorByStdEx, // текущий стандарт ECMA-335 оставляет некоторые сценарии как "неопределенное поведение", но их можно определить
+ VmOtherExceptionExpected,
+ VmOtherTypeExpected,
+ VmOtherValueExpected,
+ Cnt
+ };
+ // dyn/vm обязаны что-то возвратить, либо выбросить исключение
+ // (в тестах не должно быть методов, возвращающих void, null или исключение в качестве retVal)
+ [HandleProcessCorruptedStateExceptions]
+ public InvokeTestCombineError InvokeTestCombine(DynamicMethod dyn, object[] parameters, out object dynRet, out object vmRet, out string err)
+ {
+ Type exceptionType = null;
+ err = "";
+ try
+ {
+ dynRet = dyn.Invoke(null, parameters);
+ Assert.IsNotNull(dynRet);
+ Assert.IsInstanceOfType(dynRet, dyn.ReturnType);
+ }
+ catch (Exception e)
+ {
+ Assert.IsInstanceOfType(e, typeof(TargetInvocationException));
+ Assert.IsNotNull(e.InnerException);
+ exceptionType = e.InnerException.GetType();
+ dynRet = e.InnerException;
+ }
+ var vmStream = CreateVmStream(dyn.ReturnType, dyn.GetBaseDefinition().GetParameters(),
+ //FIXME dyn.GetMethodBody().LocalVariables.Select(o => o.LocalType).ToArray(),
+ new Type[] {},
+ GetIlBytes(dyn));
+ try
+ {
+ vmRet = Invoke(parameters, vmStream);
+ if(exceptionType != null)
+ {
+ err = $"VmOtherExceptionExpected: {exceptionType.FullName}, actual: {vmRet}";
+ return InvokeTestCombineError.VmOtherExceptionExpected;
+ }
+ if (vmRet == null || vmRet.GetType() != dyn.ReturnType)
+ {
+ err = $"VmOtherTypeExpected: {dyn.ReturnType.FullName}, actual: {((vmRet != null) ? vmRet.GetType().FullName : "null")}";
+ return InvokeTestCombineError.VmOtherTypeExpected;
+ }
+ }
+ catch (Exception e)
+ {
+ vmRet = e;
+ if (e.GetType() != exceptionType)
+ {
+ err = $"VmOtherExceptionExpected: {((exceptionType != null) ? exceptionType.FullName : dynRet)}, actual: {e.GetType().FullName}";
+ return InvokeTestCombineError.VmOtherExceptionExpected;
+ }
+ return InvokeTestCombineError.NoError;
+ }
+ if (dynRet.Equals(vmRet))
+ {
+ return InvokeTestCombineError.NoError;
+ }
+ err = $"VmOtherValueExpected: {dynRet}, actual: {vmRet}";
+ return InvokeTestCombineError.VmOtherValueExpected;
+ }
+
+ public abstract object Invoke(object[] parameters, Stream vmStream);
+ }
+}