Merge pull request #5560 from kumpera/wasm-work-p3
[mono.git] / mcs / class / corlib / Test / System / TypeTest.cs
index 1f408618bee270e7bb5c65ea1ace8861b925449e..72c2cb41923870747b317d5a06907fe1da14446c 100644 (file)
@@ -16,7 +16,7 @@ using System.Collections;
 using System.Collections.Generic;
 using System.IO;
 using System.Reflection;
-#if !MONOTOUCH && !MOBILE_STATIC
+#if !MONOTOUCH && !FULL_AOT_RUNTIME
 using System.Reflection.Emit;
 #endif
 using System.Runtime.InteropServices;
@@ -261,7 +261,7 @@ namespace MonoTests.System
        [TestFixture]
        public class TypeTest
        {
-#if !MONOTOUCH && !MOBILE_STATIC
+#if !MONOTOUCH && !FULL_AOT_RUNTIME
                private ModuleBuilder module;
 #endif
                const string ASSEMBLY_NAME = "MonoTests.System.TypeTest";
@@ -273,7 +273,7 @@ namespace MonoTests.System
                {
                        AssemblyName assemblyName = new AssemblyName ();
                        assemblyName.Name = ASSEMBLY_NAME;
-#if !MONOTOUCH && !MOBILE_STATIC
+#if !MONOTOUCH && !FULL_AOT_RUNTIME
                        var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly (
                                        assemblyName, AssemblyBuilderAccess.RunAndSave, Path.GetTempPath ());
                        module = assembly.DefineDynamicModule ("module1");
@@ -296,6 +296,14 @@ namespace MonoTests.System
                {
                }
 
+               private void GenericMethod2<A, B, C, D> ()
+                       where C : Duper
+                       where A : B, IFace
+                       where B : C
+                       where D : Baz<object>
+               {
+               }
+
                public class Nested
                {
 
@@ -369,6 +377,54 @@ namespace MonoTests.System
                        // Tests for parameters with generic constraints
                        mi = typeof (TypeTest).GetMethod ("GenericMethod", BindingFlags.Instance|BindingFlags.NonPublic);
                        Assert.IsTrue (typeof (IFace).IsAssignableFrom (mi.GetParameters ()[1].ParameterType));
+
+                       // Transitivity of IsAssignableFrom for type parameters
+                       mi = typeof (TypeTest).GetMethod ("GenericMethod2", BindingFlags.Instance|BindingFlags.NonPublic);
+                       var gparams = mi.GetGenericArguments ();
+                       // B : Duper since B : C and C : Duper
+                       Assert.IsTrue (typeof (Duper).IsAssignableFrom (gparams[1]), "#36");
+                       // A : Duper since A : B and B : Duper
+                       Assert.IsTrue (typeof (Duper).IsAssignableFrom (gparams[0]), "#37a");
+                       // A : IFace since A : IFace
+                       Assert.IsTrue (typeof (IFace).IsAssignableFrom (gparams[0]), "#37b");
+                       // B : Super since B : Duper and Duper : Super
+                       Assert.IsTrue (typeof (Super).IsAssignableFrom (gparams[1]), "#38");
+                       // A : Super since A : B and B : Super
+                       Assert.IsTrue (typeof (Super).IsAssignableFrom (gparams[0]), "#39");
+                       // D : IBar<object> since D : Baz<object> and Baz<object> : IBar<object>
+                       Assert.IsTrue (typeof (IBar<object>).IsAssignableFrom (gparams [3]), "#40");
+                       // A not assignable from B since A : B
+                       Assert.IsFalse (gparams[0].IsAssignableFrom (gparams [1]), "#41");
+                       Assert.IsFalse (gparams[0].IsAssignableFrom (gparams [2]), "#42");
+
+                       // A is not assignable from Array and Delegate and vice versa
+                       Assert.IsFalse (gparams[0].IsAssignableFrom (typeof (Array)), "#43");
+                       Assert.IsFalse (gparams[0].IsAssignableFrom (typeof (Delegate)), "#44");
+                       Assert.IsFalse (typeof (Array).IsAssignableFrom (gparams[0]), "#45");
+                       Assert.IsFalse (typeof (Delegate).IsAssignableFrom (gparams[0]), "#46");
+
+               }
+
+               [Test]
+               public void GenericParameterBaseType ()
+               {
+                       var mi = typeof (TypeTest).GetMethod ("GenericMethod2", BindingFlags.Instance|BindingFlags.NonPublic);
+                       var gparams = mi.GetGenericArguments ();
+
+                       // From the .NET documentation: BaseType property of a
+                       // gparam is "object" if its only constraints are other
+                       // gparams or interfaces, otherwise if it has a class
+                       // constraint that class is the BaseType.
+
+                       // A : B where B is a gparam, and A : IFace which is an
+                       // interface, so A.BaseType is object
+                       Assert.AreEqual (typeof (object), gparams[0].BaseType, "#1");
+                       // B : C where C is a gparam, so B.BaseType is object
+                       Assert.AreEqual (typeof (object), gparams[1].BaseType, "#2");
+                       // C : Duper where Duper is a class, so A.BaseType is Duper
+                       Assert.AreEqual (typeof (Duper), gparams[2].BaseType, "#3");
+                       // D : Baz<object>
+                       Assert.AreEqual (typeof (Baz<object>), gparams[3].BaseType, "#4");
                }
 
                [Test]
@@ -2261,11 +2317,14 @@ namespace MonoTests.System
 
                [Test]
                public void GetGenericMethodDefinitionOverInflatedMethodOnGTD () {
+                       var s = new List<int> () { 1, 2, 3 }.ConvertAll ( i => i.ToString () );
+                       Assert.AreEqual (3, s.Count);
                        var l = typeof (List<>);
                        var m = l.GetMethod ("ConvertAll");
                        var infl = m.MakeGenericMethod (typeof (int));
                        var res = m.GetGenericMethodDefinition ();
                        Assert.AreEqual (m, res, "#1");
+                       Assert.AreEqual (1, infl.GetGenericArguments().Length, "#2");
                }
 
                [Test]
@@ -3058,9 +3117,23 @@ namespace MonoTests.System
                public void MakeArrayTypeTest ()
                {
                        // This should not crash:
-                       typeof (void).MakeArrayType ();
+                       Type t = typeof (void).MakeArrayType ();
                }
                
+               [Test]
+               [ExpectedException (typeof (InvalidProgramException))]
+               public void MakeArrayTypedReferenceInstanceTest ()
+               {
+                       object o = Array.CreateInstance (typeof (global::System.TypedReference), 1);
+               }
+
+               [Test]
+               public void MakeArrayTypeLargeRank ()
+               {
+                       Assert.Throws<TypeLoadException> (delegate () {
+                                       typeof (int).MakeArrayType (33);
+                               });
+               }
 
                [ComVisible (true)]
                public class ComFoo<T> {
@@ -3151,7 +3224,7 @@ namespace MonoTests.System
                }
 
                [Test]
-#if MONOTOUCH || MOBILE_STATIC
+#if MONOTOUCH || FULL_AOT_RUNTIME
                [ExpectedException (typeof (NotSupportedException))]
 #endif
                public void MakeGenericType_UserDefinedType ()
@@ -3168,7 +3241,7 @@ namespace MonoTests.System
                }
 
                [Test]
-#if MONOTOUCH || MOBILE_STATIC
+#if MONOTOUCH || FULL_AOT_RUNTIME
                [ExpectedException (typeof (NotSupportedException))]
 #endif
                public void MakeGenericType_NestedUserDefinedType ()
@@ -3185,7 +3258,7 @@ namespace MonoTests.System
                }
                
                [Test]
