From ce8ddfe768a8c97434939a358fea7e3972a5c906 Mon Sep 17 00:00:00 2001 From: Washi Date: Wed, 20 Mar 2024 20:51:55 +0100 Subject: [PATCH] Add static method and field integration test. --- .../Emulation/CilThread.cs | 2 +- .../Emulation/Runtime/RuntimeTypeManager.cs | 4 ++-- .../Emulation/CilVirtualMachineTest.cs | 19 +++++++++++++++++++ test/Platforms/Mocks/ClassWithInitializer.cs | 3 +++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/Platforms/Echo.Platforms.AsmResolver/Emulation/CilThread.cs b/src/Platforms/Echo.Platforms.AsmResolver/Emulation/CilThread.cs index 9482c0d9..8fd524b3 100644 --- a/src/Platforms/Echo.Platforms.AsmResolver/Emulation/CilThread.cs +++ b/src/Platforms/Echo.Platforms.AsmResolver/Emulation/CilThread.cs @@ -289,7 +289,7 @@ private bool UnwindCallStack(ref ObjectHandle exceptionObject) // If the exception happened in a .cctor, register it and wrap it in a type initialization error. if (currentFrame.Body?.Owner is { IsConstructor: true, IsStatic: true, DeclaringType: {} type }) - exceptionObject = Machine.TypeManager.RegisterTypeInitializationException(type, exceptionObject); + exceptionObject = Machine.TypeManager.RegisterInitializationException(type, exceptionObject); var result = currentFrame.ExceptionHandlerStack.RegisterException(exceptionObject); if (result.IsSuccess) diff --git a/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Runtime/RuntimeTypeManager.cs b/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Runtime/RuntimeTypeManager.cs index ea56f12c..99a1432f 100644 --- a/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Runtime/RuntimeTypeManager.cs +++ b/src/Platforms/Echo.Platforms.AsmResolver/Emulation/Runtime/RuntimeTypeManager.cs @@ -47,7 +47,7 @@ private TypeInitialization GetInitialization(ITypeDescriptor type) /// The type that failed to initialize. /// The exception object that describes the failure. /// The resulting TypeInitializationException instance. - public ObjectHandle RegisterTypeInitializationException(ITypeDescriptor type, ObjectHandle innerException) + public ObjectHandle RegisterInitializationException(ITypeDescriptor type, ObjectHandle innerException) { var initialization = GetInitialization(type); if (!initialization.Exception.IsNull) @@ -62,7 +62,7 @@ public ObjectHandle RegisterTypeInitializationException(ITypeDescriptor type, Ob .AsObjectHandle(_machine); } - // TODO: incorporate `exceptionObject`. + // TODO: incorporate `innerException`. } return initialization.Exception; diff --git a/test/Platforms/Echo.Platforms.AsmResolver.Tests/Emulation/CilVirtualMachineTest.cs b/test/Platforms/Echo.Platforms.AsmResolver.Tests/Emulation/CilVirtualMachineTest.cs index 3c698ae9..4199ffdd 100644 --- a/test/Platforms/Echo.Platforms.AsmResolver.Tests/Emulation/CilVirtualMachineTest.cs +++ b/test/Platforms/Echo.Platforms.AsmResolver.Tests/Emulation/CilVirtualMachineTest.cs @@ -12,6 +12,7 @@ using Echo.Platforms.AsmResolver.Emulation.Invocation; using Echo.Platforms.AsmResolver.Tests.Emulation.Dispatch; using Echo.Platforms.AsmResolver.Tests.Mock; +using Mocks; using Xunit; using Xunit.Abstractions; using Xunit.Sdk; @@ -587,5 +588,23 @@ public void CallAndThrowUnhandledException(string methodName, object parameter) Assert.Equal(expectedException.GetType().FullName, result.ExceptionObject.GetObjectType().FullName); } + [Fact] + public void StaticFieldWithInitialValueUpdate() + { + var type = _fixture.MockModule.LookupMember(typeof(ClassWithInitializer).MetadataToken); + var increment = type.Methods.First(m => m.Name == nameof(ClassWithInitializer.IncrementCounter)); + var counter = type.Fields.First(f => f.Name == nameof(ClassWithInitializer.Counter)); + + // Verify uninitialized value. + Assert.Equal(0, _vm.StaticFields.GetFieldSpan(counter).I32); + + // Call and verify value. + _mainThread.Call(increment, Array.Empty()); + Assert.Equal(1337 + 1, _vm.StaticFields.GetFieldSpan(counter).I32); + _mainThread.Call(increment, Array.Empty()); + Assert.Equal(1337 + 2, _vm.StaticFields.GetFieldSpan(counter).I32); + _mainThread.Call(increment, Array.Empty()); + Assert.Equal(1337 + 3, _vm.StaticFields.GetFieldSpan(counter).I32); + } } } \ No newline at end of file diff --git a/test/Platforms/Mocks/ClassWithInitializer.cs b/test/Platforms/Mocks/ClassWithInitializer.cs index 47adce94..2ebc33bb 100644 --- a/test/Platforms/Mocks/ClassWithInitializer.cs +++ b/test/Platforms/Mocks/ClassWithInitializer.cs @@ -3,8 +3,11 @@ namespace Mocks; public class ClassWithInitializer { public static string Field = "Test"; + public static int Counter = 1337; public static string MethodNoFieldAccess() => "MethodNoFieldAccess"; public static string MethodFieldAccess() => "MethodFieldAccess: " + Field; + + public static void IncrementCounter() => Counter++; } \ No newline at end of file