Merge pull request #3626 from lateralusX/jlorenss/win-api-family-support-eglib
[mono.git] / mcs / class / corlib / Test / System.Reflection.Emit / TypeBuilderTest.cs
index 4d98020142651a89ae5ee6863e384a0b5ee9ac3c..43f32cfa5959467d35da5011b26986550ffe0368 100644 (file)
@@ -24,7 +24,6 @@ using System.Security.Permissions;
 using System.Runtime.InteropServices;
 using NUnit.Framework;
 using System.Runtime.CompilerServices;
-
 using System.Collections.Generic;
 
 namespace MonoTests.System.Reflection.Emit
@@ -52,7 +51,7 @@ namespace MonoTests.System.Reflection.Emit
        [TestFixture]
        public class TypeBuilderTest
        {
-               private interface AnInterface
+               public interface AnInterface
                {
                }
 
@@ -93,8 +92,8 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                public class Tuple <A,B> {
-                       A a;
-                       B b;
+                       public A a;
+                       public B b;
                }
 
                private AssemblyBuilder assembly;
@@ -1183,6 +1182,7 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
+               [Category ("AndroidNotWorking")] // Fails with System.MethodAccessException : Method `t17:.ctor ()' is inaccessible from method `t18:.ctor ()'
                public void DefineDefaultConstructor_Parent_DefaultCtorInaccessible ()
                {
                        TypeBuilder tb;
@@ -8435,6 +8435,7 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
+               [Category ("MobileNotWorking")] // Not available in the 2.1 profile
                public void TestAddDeclarativeSecurityAlreadyCreated ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
@@ -8453,6 +8454,7 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
+               [Category ("MobileNotWorking")] // Not available in the 2.1 profile
                public void TestAddDeclarativeSecurityNullPermissionSet ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
@@ -8469,6 +8471,7 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
+               [Category ("MobileNotWorking")] // Not available in the 2.1 profile
                public void TestAddDeclarativeSecurityInvalidAction ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
@@ -8489,6 +8492,7 @@ namespace MonoTests.System.Reflection.Emit
                }
 
                [Test]
+               [Category ("MobileNotWorking")] // Not available in the 2.1 profile
                public void TestAddDeclarativeSecurityDuplicateAction ()
                {
                        TypeBuilder tb = module.DefineType (genTypeName ());
@@ -8969,7 +8973,7 @@ namespace MonoTests.System.Reflection.Emit
                        Assert.IsFalse (tb.IsAssignableFrom (typeof (FileStream)), "#C6");
                        Assert.IsTrue (typeof (object).IsAssignableFrom (tb), "#C7");
                        Assert.IsFalse (tb.IsAssignableFrom (typeof (object)), "#C8");
-                       Assert.IsFalse (typeof (IDisposable).IsAssignableFrom (tb), "#C9");
+                       Assert.IsTrue (typeof (IDisposable).IsAssignableFrom (tb), "#C9");
                        Assert.IsFalse (tb.IsAssignableFrom (typeof (IDisposable)), "#C10");
 
                        Assert.IsTrue (tb.IsAssignableFrom (tb), "#D1");
@@ -8977,13 +8981,13 @@ namespace MonoTests.System.Reflection.Emit
 
                        TypeBuilder tb2 = module.DefineType (genTypeName (),
                                TypeAttributes.Public, tb,
-                               new Type [] { typeof (IAir) });
+                               new Type[] { typeof (IAir) });
 
-                       Assert.IsFalse (typeof (IThrowable).IsAssignableFrom (tb2), "#E1");
+                       Assert.IsTrue (typeof (IThrowable).IsAssignableFrom (tb2), "#E1");
                        Assert.IsFalse (tb2.IsAssignableFrom (typeof (IThrowable)), "#E2");
-                       Assert.IsFalse (typeof (IMoveable).IsAssignableFrom (tb2), "#E3");
+                       Assert.IsTrue (typeof (IMoveable).IsAssignableFrom (tb2), "#E3");
                        Assert.IsFalse (tb2.IsAssignableFrom (typeof (IMoveable)), "#E4");
-                       Assert.IsFalse (typeof (IComparable).IsAssignableFrom (tb2), "#E5");
+                       Assert.IsTrue (typeof (IComparable).IsAssignableFrom (tb2), "#E5");
                        Assert.IsFalse (tb2.IsAssignableFrom (typeof (IComparable)), "#E6");
                        Assert.IsTrue (typeof (IAir).IsAssignableFrom (tb2), "#E7");
                        Assert.IsFalse (tb2.IsAssignableFrom (typeof (IAir)), "#E8");
@@ -8992,9 +8996,9 @@ namespace MonoTests.System.Reflection.Emit
                        Assert.IsFalse (typeof (ILiquid).IsAssignableFrom (tb2), "#E11");
                        Assert.IsFalse (tb2.IsAssignableFrom (typeof (ILiquid)), "#E12");
 
-                       Assert.IsFalse (typeof (Foo).IsAssignableFrom (tb2), "#F1");
+                       Assert.IsTrue (typeof (Foo).IsAssignableFrom (tb2), "#F1");
                        Assert.IsFalse (tb2.IsAssignableFrom (typeof (Foo)), "#F2");
-                       Assert.IsFalse (typeof (Bar).IsAssignableFrom (tb2), "#F3");
+                       Assert.IsTrue (typeof (Bar).IsAssignableFrom (tb2), "#F3");
                        Assert.IsFalse (tb2.IsAssignableFrom (typeof (Bar)), "#F4");
                        Assert.IsFalse (typeof (Baz).IsAssignableFrom (tb2), "#F5");
                        Assert.IsFalse (tb2.IsAssignableFrom (typeof (Baz)), "#F6");
@@ -9007,7 +9011,7 @@ namespace MonoTests.System.Reflection.Emit
                        Assert.IsFalse (tb2.IsAssignableFrom (typeof (FileStream)), "#G6");
                        Assert.IsTrue (typeof (object).IsAssignableFrom (tb2), "#G7");
                        Assert.IsFalse (tb2.IsAssignableFrom (typeof (object)), "#G8");
-                       Assert.IsFalse (typeof (IDisposable).IsAssignableFrom (tb2), "#G9");
+                       Assert.IsTrue (typeof (IDisposable).IsAssignableFrom (tb2), "#G9");
                        Assert.IsFalse (tb2.IsAssignableFrom (typeof (IDisposable)), "#G10");
 
                        Assert.IsTrue (tb2.IsAssignableFrom (tb2), "#H1");
@@ -9016,24 +9020,24 @@ namespace MonoTests.System.Reflection.Emit
 
                        TypeBuilder tb3 = module.DefineType (genTypeName (),
                                TypeAttributes.Public, tb2,
-                               new Type [] { typeof (IWater) });
+                               new Type[] { typeof (IWater) });
 