-#if MONOTOUCH || MOBILE_STATIC
+#if MONOTOUCH || FULL_AOT_RUNTIME
                [ExpectedException (typeof (NotSupportedException))]
 #endif
                public void TestMakeGenericType_UserDefinedType_DotNet20SP1 () 
@@ -3198,7 +3271,7 @@ namespace MonoTests.System
                }
                
                [Test]
-#if MONOTOUCH || MOBILE_STATIC
+#if MONOTOUCH || FULL_AOT_RUNTIME
                [ExpectedException (typeof (NotSupportedException))]
 #endif
                public void MakeGenericType_BadUserType ()
@@ -3257,6 +3330,38 @@ namespace MonoTests.System
                        Assert.AreSame (expectedType, r, "#2");
                }
 
+               public class BConstrained<Y> where Y : BConstrained<Y> {
+               }
+
+               public class AConstrained<X> : BConstrained<AConstrained<X>> {
+               }
+
+               [Test] // Bug https://bugzilla.xamarin.com/show_bug.cgi?id=54485
+               public void MakeGenericType_GTD_Constraint ()
+               {
+                       // This is pretty weird, but match .NET behavior (note
+                       // that typeof(BConstrained<AConstrained<>>) is a
+                       // compile-time error with roslyn, but it's apparently
+                       // an ok thing to make with reflection.
+                       var tb = typeof (BConstrained<>);
+                       var ta = typeof (AConstrained<>);
+                       var result = tb.MakeGenericType (ta);
+                       Assert.IsNotNull (result, "#1");
+                       // lock down the answer to match what .NET makes
+                       Assert.IsTrue (result.IsGenericType, "#2");
+                       Assert.AreEqual (tb, result.GetGenericTypeDefinition (), "#3");
+                       var bargs = result.GetGenericArguments ();
+                       Assert.AreEqual (1, bargs.Length, "#4");
+                       var arg = bargs [0];
+                       Assert.IsTrue (arg.IsGenericType, "#5");
+                       // N.B. evidently AConstrained`1 and AConstrained`1<!0> are the same type
+                       Assert.IsTrue (arg.IsGenericTypeDefinition, "#6");
+                       Assert.AreEqual (ta, arg.GetGenericTypeDefinition (), "#7");
+                       var aargs = arg.GetGenericArguments ();
+                       Assert.AreEqual (1, aargs.Length, "#8");
+                       Assert.AreEqual (ta.GetGenericArguments () [0], aargs [0], "#9");
+               }
+
        [Test]
        public void EqualsUserType () {
                UserType2 t1 = new UserType2(null);
@@ -3334,7 +3439,7 @@ namespace MonoTests.System
                        Assert.AreEqual (t1, t2);
                }
 
