X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2Fcorlib%2FTest%2FSystem.Reflection.Emit%2FILGeneratorTest.cs;h=c943d6859ca60634cc75f9e2278d10163aab871f;hb=d0ad7e2df9bf67d11cd0164d39916f4659e606f1;hp=564c2851cf985b5f90341bf22b261ae0a2308b3e;hpb=64f85a65b023522d3f34e9932e6a843e0ad8fc3b;p=mono.git diff --git a/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs b/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs index 564c2851cf9..c943d6859ca 100644 --- a/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs +++ b/mcs/class/corlib/Test/System.Reflection.Emit/ILGeneratorTest.cs @@ -6,32 +6,22 @@ // (C) Novell, Inc. http://www.novell.com using System; +using System.Collections.Generic; using System.Reflection; using System.Reflection.Emit; +using System.Runtime.InteropServices; using System.Threading; using NUnit.Framework; -namespace MonoTests.System.Reflection.Emit { - +namespace MonoTests.System.Reflection.Emit +{ [TestFixture] - public class ILGeneratorTest { - + public class ILGeneratorTest + { TypeBuilder tb; ILGenerator il_gen; - static TypeBuilder DefineDynType () - { - AssemblyName assemblyName = new AssemblyName (); - assemblyName.Name = "MonoTests.System.Reflection.Emit.ILGeneratorTest"; - - AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly ( - assemblyName, AssemblyBuilderAccess.Run); - - ModuleBuilder module = assembly.DefineDynamicModule ("module1"); - return module.DefineType ("T", TypeAttributes.Public); - } - void DefineBasicMethod () { MethodBuilder mb = tb.DefineMethod("F", @@ -41,17 +31,43 @@ namespace MonoTests.System.Reflection.Emit { [SetUp] public void SetUp () - { - tb = DefineDynType (); + { + AssemblyName assemblyName = new AssemblyName (); + assemblyName.Name = "MonoTests.System.Reflection.Emit.ILGeneratorTest"; + + AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly ( + assemblyName, AssemblyBuilderAccess.Run); + + ModuleBuilder module = assembly.DefineDynamicModule ("module1"); + tb = module.DefineType ("T", TypeAttributes.Public); } [Test] - [ExpectedException (typeof (ArgumentNullException))] - public void DeclareLocal_NULL () + public void DeclareLocal_LocalType_Null () { DefineBasicMethod (); - il_gen.DeclareLocal (null); + try { + il_gen.DeclareLocal (null); + Assert.Fail ("#A1"); + } catch (ArgumentNullException ex) { + Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#A2"); + Assert.IsNull (ex.InnerException, "#A3"); + Assert.IsNotNull (ex.Message, "#A4"); + Assert.IsNotNull (ex.ParamName, "#A5"); + Assert.AreEqual ("localType", ex.ParamName, "#A"); + } + + try { + il_gen.DeclareLocal (null, false); + Assert.Fail ("#B1"); + } catch (ArgumentNullException ex) { + Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#B2"); + Assert.IsNull (ex.InnerException, "#B3"); + Assert.IsNotNull (ex.Message, "#B4"); + Assert.IsNotNull (ex.ParamName, "#B5"); + Assert.AreEqual ("localType", ex.ParamName, "#B6"); + } } [Test] @@ -59,7 +75,6 @@ namespace MonoTests.System.Reflection.Emit { public void DefineFilterBodyWithTypeNotNull () { DefineBasicMethod (); - il_gen.BeginExceptionBlock (); il_gen.EmitWriteLine ("in try"); il_gen.BeginExceptFilterBlock (); @@ -68,6 +83,50 @@ namespace MonoTests.System.Reflection.Emit { il_gen.EmitWriteLine ("in filter body"); il_gen.EndExceptionBlock (); } + + [Test] // bug #81431 + public void FilterAndCatchBlock () + { + DefineBasicMethod (); + ILGenerator il = il_gen; + il.BeginExceptionBlock (); + il.BeginExceptFilterBlock (); + il.BeginCatchBlock (null); + il.BeginCatchBlock (typeof (SystemException)); + } + + [Test] + [ExpectedException (typeof (InvalidOperationException))] + public void InvalidFilterBlock1 () + { + DefineBasicMethod (); + ILGenerator il = il_gen; + il.BeginExceptionBlock (); + il.BeginExceptFilterBlock (); + il.EndExceptionBlock (); + } + + [Test] + public void ValidFilterBlock1 () + { + DefineBasicMethod (); + ILGenerator il = il_gen; + il.BeginExceptionBlock (); + il.BeginExceptFilterBlock (); + il.BeginFaultBlock (); + il.EndExceptionBlock (); + } + + [Test] + public void ValidFilterBlock2 () + { + DefineBasicMethod (); + ILGenerator il = il_gen; + il.BeginExceptionBlock (); + il.BeginExceptFilterBlock (); + il.BeginFinallyBlock (); + il.EndExceptionBlock (); + } /// /// Try to emit something like that: @@ -125,6 +184,170 @@ namespace MonoTests.System.Reflection.Emit { il_gen.Emit (OpCodes.Ret); } + [Test] // Emit (OpCode, ConstructorInfo) + [Category ("NotDotNet")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610 + public void Emit3_Constructor_Null () + { + DefineBasicMethod (); + try { + il_gen.Emit (OpCodes.Newobj, (ConstructorInfo) null); + Assert.Fail ("#1"); + } catch (ArgumentNullException ex) { + Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2"); + Assert.IsNull (ex.InnerException, "#3"); + Assert.IsNotNull (ex.Message, "#4"); + Assert.IsNotNull (ex.ParamName, "#5"); + } + } + + [Test] // Emit (OpCode, ConstructorInfo) + [Category ("NotWorking")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610 + public void Emit3_Constructor_Null_MS () + { + DefineBasicMethod (); + try { + il_gen.Emit (OpCodes.Newobj, (ConstructorInfo) null); + Assert.Fail ("#1"); + } catch (NullReferenceException) { + } + } + + [Test] // Emit (OpCode, FieldInfo) + public void Emit5_Field_Null () + { + DefineBasicMethod (); + try { + il_gen.Emit (OpCodes.Ldsfld, (FieldInfo) null); + Assert.Fail ("#1"); + } catch (ArgumentNullException ex) { + Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2"); + Assert.IsNull (ex.InnerException, "#3"); + Assert.IsNotNull (ex.Message, "#4"); + Assert.IsNotNull (ex.ParamName, "#5"); + } + } + + [Test] // Emit (OpCode, Label []) + [Category ("NotDotNet")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610 + public void Emit10_Labels_Null () + { + DefineBasicMethod (); + try { + il_gen.Emit (OpCodes.Switch, (Label []) null); + Assert.Fail ("#1"); + } catch (ArgumentNullException ex) { + Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2"); + Assert.IsNull (ex.InnerException, "#3"); + Assert.IsNotNull (ex.Message, "#4"); + Assert.IsNotNull (ex.ParamName, "#5"); + Assert.AreEqual ("labels", ex.ParamName, "#6"); + } + } + + [Test] + [Category ("NotWorking")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610 + public void Emit10_Labels_Null_MS () + { + DefineBasicMethod (); + try { + il_gen.Emit (OpCodes.Switch, (Label []) null); + Assert.Fail ("#1"); + } catch (NullReferenceException) { + } + } + + [Test] // Emit (OpCode, LocalBuilder) + public void Emit11_Local_Null () + { + DefineBasicMethod (); + try { + il_gen.Emit (OpCodes.Switch, (LocalBuilder) null); + Assert.Fail ("#1"); + } catch (ArgumentNullException ex) { + Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2"); + Assert.IsNull (ex.InnerException, "#3"); + Assert.IsNotNull (ex.Message, "#4"); + Assert.IsNotNull (ex.ParamName, "#5"); + Assert.AreEqual ("local", ex.ParamName, "#6"); + } + } + + [Test] // Emit (OpCode, MethodInfo) + public void Emit12_Method_Null () + { + DefineBasicMethod (); + try { + il_gen.Emit (OpCodes.Switch, (MethodInfo) null); + Assert.Fail ("#1"); + } catch (ArgumentNullException ex) { + Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2"); + Assert.IsNull (ex.InnerException, "#3"); + Assert.IsNotNull (ex.Message, "#4"); + Assert.IsNotNull (ex.ParamName, "#5"); + Assert.AreEqual ("meth", ex.ParamName, "#6"); + } + } + + [Test] // Emit (OpCode, SignatureHelper) + public void Emit14_Signature_Null () + { + DefineBasicMethod (); + try { + il_gen.Emit (OpCodes.Switch, (SignatureHelper) null); + Assert.Fail ("#1"); + } catch (ArgumentNullException ex) { + Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2"); + Assert.IsNull (ex.InnerException, "#3"); + Assert.IsNotNull (ex.Message, "#4"); + Assert.IsNotNull (ex.ParamName, "#5"); + } + } + + [Test] // Emit (OpCode, String) + public void Emit16_String_Null () + { + DefineBasicMethod (); + try { + il_gen.Emit (OpCodes.Switch, (String) null); + Assert.Fail ("#1"); + } catch (ArgumentNullException ex) { + Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2"); + Assert.IsNull (ex.InnerException, "#3"); + Assert.IsNotNull (ex.Message, "#4"); + } + } + + [Test] // Emit (OpCode, Type) + public void Emit16_Type_Null () + { + DefineBasicMethod (); + try { + il_gen.Emit (OpCodes.Switch, (Type) null); + Assert.Fail ("#1"); + } catch (ArgumentNullException ex) { + Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2"); + Assert.IsNull (ex.InnerException, "#3"); + Assert.IsNotNull (ex.Message, "#4"); + Assert.IsNotNull (ex.ParamName, "#5"); + } + } + + [Test] + public void EmitCall_MethodInfo_Null () + { + DefineBasicMethod (); + try { + il_gen.EmitCall (OpCodes.Call, (MethodInfo) null, null); + Assert.Fail ("#1"); + } catch (ArgumentNullException ex) { + Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2"); + Assert.IsNull (ex.InnerException, "#3"); + Assert.IsNotNull (ex.Message, "#4"); + Assert.IsNotNull (ex.ParamName, "#5"); + Assert.AreEqual ("methodInfo", ex.ParamName, "#6"); + } + } + [Test] public void TestFilterEmittingWithHandlerExecution () { @@ -135,6 +358,40 @@ namespace MonoTests.System.Reflection.Emit { Assert.IsTrue ((bool) tf.Invoke (null, new object [] { true })); } + delegate void FooFoo (); + + static void Foo () + { + } + + [Test] + public void TestEmitCalliWithNullReturnType () + { + MethodBuilder mb = tb.DefineMethod ("F", + MethodAttributes.Public | MethodAttributes.Static, null, new Type [] { typeof (IntPtr) }); + mb.SetImplementationFlags (MethodImplAttributes.NoInlining); + il_gen = mb.GetILGenerator (); + il_gen.Emit (OpCodes.Ldarg_0); + il_gen.EmitCalli (OpCodes.Calli, CallingConvention.StdCall, null, Type.EmptyTypes); + il_gen.Emit (OpCodes.Ret); + + Type dynt = tb.CreateType (); + dynt.GetMethod ("F", BindingFlags.Public | BindingFlags.Static).Invoke ( + null, new object [] { Marshal.GetFunctionPointerForDelegate (new FooFoo (Foo)) }); + } + + //Test for #509131 + [Test] + public void TestEmitCallIgnoresOptionalArgsForNonVarargMethod () + { + DefineBasicMethod (); + try { + il_gen.EmitCall (OpCodes.Call, typeof (object).GetMethod ("GetHashCode"), new Type[] { typeof (string) }); + } catch (InvalidOperationException ex) { + Assert.Fail ("#1"); + } + } + [Test] [ExpectedException (typeof (Exception))] public void TestFilterEmittingWithoutHandlerExecution () @@ -149,5 +406,171 @@ namespace MonoTests.System.Reflection.Emit { throw tie.InnerException; } } + + [Test] + public void TestEmitLocalInfoWithNopOpCode () + { + var method_builder = tb.DefineMethod ("linop", MethodAttributes.Public | MethodAttributes.Static, typeof (bool), Type.EmptyTypes); + il_gen = method_builder.GetILGenerator (); + + var local = il_gen.DeclareLocal (typeof (int)); + il_gen.Emit (OpCodes.Nop, local); + il_gen.Emit (OpCodes.Ldc_I4_1); + il_gen.Emit (OpCodes.Ret); + + var type = tb.CreateType (); + var method = type.GetMethod ("linop"); + + Assert.IsNotNull (method); + Assert.IsTrue ((bool) method.Invoke (null, new object [0])); + } + + [Test] + [ExpectedException (typeof (ArgumentException))] + public void LdObjByRef () { + DefineBasicMethod (); + ILGenerator ig = il_gen; + + ig.Emit (OpCodes.Ldtoken, typeof (int).MakeByRefType ()); + } + + + + [Test] //bug #649017 + public void GtdEncodingAsOpenInstance () { + AssemblyName asmname = new AssemblyName (); + asmname.Name = "test"; + AssemblyBuilder asmbuild = Thread.GetDomain ().DefineDynamicAssembly (asmname, AssemblyBuilderAccess.RunAndSave); + ModuleBuilder modbuild = asmbuild.DefineDynamicModule ("modulename", "test.exe"); + + TypeBuilder myType = modbuild.DefineType ("Sample", TypeAttributes.Public); + + string[] typeParamNames = { "TFirst" }; + myType.DefineGenericParameters (typeParamNames); + + var nested = myType.DefineNestedType ("nested"); + nested.DefineGenericParameters (typeParamNames); + + var m = myType.DefineMethod ("test", MethodAttributes.Public); + m.SetParameters (myType); + + var ilgen = m.GetILGenerator (); + ilgen.Emit (OpCodes.Castclass, nested); + ilgen.Emit (OpCodes.Castclass, typeof (List<>)); + ilgen.Emit (OpCodes.Ldtoken, nested); + ilgen.Emit (OpCodes.Ldtoken, typeof (List<>)); + + var baked = myType.CreateType (); + nested.CreateType (); + + var method = baked.GetMethod ("test"); + var body = method.GetMethodBody (); + /* + The resulting IL is: + [ 0] 0x74 token:uint + [ 5] 0x74 token:uint + [10] 0xd0 token:uint + [10] 0xd0 token:uint + The first two tokens must be to typespecs and the last two to typeref/typedef*/ + var il = body.GetILAsByteArray (); + + Assert.AreEqual (20, il.Length, "#1"); + Assert.AreEqual (0x1B, il [4]); //typespec + Assert.AreEqual (0x1B, il [9]); //typespec + Assert.AreEqual (0x02, il [14]); //typedef + Assert.AreEqual (0x01, il [19]); //typeref + } + + [Test] + public void MethodRefTokenSame () { + // Get the same non-virtual method from a base and a derived type so + // that the MemberInfo:DeclaredType differs but the tokens are the same. + // + // Regression test for bugzilla #59364 + + DefineBasicMethod (); + + var m1 = typeof (object).GetMethod ("GetType"); + var m2 = typeof (string).GetMethod ("GetType"); + + var value_getter = typeof (RuntimeMethodHandle).GetProperty ("Value").GetMethod; + + var il = il_gen; + + var loc = il.DeclareLocal (typeof (RuntimeMethodHandle)); + + // return ((int)(RuntimeMethodHandle (m1).Value == RuntimeMethodHandle (m2).Value)).ToString () + il.Emit (OpCodes.Ldtoken, m1); + il.Emit (OpCodes.Stloc, loc); + il.Emit (OpCodes.Ldloca, loc); + il.Emit (OpCodes.Call, value_getter); + il.Emit (OpCodes.Ldtoken, m2); + il.Emit (OpCodes.Stloc, loc); + il.Emit (OpCodes.Ldloca, loc); + il.Emit (OpCodes.Call, value_getter); + il.Emit (OpCodes.Ceq); + il.Emit (OpCodes.Box, typeof (Int32)); + il.Emit (OpCodes.Callvirt, typeof (object).GetMethod ("ToString")); + il.Emit (OpCodes.Ret); + + var baked = tb.CreateType (); + + var x = Activator.CreateInstance (baked); + var m = baked.GetMethod ("F"); + + var s = m.Invoke (x, null); + + Assert.AreEqual ("1", s); + + } + + public class Base { + public int x; + } + + public class Derived : Base { + } + + [Test] + public void FieldRefTokenSame () { + DefineBasicMethod (); + + // Get the same field from a base and a derived type so hat + // the MemberInfo:DeclaredType differs but the tokens are the same. + // + // Regression test for bugzilla #59364 + + var f1 = typeof (Base).GetField ("x"); + var f2 = typeof (Derived).GetField ("x"); + + var value_getter = typeof (RuntimeFieldHandle).GetProperty("Value").GetMethod; + + var il = il_gen; + + var loc = il.DeclareLocal (typeof (RuntimeFieldHandle)); + + il.Emit (OpCodes.Ldtoken, f1); + il.Emit (OpCodes.Stloc, loc); + il.Emit (OpCodes.Ldloca, loc); + il.Emit (OpCodes.Call, value_getter); + il.Emit (OpCodes.Ldtoken, f2); + il.Emit (OpCodes.Stloc, loc); + il.Emit (OpCodes.Ldloca, loc); + il.Emit (OpCodes.Call, value_getter); + il.Emit (OpCodes.Ceq); + il.Emit (OpCodes.Box, typeof (Int32)); + il.Emit (OpCodes.Callvirt, typeof (object).GetMethod ("ToString")); + il.Emit (OpCodes.Ret); + + var baked = tb.CreateType (); + + var x = Activator.CreateInstance (baked); + var m = baked.GetMethod ("F"); + + var s = m.Invoke (x, null); + + Assert.AreEqual ("1", s); + } + } }