-                       Assert.IsFalse (typeof (IThrowable).IsAssignableFrom (tb3), "#I1");
+                       Assert.IsTrue (typeof (IThrowable).IsAssignableFrom (tb3), "#I1");
                        Assert.IsFalse (tb3.IsAssignableFrom (typeof (IThrowable)), "#I2");
-                       Assert.IsFalse (typeof (IMoveable).IsAssignableFrom (tb3), "#I3");
+                       Assert.IsTrue (typeof (IMoveable).IsAssignableFrom (tb3), "#I3");
                        Assert.IsFalse (tb3.IsAssignableFrom (typeof (IMoveable)), "#I4");
-                       Assert.IsFalse (typeof (IComparable).IsAssignableFrom (tb3), "#I5");
+                       Assert.IsTrue (typeof (IComparable).IsAssignableFrom (tb3), "#I5");
                        Assert.IsFalse (tb3.IsAssignableFrom (typeof (IComparable)), "#I6");
-                       Assert.IsFalse (typeof (IAir).IsAssignableFrom (tb3), "#I7");
+                       Assert.IsTrue (typeof (IAir).IsAssignableFrom (tb3), "#I7");
                        Assert.IsFalse (tb3.IsAssignableFrom (typeof (IAir)), "#I8");
                        Assert.IsTrue (typeof (IWater).IsAssignableFrom (tb3), "#I9");
                        Assert.IsFalse (tb3.IsAssignableFrom (typeof (IWater)), "#I10");
                        //Assert.IsFalse (typeof (ILiquid).IsAssignableFrom (tb3), "#I11");
                        Assert.IsFalse (tb3.IsAssignableFrom (typeof (ILiquid)), "#I12");
 
