[test] Add gparam Type.IsAssignableFrom and Type.BaseType tests
authorAleksey Kliger <aleksey@xamarin.com>
Tue, 26 Sep 2017 17:01:43 +0000 (13:01 -0400)
committerAleksey Kliger (λgeek) <akliger@gmail.com>
Tue, 26 Sep 2017 19:59:46 +0000 (15:59 -0400)
Lock down .NET Framework documented behavior

mcs/class/corlib/Test/System/TypeTest.cs

index 3fe3c3e61b41b109e4b5f0f554618262a36ee7cd..72c2cb41923870747b317d5a06907fe1da14446c 100644 (file)
@@ -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]