[test] SRE ILGenerator test for methodref and fieldref token caching
[mono.git] / mcs / class / corlib / Test / System.Reflection.Emit / ILGeneratorTest.cs
index 71e085c298f2ccefd1825a4b835305f0a6159e77..c943d6859ca60634cc75f9e2278d10163aab871f 100644 (file)
@@ -6,6 +6,7 @@
 // (C) Novell, Inc.  http://www.novell.com
 
 using System;
+using System.Collections.Generic;
 using System.Reflection;
 using System.Reflection.Emit;
 using System.Runtime.InteropServices;
@@ -57,7 +58,6 @@ namespace MonoTests.System.Reflection.Emit
                                Assert.AreEqual ("localType", ex.ParamName, "#A");
                        }
 
-#if NET_2_0
                        try {
                                il_gen.DeclareLocal (null, false);
                                Assert.Fail ("#B1");
@@ -68,7 +68,6 @@ namespace MonoTests.System.Reflection.Emit
                                Assert.IsNotNull (ex.ParamName, "#B5");
                                Assert.AreEqual ("localType", ex.ParamName, "#B6");
                        }
-#endif
                }
 
                [Test]
@@ -186,9 +185,7 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test] // Emit (OpCode, ConstructorInfo)
-#if NET_2_0
                [Category ("NotDotNet")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610
-#endif
                public void Emit3_Constructor_Null ()
                {
                        DefineBasicMethod ();
@@ -203,7 +200,6 @@ namespace MonoTests.System.Reflection.Emit
                        }
                }
 
-#if NET_2_0
                [Test] // Emit (OpCode, ConstructorInfo)
                [Category ("NotWorking")] // MS bug: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=304610
                public void Emit3_Constructor_Null_MS ()
@@ -215,7 +211,6 @@ namespace MonoTests.System.Reflection.Emit
                        } catch (NullReferenceException) {
                        }
                }
-#endif
 
                [Test] // Emit (OpCode, FieldInfo)
                public void Emit5_Field_Null ()
@@ -363,7 +358,6 @@ namespace MonoTests.System.Reflection.Emit
                        Assert.IsTrue ((bool) tf.Invoke (null, new object [] { true }));
                }
 
-#if NET_2_0
                delegate void FooFoo ();
 
                static void Foo ()
@@ -385,7 +379,18 @@ namespace MonoTests.System.Reflection.Emit
                        dynt.GetMethod ("F", BindingFlags.Public | BindingFlags.Static).Invoke (
                                null, new object [] { Marshal.GetFunctionPointerForDelegate (new FooFoo (Foo)) });
                }
-#endif
+
+               //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))]
@@ -401,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);
+               }
+
        }
 }