-                       Assert.IsFalse (typeof (Foo).IsAssignableFrom (tb3), "#J1");
+                       Assert.IsTrue (typeof (Foo).IsAssignableFrom (tb3), "#J1");
                        Assert.IsFalse (tb3.IsAssignableFrom (typeof (Foo)), "#J2");
-                       Assert.IsFalse (typeof (Bar).IsAssignableFrom (tb3), "#J3");
+                       Assert.IsTrue (typeof (Bar).IsAssignableFrom (tb3), "#J3");
                        Assert.IsFalse (tb3.IsAssignableFrom (typeof (Bar)), "#J4");
                        Assert.IsFalse (typeof (Baz).IsAssignableFrom (tb3), "#J5");
                        Assert.IsFalse (tb3.IsAssignableFrom (typeof (Baz)), "#J6");
@@ -9046,7 +9050,7 @@ namespace MonoTests.System.Reflection.Emit
                        Assert.IsFalse (tb3.IsAssignableFrom (typeof (FileStream)), "#K6");
                        Assert.IsTrue (typeof (object).IsAssignableFrom (tb3), "#K7");
                        Assert.IsFalse (tb3.IsAssignableFrom (typeof (object)), "#K8");
-                       Assert.IsFalse (typeof (IDisposable).IsAssignableFrom (tb3), "#K9");
+                       Assert.IsTrue (typeof (IDisposable).IsAssignableFrom (tb3), "#K9");
                        Assert.IsFalse (tb3.IsAssignableFrom (typeof (IDisposable)), "#K10");
 
                        Assert.IsTrue (tb3.IsAssignableFrom (tb3), "#L1");
@@ -9090,6 +9094,8 @@ namespace MonoTests.System.Reflection.Emit
 
 
                [Test]
+               // Casts don't work with unfinished types
+               [Category ("NotWorking")]
                [Category ("NotDotNet")]
                public void IsAssignableFrom_NotCreated_Array ()
                {
@@ -9790,13 +9796,13 @@ namespace MonoTests.System.Reflection.Emit
             TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public, typeof (EmptyIfaceImpl));
                        TypeBuilder tb2 = module.DefineType (genTypeName (), TypeAttributes.Public, tb);
 
-                       Assert.IsFalse (typeof (EmptyInterface).IsAssignableFrom (tb));
+                       Assert.IsTrue (typeof (EmptyInterface).IsAssignableFrom (tb));
                        Type t = tb.CreateType ();
                        Assert.IsTrue (typeof (EmptyInterface).IsAssignableFrom (tb));
                        Assert.IsTrue (typeof (EmptyInterface).IsAssignableFrom (t));
                        
                        
-                       Assert.IsFalse (typeof (EmptyInterface).IsAssignableFrom (tb2));
+                       Assert.IsTrue (typeof (EmptyInterface).IsAssignableFrom (tb2));
                        Type t2 = tb2.CreateType ();
                        Assert.IsTrue (typeof (EmptyInterface).IsAssignableFrom (tb2));
                        Assert.IsTrue (typeof (EmptyInterface).IsAssignableFrom (t2));
@@ -10716,9 +10722,8 @@ namespace MonoTests.System.Reflection.Emit
                                tb.CreateType ();
                        } catch {
                        }
-
+/* this is mono only
                        try {
-                               /* This is mono only */
                                UnmanagedMarshal m = UnmanagedMarshal.DefineCustom (t, "foo", "bar", Guid.Empty);
                                TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public, typeof (object));
                                FieldBuilder fb = tb.DefineField ("Foo", typeof (int), FieldAttributes.Public);
@@ -10726,7 +10731,7 @@ namespace MonoTests.System.Reflection.Emit
                                tb.CreateType ();
                        } catch {
                        }