-#if !MONOTOUCH && !MOBILE_STATIC
+#if !MONOTOUCH && !FULL_AOT_RUNTIME
                [Test]
                public void SpaceAfterComma () {
                        string strType = "System.Collections.Generic.Dictionary`2[[System.Int32,mscorlib], [System.String,mscorlib]],mscorlib";
@@ -3342,7 +3447,7 @@ namespace MonoTests.System
                }
 #endif
 
-#if !MONOTOUCH && !MOBILE_STATIC
+#if !MONOTOUCH && !FULL_AOT_RUNTIME
                [Test]
                public void Bug506757 ()
                {
@@ -3570,6 +3675,38 @@ namespace MonoTests.System
                        public int field;
                }
 
+               [Test]
+               public void IsAssignableFromGenericArgumentsWithConstraints ()
+               {
+                       // Regression test for #58809
+
+                       // Generic Parameters of a gtd should have their
+                       // constraints respected even when those constraints
+                       // are other generic parameters themselves.
+
+                       var ps = typeof (GenericWithParamConstraints<,,>).GetGenericArguments ();
+
+                       var a = ps[0];
+                       var b = ps[1];
+                       var c = ps[2];
+
+                       // Foo<C>
+                       var fooOfC = typeof (Foo<>).MakeGenericType (c);
+
+                       // constraint B : Foo <C>
+                       Assert.IsTrue (fooOfC.IsAssignableFrom (b), "#1");
+
+                       // constraint A : B
+                       Assert.IsTrue (b.IsAssignableFrom (a), "#2");
+
+                       // A : Foo<C> since A : B and B : Foo<C>
+                       Assert.IsTrue (fooOfC.IsAssignableFrom (a), "#3");
+               }
+
+               class GenericWithParamConstraints<A, B, C> where B : Foo<C> where A : B
+               {
+               }
+
                [Test] // Bug #612780
                public void CannotMakeDerivedTypesFromTypedByRef ()
                {
@@ -4191,6 +4328,17 @@ namespace MonoTests.System
                        MustTLE (string.Format ("{0}ZZZZ,{1}", typeof (MyRealEnum).FullName, aqn));
                }
 
+               [Test]
+               public void GetTypeExceptionMsg () {
+                       string typeName = "system.int32, foo";
+                       try {
+                               Type.GetType(typeName, true, false);
+                       } catch (TypeLoadException ex) {
+                               Assert.IsTrue (ex.Message.Contains ("system.int32"));
+                               Assert.IsTrue (ex.Message.Contains ("foo"));
+                       }
+               }
+
                delegate void MyAction<in T>(T ag);
 
                [Test] //bug #668506
@@ -4272,7 +4420,7 @@ namespace MonoTests.System
 
                }
 
-#if !MONOTOUCH && !MOBILE_STATIC
+#if !MONOTOUCH && !FULL_AOT_RUNTIME && !MONOMAC
                [Test]
                [Category ("AndroidNotWorking")] // requires symbol writer
                public void FullNameGetTypeParseEscapeRoundtrip () // bug #26384
@@ -4280,7 +4428,7 @@ namespace MonoTests.System
                        var nm = new AssemblyName ("asm");
                        var ab = AssemblyBuilder.DefineDynamicAssembly (nm,
                                                                        AssemblyBuilderAccess.Run);
-                       var mb = ab.DefineDynamicModule("m", true);
+                       var mb = ab.DefineDynamicModule("m", false);
                        var tb = mb.DefineType ("NameSpace,+*&[]\\.Type,+*&[]\\",
                                                TypeAttributes.Class | TypeAttributes.Public);
 
@@ -4318,6 +4466,24 @@ namespace MonoTests.System
                }
 #endif
 
+
+               [Test]
+               public void GetTypeBadArity()
+               {
+                       // Regression test for #46250
+                       try {
+                               Type.GetType ("System.Collections.Generic.Dictionary`2[System.String]", true);
+                               Assert.Fail ("Did not throw an exception (#1)");
+                       } catch (ArgumentException) {
+                       }
+
+                       try {
+                               Type.GetType ("System.Collections.Generic.Dictionary`2[System.String,System.Int32,System.Int64]", true);
+                               Assert.Fail ("Did not throw an exception (#2)");
+                       } catch (ArgumentException) {
+                       }
+               }
+
                public abstract class Stream : IDisposable
                {
                        public void Dispose ()