[test] SRE ILGenerator test for methodref and fieldref token caching
[mono.git] / mcs / class / corlib / Test / System.Reflection.Emit / ILGeneratorTest.cs
index fa3c9fc7c28519b3a43761838fdb420b5690c0f8..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,9 +379,7 @@ namespace MonoTests.System.Reflection.Emit
                        dynt.GetMethod ("F", BindingFlags.Public | BindingFlags.Static).Invoke (
                                null, new object [] { Marshal.GetFunctionPointerForDelegate (new FooFoo (Foo)) });
                }
-#endif
 
-#if NET_2_0
                //Test for #509131
                [Test]
                public void TestEmitCallIgnoresOptionalArgsForNonVarargMethod ()
@@ -399,18 +391,6 @@ namespace MonoTests.System.Reflection.Emit
                                Assert.Fail ("#1");
                        }
                }
-#else
-               [Test]
-               public void TestEmitCallThrowsOnOptionalArgsForNonVarargMethod ()
-               {
-                       DefineBasicMethod ();
-                       try {
-                               il_gen.EmitCall (OpCodes.Call, typeof (object).GetMethod ("GetHashCode"), new Type[] { typeof (string) });
-                               Assert.Fail ("#1");
-                       } catch (InvalidOperationException ex) {
-                       }
-               }
-#endif
 
                [Test]
                [ExpectedException (typeof (Exception))]
@@ -453,5 +433,144 @@ namespace MonoTests.System.Reflection.Emit
 
                        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);
+               }
+
        }
 }