-
+*/
                        try {
                                /* Properties */
                                TypeBuilder tb = module.DefineType (genTypeName (), TypeAttributes.Public, typeof (object));
@@ -10880,6 +10885,7 @@ namespace MonoTests.System.Reflection.Emit
 
                //Test for #572660
         [Test]
+        [Category ("MobileNotWorking")] // Mono.CompilerServices.SymbolWriter not available in XA
         public void CircularArrayType()
         {
                        var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("Test"), AssemblyBuilderAccess.RunAndSave);
@@ -10950,5 +10956,195 @@ namespace MonoTests.System.Reflection.Emit
                                //OK
                        }
                }
+
+               [Test]
+               public void TypeWithFieldRVAWorksUnderSgen () {
+               AssemblyName an = new AssemblyName("MAIN");
+               AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly(an,
+                   AssemblyBuilderAccess.Run, ".");
+               ModuleBuilder mob = ab.DefineDynamicModule("MAIN");
+               TypeBuilder tb = mob.DefineType("MAIN", TypeAttributes.Public |
+                   TypeAttributes.Sealed | TypeAttributes.Abstract |
+                   TypeAttributes.Class | TypeAttributes.BeforeFieldInit);
+
+               byte[] source = new byte[] { 42 };
+               FieldBuilder fb = tb.DefineInitializedData("A0", source, 0);
+
+               MethodBuilder mb = tb.DefineMethod("EVAL", MethodAttributes.Static |
+                   MethodAttributes.Public, typeof(byte[]), new Type[] { });
+               ILGenerator il = mb.GetILGenerator();
+
+               il.Emit(OpCodes.Ldc_I4_1);
+               il.Emit(OpCodes.Newarr, typeof(byte));
+               il.Emit(OpCodes.Dup);
+               il.Emit(OpCodes.Ldtoken, fb);
+               il.Emit(OpCodes.Call, typeof(RuntimeHelpers).GetMethod("InitializeArray"));
+               il.Emit(OpCodes.Ret);
+
+               Type t = tb.CreateType();
+
+               GC.Collect();
+
+               byte[] res = (byte[]) t.InvokeMember("EVAL", BindingFlags.Public |
+                   BindingFlags.Static | BindingFlags.InvokeMethod, null, null,
+                   new object[] { });
+
+               Assert.AreEqual (42, res[0]);
+           }
+
+
+               [Test]
+               public void Ldfld_Regress_9531 () {
+                       Build<Example<int>> ();
+               }
+
+               void Build<T> () {
+            var base_class = typeof(T);
+
+            var builder = module.DefineType(genTypeName (),
+                TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Public,
+                base_class);
+
+            var field = builder.BaseType.GetField("Field", BindingFlags.Instance | BindingFlags.Public);
+            
+            var cb = builder.DefineConstructor(
+                MethodAttributes.Public | MethodAttributes.SpecialName,
+                CallingConventions.HasThis,
+                new[] { typeof(string) });
+            
+            var il = cb.GetILGenerator();
+            
+            if (field == null)
+            {
+                throw new InvalidOperationException("wtf");
+            }
+            
+            il.Emit(OpCodes.Ldarg_0);
+            il.Emit(OpCodes.Ldarg_1);
+            il.Emit(OpCodes.Stfld, field);
+            il.Emit(OpCodes.Ret);
+            
+            builder.CreateType();
+               }
+
+               public class Example<T> {
+                       public string Field;
+                       public T Field2;
+               }
+
+               [Test]
+               [Category ("AndroidNotWorking")]
+               // It's not possible to save the assembly in the current directory on Android and AssemblyBuilder.DefineDynamicModule will not
+               // allow a full path to the assembly to be passed to it. Trying to change the current directory before saving will not work either as
+               // FileStream will then prepend / to the file name (perhaps it's another bug) and write access to the filesystem root is, obviously, denied
+               public void Ldfld_Encoding_10122 () {
+                       Build2<Example<int>> ();
+               }
+
+               void Build2<T> () {
+                       var base_class = typeof(T);
+
+               string AssemblyName = genTypeName ();
+               string AssemblyFileName = AssemblyName + ".dll";
+
+                       var assemblyBuilderAccess = AssemblyBuilderAccess.Save;
+                       var assemblyName = new AssemblyName(AssemblyName);
+                       var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, assemblyBuilderAccess);
+                       var moduleBuilder = assemblyBuilder.DefineDynamicModule(AssemblyName, AssemblyFileName);
+
+
+                       var builder = moduleBuilder.DefineType("Wrapped",
+                TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Public,
+                base_class);
+
+            var field = builder.BaseType.GetField("Field", BindingFlags.Instance | BindingFlags.Public);
+            
+            var cb = builder.DefineConstructor(
+                MethodAttributes.Public | MethodAttributes.SpecialName,
+                CallingConventions.HasThis,
+                new[] { typeof(string) });
+            
+            var il = cb.GetILGenerator();
+            
+            if (field == null)
+            {
+                throw new InvalidOperationException("wtf");
+            }
+            
+            il.Emit(OpCodes.Ldarg_0);
+            il.Emit(OpCodes.Ldarg_1);
+            il.Emit(OpCodes.Stfld, field);
+            il.Emit(OpCodes.Ret);
+            
+            builder.CreateType();
+
+                       assemblyBuilder.Save (AssemblyFileName);
+
+                       var fromDisk = Assembly.Load (AssemblyName);
+                       Console.WriteLine (fromDisk);
+                       var t = fromDisk.GetType ("Wrapped");
+                       Activator.CreateInstance (t, new object[] { "string"});
+               }
+
+               public interface IFace16096 {
+                       object Bar ();
+               }
+
+               [Test]
+               public void MemberRef_Caching_16096 () {
+                       var outer_class = module.DefineType(
+                               "container",
+                               TypeAttributes.Class | TypeAttributes.Public,
+                               typeof(object));
+
+                       var builder = outer_class.DefineNestedType(
+                               "bind@32-1",
+                               TypeAttributes.Class | TypeAttributes.Public,
+                               typeof(object));
+
+                       builder.AddInterfaceImplementation (typeof (IFace16096));
+
+                       var ctor = builder.DefineDefaultConstructor (MethodAttributes.Public);
+                       var field = builder.DefineField ("Field", typeof (object), FieldAttributes.Public);
+                       var g_args = builder.DefineGenericParameters("b","a");
+                       var method = builder.DefineMethod ("Bar", MethodAttributes.Public | MethodAttributes.Virtual, typeof (object), new Type [0]);
+
+                       var il = method.GetILGenerator();
+                       il.Emit (OpCodes.Ldarg_0);
+                       il.Emit (OpCodes.Ldfld, TypeBuilder.GetField (builder.MakeGenericType (g_args), field));
+                       il.Emit (OpCodes.Pop);
+                       il.Emit (OpCodes.Newobj, TypeBuilder.GetConstructor (builder.MakeGenericType (g_args), ctor));
+                       il.Emit (OpCodes.Ret);
+
+                       var type = builder.CreateType ();
+
+                       /*Build a gshared instance. */
+                       var ginst = type.MakeGenericType (typeof (List<char>), typeof (object));
+                       var ins = (IFace16096)Activator.CreateInstance (ginst);
+
+                       /* This will trigger the runtime to cache the MEMBER_REF to the .ctor as it won't have a context. */
+                       var ins2 = ins.Bar ();
+                       Assert.IsNotNull (ins2);
+
+                       /* Build an unsharable version. */
+                       var ginst2 = type.MakeGenericType (typeof (List<char>), typeof (char));
+                       var ins3 = (IFace16096)Activator.CreateInstance (ginst2);
+
+                       /* This will trigger the runtime to use the cached version, which is wrong as it's an open type. */
+                       var ins4 = ins3.Bar ();
+                       Assert.IsNotNull (ins4);
+               }
+
+               // #22059
+               [Test]
+               [ExpectedException (typeof (TypeLoadException))]
+               public void PrivateIface ()
+               {
+                       TypeBuilder tb = module.DefineType ("Sample", TypeAttributes.Public, typeof (object), new[] { typeof (IFoo) });
+            tb.CreateType();
+               }
+
+               interface IFoo {
+               }
        }
 }