1 // 2 // System.Reflection.MethodInfo Test Cases 3 // 4 // Authors: 5 // Zoltan Varga (vargaz@gmail.com) 6 // Aleksey Kliger (aleksey@xamarin.com) 7 // 8 // (c) 2003 Ximian, Inc. (http://www.ximian.com) 9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com) 10 // Copyright (C) 2015 Xamarin, Inc. (http://www.xamarin.com) 11 // 12 // Permission is hereby granted, free of charge, to any person obtaining 13 // a copy of this software and associated documentation files (the 14 // "Software"), to deal in the Software without restriction, including 15 // without limitation the rights to use, copy, modify, merge, publish, 16 // distribute, sublicense, and/or sell copies of the Software, and to 17 // permit persons to whom the Software is furnished to do so, subject to 18 // the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be 21 // included in all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 // 31 32 using NUnit.Framework; 33 using System; 34 using System.Threading; 35 using System.Reflection; 36 #if !MONOTOUCH && !FULL_AOT_RUNTIME 37 using System.Reflection.Emit; 38 #endif 39 using System.Runtime.InteropServices; 40 using System.Runtime.CompilerServices; 41 42 using System.Collections.Generic; 43 44 namespace A.B.C { 45 // Disable expected warning 46 #pragma warning disable 169 47 public struct MethodInfoTestStruct { 48 int p; 49 } 50 #pragma warning restore 169 51 } 52 namespace MonoTests.System.Reflection 53 { 54 [TestFixture] 55 public class MethodInfoTest 56 { 57 #if MONOTOUCH || FULL_AOT_RUNTIME 58 // use an existing symbol - so we can build without dlsym. It does not matter that the signature does not match for the test 59 [DllImport ("libc", EntryPoint="readlink", CharSet=CharSet.Unicode, ExactSpelling=false, PreserveSig=true, SetLastError=true, BestFitMapping=true, ThrowOnUnmappableChar=true)] 60 #else 61 [DllImport ("libfoo", EntryPoint="foo", CharSet=CharSet.Unicode, ExactSpelling=false, PreserveSig=true, SetLastError=true, BestFitMapping=true, ThrowOnUnmappableChar=true)] 62 #endif dllImportMethod()63 public static extern void dllImportMethod (); 64 [MethodImplAttribute(MethodImplOptions.PreserveSig)] preserveSigMethod()65 public void preserveSigMethod () 66 { 67 } 68 69 [MethodImplAttribute(MethodImplOptions.Synchronized)] synchronizedMethod()70 public void synchronizedMethod () 71 { 72 } 73 74 public interface InterfaceTest 75 { Clone()76 void Clone (); 77 } 78 79 [Test] IsDefined_AttributeType_Null()80 public void IsDefined_AttributeType_Null () 81 { 82 MethodInfo mi = typeof (MethodInfoTest).GetMethod ("foo"); 83 84 try { 85 mi.IsDefined ((Type) null, false); 86 Assert.Fail ("#1"); 87 } catch (ArgumentNullException ex) { 88 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2"); 89 Assert.IsNull (ex.InnerException, "#3"); 90 Assert.IsNotNull (ex.Message, "#4"); 91 Assert.IsNotNull (ex.ParamName, "#5"); 92 Assert.AreEqual ("attributeType", ex.ParamName, "#6"); 93 } 94 } 95 96 [Test] TestInvokeByRefReturnMethod()97 public void TestInvokeByRefReturnMethod () 98 { 99 try { 100 MethodInfo m = typeof (int[]).GetMethod ("Address"); 101 m.Invoke (new int[1], new object[] { 0 }); 102 Assert.Fail ("#1"); 103 } catch (NotSupportedException e) { 104 Assert.AreEqual (typeof (NotSupportedException), e.GetType (), "#2"); 105 Assert.IsNull (e.InnerException, "#3"); 106 Assert.IsNotNull (e.Message, "#4"); 107 } 108 } 109 110 [Test] PseudoCustomAttributes()111 public void PseudoCustomAttributes () 112 { 113 Type t = typeof (MethodInfoTest); 114 115 DllImportAttribute attr = (DllImportAttribute)((t.GetMethod ("dllImportMethod").GetCustomAttributes (typeof (DllImportAttribute), true)) [0]); 116 117 Assert.AreEqual (CallingConvention.Winapi, attr.CallingConvention, "#1"); 118 #if MONOTOUCH || FULL_AOT_RUNTIME 119 Assert.AreEqual ("readlink", attr.EntryPoint, "#2"); 120 Assert.AreEqual ("libc", attr.Value, "#3"); 121 #else 122 Assert.AreEqual ("foo", attr.EntryPoint, "#2"); 123 Assert.AreEqual ("libfoo", attr.Value, "#3"); 124 #endif 125 Assert.AreEqual (CharSet.Unicode, attr.CharSet, "#4"); 126 Assert.AreEqual (false, attr.ExactSpelling, "#5"); 127 Assert.AreEqual (true, attr.PreserveSig, "#6"); 128 Assert.AreEqual (true, attr.SetLastError, "#7"); 129 Assert.AreEqual (true, attr.BestFitMapping, "#8"); 130 Assert.AreEqual (true, attr.ThrowOnUnmappableChar, "#9"); 131 132 PreserveSigAttribute attr2 = (PreserveSigAttribute)((t.GetMethod ("preserveSigMethod").GetCustomAttributes (true)) [0]); 133 134 // This doesn't work under MS.NET 135 /* 136 MethodImplAttribute attr3 = (MethodImplAttribute)((t.GetMethod ("synchronizedMethod").GetCustomAttributes (true)) [0]); 137 */ 138 } 139 140 [return: MarshalAs (UnmanagedType.Interface)] ReturnTypeMarshalAs()141 public void ReturnTypeMarshalAs () 142 { 143 } 144 145 [Test] ReturnTypePseudoCustomAttributes()146 public void ReturnTypePseudoCustomAttributes () 147 { 148 MethodInfo mi = typeof (MethodInfoTest).GetMethod ("ReturnTypeMarshalAs"); 149 150 Assert.IsTrue (mi.ReturnTypeCustomAttributes.GetCustomAttributes (typeof (MarshalAsAttribute), true).Length == 1); 151 } 152 foo(int i, int j)153 public static int foo (int i, int j) 154 { 155 return i + j; 156 } 157 158 [Test] StaticInvokeWithObject()159 public void StaticInvokeWithObject () 160 { 161 MethodInfo mi = typeof (MethodInfoTest).GetMethod ("foo"); 162 163 mi.Invoke (new Object (), new object [] { 1, 2 }); 164 } 165 166 [Test] ByRefInvoke()167 public void ByRefInvoke () 168 { 169 MethodInfo met = typeof(MethodInfoTest).GetMethod ("ByRefTest"); 170 object[] parms = new object[] {1}; 171 met.Invoke (null, parms); 172 Assert.AreEqual (2, parms[0]); 173 } 174 ByRefTest(ref int a1)175 public static void ByRefTest (ref int a1) 176 { 177 if (a1 == 1) 178 a1 = 2; 179 } 180 181 static int byref_arg; 182 ByrefVtype(ref int i)183 public static void ByrefVtype (ref int i) { 184 byref_arg = i; 185 i = 5; 186 } 187 188 [Test] ByrefVtypeInvoke()189 public void ByrefVtypeInvoke () 190 { 191 MethodInfo mi = typeof (MethodInfoTest).GetMethod ("ByrefVtype"); 192 193 object o = 1; 194 object[] args = new object [] { o }; 195 mi.Invoke (null, args); 196 Assert.AreEqual (1, byref_arg, "#A1"); 197 Assert.AreEqual (1, o, "#A2"); 198 Assert.AreEqual (5, args[0], "#A3"); 199 200 args [0] = null; 201 mi.Invoke (null, args); 202 Assert.AreEqual (0, byref_arg, "#B1"); 203 Assert.AreEqual (5, args[0], "#B2"); 204 } 205 HeyHey(out string out1, ref DateTime ref1)206 public void HeyHey (out string out1, ref DateTime ref1) 207 { 208 out1 = null; 209 } 210 SignatureTest(__arglist)211 public void SignatureTest (__arglist) 212 { 213 } 214 PtrFunc(int* a)215 public static unsafe int* PtrFunc (int* a) 216 { 217 return (int*) 0; 218 } 219 220 #if MONO_FEATURE_THREAD_ABORT 221 [Test] // bug #81538 InvokeThreadAbort()222 public void InvokeThreadAbort () 223 { 224 MethodInfo method = typeof (MethodInfoTest).GetMethod ("AbortIt"); 225 try { 226 method.Invoke (null, new object [0]); 227 Assert.Fail ("#1"); 228 } 229 catch (ThreadAbortException ex) { 230 Thread.ResetAbort (); 231 Assert.IsNull (ex.InnerException, "#2"); 232 } 233 } 234 AbortIt()235 public static void AbortIt () 236 { 237 Thread.CurrentThread.Abort (); 238 } 239 #endif 240 241 [Test] // bug #76541 ToStringByRef()242 public void ToStringByRef () 243 { 244 Assert.AreEqual ("Void HeyHey(System.String ByRef, System.DateTime ByRef)", 245 this.GetType ().GetMethod ("HeyHey").ToString ()); 246 } 247 248 [Test] ToStringArgList()249 public void ToStringArgList () 250 { 251 Assert.AreEqual ("Void SignatureTest(...)", 252 this.GetType ().GetMethod ("SignatureTest").ToString ()); 253 } 254 255 [Test] ToStringWithPointerSignatures()256 public void ToStringWithPointerSignatures () //bug #409583 257 { 258 Assert.AreEqual ("Int32* PtrFunc(Int32*)", this.GetType ().GetMethod ("PtrFunc").ToString ()); 259 } 260 261 public struct SimpleStruct 262 { 263 public int a; 264 } 265 PtrFunc2(SimpleStruct* a, A.B.C.MethodInfoTestStruct *b)266 public static unsafe SimpleStruct* PtrFunc2 (SimpleStruct* a, A.B.C.MethodInfoTestStruct *b) 267 { 268 return (SimpleStruct*) 0; 269 } 270 271 [Test] ToStringWithPointerSignaturesToNonPrimitiveType()272 public void ToStringWithPointerSignaturesToNonPrimitiveType () 273 { 274 Assert.AreEqual ("SimpleStruct* PtrFunc2(SimpleStruct*, A.B.C.MethodInfoTestStruct*)", 275 this.GetType ().GetMethod ("PtrFunc2").ToString ()); 276 } 277 [Test] ToStringGenericMethod()278 public void ToStringGenericMethod () 279 { 280 Assert.AreEqual ("System.Collections.ObjectModel.ReadOnlyCollection`1[T] AsReadOnly[T](T[])", 281 typeof (Array).GetMethod ("AsReadOnly").ToString ()); 282 } 283 f()284 class GBD_A { public virtual void f () {} } f()285 class GBD_B : GBD_A { public override void f () {} } f()286 class GBD_C : GBD_B { public override void f () {} } f()287 class GBD_D : GBD_C { public new virtual void f () {} } f()288 class GBD_E : GBD_D { public override void f () {} } 289 290 class GBD_E2 : GBD_D { } 291 class GBD_F : GBD_E { } 292 293 294 [Test] GetBaseDefinition()295 public void GetBaseDefinition () 296 { 297 Assert.AreEqual (typeof (GBD_A), typeof (GBD_C).GetMethod ("f").GetBaseDefinition ().DeclaringType); 298 Assert.AreEqual (typeof (GBD_A), typeof (GBD_C).GetMethod ("f").GetBaseDefinition ().ReflectedType, "#1r"); 299 300 Assert.AreEqual (typeof (GBD_D), typeof (GBD_D).GetMethod ("f").GetBaseDefinition ().DeclaringType); 301 Assert.AreEqual (typeof (GBD_D), typeof (GBD_D).GetMethod ("f").GetBaseDefinition ().ReflectedType, "#2r"); 302 303 Assert.AreEqual (typeof (GBD_D), typeof (GBD_E).GetMethod ("f").GetBaseDefinition ().DeclaringType); 304 Assert.AreEqual (typeof (GBD_D), typeof (GBD_E).GetMethod ("f").GetBaseDefinition ().ReflectedType, "#3r"); 305 306 Assert.AreEqual (typeof (GBD_D), typeof (GBD_E2).GetMethod ("f").GetBaseDefinition ().DeclaringType, "#4"); 307 Assert.AreEqual (typeof (GBD_D), typeof (GBD_E2).GetMethod ("f").GetBaseDefinition ().ReflectedType, "#4r"); 308 309 Assert.AreEqual (typeof (GBD_D), typeof (GBD_F).GetMethod ("f").GetBaseDefinition ().DeclaringType, "#5"); 310 Assert.AreEqual (typeof (GBD_D), typeof (GBD_F).GetMethod ("f").GetBaseDefinition ().ReflectedType, "#5r"); 311 312 } 313 314 class GenericBase<T,H> { f2()315 public virtual void f2 () { } 316 } 317 318 class GenericMid<T, U> : GenericBase<T, Action<U>> { f1()319 public virtual T f1 () { return default (T); } 320 } 321 322 class GenericChild<T> : GenericMid<T, int> { f1()323 public override T f1 () { return default (T); } f2()324 public override void f2 () { } 325 } 326 327 class DerivedFromGenericBase : GenericBase<int, int> { 328 } 329 330 [Test] GetBaseDefinition_OpenConstructedBaseType()331 public void GetBaseDefinition_OpenConstructedBaseType () // 36305 332 { 333 var t = typeof (GenericChild<string>); 334 335 var mi1 = t.GetMethod ("f1"); 336 var mi1_base = mi1.GetBaseDefinition (); 337 338 Assert.AreEqual (typeof (GenericMid<string, int>), mi1_base.DeclaringType, "#1"); 339 340 var mi2 = t.GetMethod ("f2"); 341 var mi2_base = mi2.GetBaseDefinition (); 342 343 Assert.AreEqual (typeof (GenericBase<string, Action<int>>), mi2_base.DeclaringType, "#2"); 344 } 345 346 class TestInheritedMethodA { TestMethod()347 private void TestMethod () 348 { 349 } 350 TestMethod2()351 public void TestMethod2 () 352 { 353 } 354 } 355 356 class TestInheritedMethodB : TestInheritedMethodA { 357 } 358 359 [Test] InheritanceTestGetMethodTest()360 public void InheritanceTestGetMethodTest () 361 { 362 MethodInfo inheritedMethod = typeof(TestInheritedMethodB).GetMethod("TestMethod", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 363 MethodInfo baseMethod = typeof(TestInheritedMethodB).GetMethod("TestMethod", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 364 Assert.AreSame (inheritedMethod, baseMethod); 365 366 MethodInfo inheritedMethod2 = typeof(TestInheritedMethodB).GetMethod("TestMethod2", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 367 MethodInfo baseMethod2 = typeof(TestInheritedMethodB).GetMethod("TestMethod2", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 368 Assert.AreSame (inheritedMethod, baseMethod); 369 } 370 371 [Test] GetMethodBody_Abstract()372 public void GetMethodBody_Abstract () 373 { 374 MethodBody mb = typeof (InterfaceTest).GetMethod ("Clone").GetMethodBody (); 375 Assert.IsNull (mb); 376 } 377 378 [Test] GetMethodBody_Runtime()379 public void GetMethodBody_Runtime () 380 { 381 MethodBody mb = typeof (AsyncCallback).GetMethod ("Invoke").GetMethodBody (); 382 Assert.IsNull (mb); 383 } 384 385 [Test] GetMethodBody_Pinvoke()386 public void GetMethodBody_Pinvoke () 387 { 388 MethodBody mb = typeof (MethodInfoTest).GetMethod ("dllImportMethod").GetMethodBody (); 389 Assert.IsNull (mb); 390 } 391 392 [Test] GetMethodBody_Icall()393 public void GetMethodBody_Icall () 394 { 395 foreach (MethodInfo mi in typeof (object).GetMethods (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance)) 396 if ((mi.GetMethodImplementationFlags () & MethodImplAttributes.InternalCall) != 0) { 397 MethodBody mb = mi.GetMethodBody (); 398 Assert.IsNull (mb); 399 } 400 } 401 locals_method()402 public static void locals_method () 403 { 404 byte[] b = new byte [10]; 405 406 unsafe { 407 /* This generates a pinned local */ 408 fixed (byte *p = &b [0]) { 409 } 410 } 411 } 412 413 [Test] GetMethodBody()414 public void GetMethodBody () 415 { 416 #if (MONOTOUCH || FULL_AOT_RUNTIME) && !DEBUG 417 Assert.Ignore ("Release app (on devices) are stripped of (managed) IL so this test would fail"); 418 #endif 419 MethodBody mb = typeof (MethodInfoTest).GetMethod ("locals_method").GetMethodBody (); 420 421 Assert.IsTrue (mb.InitLocals, "#1"); 422 Assert.IsTrue (mb.LocalSignatureMetadataToken > 0, "#2"); 423 424 IList<LocalVariableInfo> locals = mb.LocalVariables; 425 426 bool foundPinnedBytePointer = false; 427 unsafe { 428 foreach (LocalVariableInfo lvi in locals) { 429 if (lvi.LocalType == typeof (byte[])) 430 // This is optimized out by CSC in .NET 4.6 431 Assert.IsFalse (lvi.IsPinned, "#3-1"); 432 433 if (/* mcs */ lvi.LocalType == typeof (byte*) || /* csc */ lvi.LocalType == typeof (byte).MakeByRefType ()) { 434 // We have three locals. There's b the byte[], there's a byte* and there's a byte&. 435 // mcs emits a byte* for the latter type. 436 // We need to find one such pinned byte pointer. Therefore we're folding with logical or 437 foundPinnedBytePointer = foundPinnedBytePointer || lvi.IsPinned; 438 } 439 } 440 } 441 Assert.IsTrue (foundPinnedBytePointer, "#4"); 442 } 443 return_parameter_test()444 public int return_parameter_test () 445 { 446 return 0; 447 } 448 449 [Test] GetMethodFromHandle_Generic()450 public void GetMethodFromHandle_Generic () 451 { 452 MethodHandleTest<int> test = new MethodHandleTest<int> (); 453 RuntimeMethodHandle mh = test.GetType ().GetProperty ("MyList") 454 .GetGetMethod ().MethodHandle; 455 MethodBase mb = MethodInfo.GetMethodFromHandle (mh, 456 typeof (MethodHandleTest<int>).TypeHandle); 457 Assert.IsNotNull (mb, "#1"); 458 List<int> list = (List<int>) mb.Invoke (test, null); 459 Assert.IsNotNull (list, "#2"); 460 Assert.AreEqual (1, list.Count, "#3"); 461 } 462 463 [Test] ReturnParameter()464 public void ReturnParameter () 465 { 466 ParameterInfo pi = typeof (MethodInfoTest).GetMethod ("return_parameter_test").ReturnParameter; 467 Assert.AreEqual (typeof (int), pi.ParameterType, "#1"); 468 Assert.AreEqual (-1, pi.Position, "#2"); 469 // MS always return false here 470 //Assert.IsTrue (pi.IsRetval, "#3"); 471 } 472 473 [Test] MethodInfoModule()474 public void MethodInfoModule () 475 { 476 Type type = typeof (MethodInfoTest); 477 MethodInfo me = type.GetMethod ("return_parameter_test"); 478 479 Assert.AreEqual (type.Module, me.Module); 480 } 481 482 [Test] InvokeOnRefOnlyAssembly()483 public void InvokeOnRefOnlyAssembly () 484 { 485 Assembly a = Assembly.ReflectionOnlyLoad (typeof (MethodInfoTest).Assembly.FullName); 486 Type t = a.GetType (typeof (RefOnlyMethodClass).FullName); 487 MethodInfo m = t.GetMethod ("RefOnlyMethod", BindingFlags.Static | BindingFlags.NonPublic); 488 try { 489 m.Invoke (null, new object [0]); 490 Assert.Fail ("#1"); 491 } catch (InvalidOperationException ex) { 492 // The requested operation is invalid in the 493 // ReflectionOnly context 494 Assert.AreEqual (typeof (InvalidOperationException), ex.GetType (), "#2"); 495 Assert.IsNull (ex.InnerException, "#3"); 496 Assert.IsNotNull (ex.Message, "#4"); 497 } 498 } 499 500 [Test] 501 [ExpectedException (typeof (TargetInvocationException))] InvokeInvalidOpExceptionThrow()502 public void InvokeInvalidOpExceptionThrow () { 503 MethodInfo mi = typeof (MethodInfoTest).GetMethod ("ThrowMethod"); 504 mi.Invoke(null, null); 505 } 506 ThrowMethod()507 public static void ThrowMethod () { 508 throw new InvalidOperationException (); 509 } 510 511 [Test] InvokeGenericVtype()512 public void InvokeGenericVtype () 513 { 514 KeyValuePair<string, uint> kvp = new KeyValuePair<string, uint> ("a", 21); 515 Type type = kvp.GetType (); 516 Type [] arguments = type.GetGenericArguments (); 517 MethodInfo method = typeof (MethodInfoTest).GetMethod ("Go"); 518 MethodInfo generic_method = method.MakeGenericMethod (arguments); 519 kvp = (KeyValuePair<string, uint>)generic_method.Invoke (null, new object [] { kvp }); 520 521 Assert.AreEqual ("a", kvp.Key, "#1"); 522 Assert.AreEqual (21, kvp.Value, "#2"); 523 } 524 Go(KeyValuePair <T1, T2> kvp)525 public static KeyValuePair<T1, T2> Go <T1, T2> (KeyValuePair <T1, T2> kvp) 526 { 527 return kvp; 528 } 529 530 [Test] // bug #81997 InvokeGenericInst()531 public void InvokeGenericInst () 532 { 533 List<string> str = null; 534 535 object [] methodArgs = new object [] { str }; 536 MethodInfo mi = typeof (MethodInfoTest).GetMethod ("GenericRefMethod"); 537 mi.Invoke (null, methodArgs); 538 Assert.IsNotNull (methodArgs [0], "#A1"); 539 Assert.IsNull (str, "#A2"); 540 Assert.IsTrue (methodArgs [0] is List<string>, "#A3"); 541 542 List<string> refStr = methodArgs [0] as List<string>; 543 Assert.IsNotNull (refStr, "#B1"); 544 Assert.AreEqual (1, refStr.Count, "#B2"); 545 Assert.AreEqual ("test", refStr [0], "#B3"); 546 } 547 GenericRefMethod(ref List<string> strArg)548 public static void GenericRefMethod (ref List<string> strArg) 549 { 550 strArg = new List<string> (); 551 strArg.Add ("test"); 552 } 553 MakeGenericMethodArgsMismatchFoo()554 public void MakeGenericMethodArgsMismatchFoo<T> () 555 { 556 } 557 558 [Test] MakeGenericMethodArgsMismatch()559 public void MakeGenericMethodArgsMismatch () 560 { 561 MethodInfo gmi = this.GetType ().GetMethod ( 562 "MakeGenericMethodArgsMismatchFoo"); 563 try { 564 gmi.MakeGenericMethod (); 565 Assert.Fail ("#1"); 566 } catch (ArgumentException ex) { 567 // The type or method has 1 generic parameter(s), 568 // but 0 generic argument(s) were provided. A 569 // generic argument must be provided for each 570 // generic parameter 571 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2"); 572 Assert.IsNull (ex.InnerException, "#3"); 573 Assert.IsNotNull (ex.Message, "#4"); 574 Assert.IsNull (ex.ParamName, "#5"); 575 } 576 } 577 SimpleGenericMethod()578 public void SimpleGenericMethod<TFoo, TBar> () {} 579 580 [Test] MakeGenericMethodWithNullArray()581 public void MakeGenericMethodWithNullArray () 582 { 583 MethodInfo gmi = this.GetType ().GetMethod ("SimpleGenericMethod"); 584 try { 585 gmi.MakeGenericMethod ((Type []) null); 586 Assert.Fail ("#1"); 587 } catch (ArgumentNullException ex) { 588 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2"); 589 Assert.IsNull (ex.InnerException, "#3"); 590 Assert.IsNotNull (ex.Message, "#4"); 591 Assert.AreEqual ("methodInstantiation", ex.ParamName, "#5"); 592 } 593 } 594 595 [Test] MakeGenericMethodWithNullValueInTypesArray()596 public void MakeGenericMethodWithNullValueInTypesArray () 597 { 598 MethodInfo gmi = this.GetType ().GetMethod ("SimpleGenericMethod"); 599 try { 600 gmi.MakeGenericMethod (new Type [] { typeof (int), null }); 601 Assert.Fail ("#1"); 602 } catch (ArgumentNullException ex) { 603 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2"); 604 Assert.IsNull (ex.InnerException, "#3"); 605 Assert.IsNotNull (ex.Message, "#4"); 606 Assert.IsNull (ex.ParamName, "#5"); 607 } 608 } 609 610 [Test] MakeGenericMethodWithNonGenericMethodDefinitionMethod()611 public void MakeGenericMethodWithNonGenericMethodDefinitionMethod () 612 { 613 MethodInfo gmi = this.GetType ().GetMethod ("SimpleGenericMethod"); 614 MethodInfo inst = gmi.MakeGenericMethod (typeof (int), typeof (double)); 615 try { 616 inst.MakeGenericMethod (typeof (int), typeof (double)); 617 Assert.Fail ("#1"); 618 } catch (InvalidOperationException ex) { 619 } 620 } 621 #if !MONOTOUCH && !FULL_AOT_RUNTIME SimpleGenericMethod2()622 public TFoo SimpleGenericMethod2<TFoo, TBar> () { return default (TFoo); } 623 /*Test for the uggly broken behavior of SRE.*/ 624 [Test] MakeGenericMethodWithSreTypeResultsInStupidMethodInfo()625 public void MakeGenericMethodWithSreTypeResultsInStupidMethodInfo () 626 { 627 AssemblyName assemblyName = new AssemblyName (); 628 assemblyName.Name = "MonoTests.System.Reflection.Emit.MethodInfoTest"; 629 AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.RunAndSave, "."); 630 ModuleBuilder module = assembly.DefineDynamicModule ("module1", "tst.dll"); 631 TypeBuilder tb = module.DefineType ("Test", TypeAttributes.Public); 632 633 MethodInfo gmi = this.GetType ().GetMethod ("SimpleGenericMethod2"); 634 MethodInfo ins = gmi.MakeGenericMethod (typeof (int), tb); 635 636 Assert.AreSame (tb, ins.GetGenericArguments () [1], "#1"); 637 /*broken ReturnType*/ 638 Assert.AreSame (gmi.GetGenericArguments () [0], ins.ReturnType, "#2"); 639 } 640 #endif pass_nullable(int? i)641 public static int? pass_nullable (int? i) 642 { 643 return i; 644 } 645 646 [Test] NullableTests()647 public void NullableTests () 648 { 649 MethodInfo mi = typeof (MethodInfoTest).GetMethod ("pass_nullable"); 650 Assert.AreEqual (102, mi.Invoke (null, new object [] { 102 }), "#1"); 651 Assert.AreEqual (null, mi.Invoke (null, new object [] { null }), "#2"); 652 653 // Test conversion of vtype to a nullable type for the this argument 654 PropertyInfo pi = typeof (Nullable <int>).GetProperty ("HasValue"); 655 Assert.AreEqual (true, pi.GetGetMethod ().Invoke (10, null)); 656 PropertyInfo pi2 = typeof (Nullable <int>).GetProperty ("Value"); 657 Assert.AreEqual (10, pi2.GetGetMethod ().Invoke (10, null)); 658 } 659 foo_generic()660 public static void foo_generic<T> () 661 { 662 } 663 664 [Test] IsGenericMethod()665 public void IsGenericMethod () 666 { 667 MethodInfo mi = typeof (MethodInfoTest).GetMethod ("foo_generic"); 668 Assert.AreEqual (true, mi.IsGenericMethod, "#1"); 669 MethodInfo mi2 = mi.MakeGenericMethod (new Type[] { typeof (int) }); 670 Assert.AreEqual (true, mi2.IsGenericMethod, "#2"); 671 MethodInfo mi3 = typeof (GenericHelper<int>).GetMethod ("Test"); 672 Assert.AreEqual (false, mi3.IsGenericMethod, "#3"); 673 } 674 675 class A<T> 676 { Foo(T2 i)677 public static void Foo<T2> (T2 i) 678 { 679 } 680 Bar()681 public static void Bar () 682 { 683 } 684 685 public class B 686 { Baz()687 public static void Baz () 688 { 689 } 690 } 691 } 692 693 [Test] ContainsGenericParameters()694 public void ContainsGenericParameters () 695 { 696 // Non-generic method in open generic type 697 Assert.IsTrue (typeof (A<int>).GetGenericTypeDefinition ().GetMethod ("Bar").ContainsGenericParameters); 698 // open generic method in closed generic type 699 Assert.IsTrue (typeof (A<int>).GetMethod ("Foo").ContainsGenericParameters); 700 // non-generic method in closed generic type 701 Assert.IsFalse (typeof (A<int>).GetMethod ("Bar").ContainsGenericParameters); 702 // closed generic method in closed generic type 703 Assert.IsFalse (typeof (A<int>).GetMethod ("Foo").MakeGenericMethod (new Type [] { typeof (int) }).ContainsGenericParameters); 704 // non-generic method in non-generic nested type of closed generic type 705 Assert.IsFalse (typeof (A<int>.B).GetMethod ("Baz").ContainsGenericParameters); 706 // non-generic method in non-generic nested type of open generic type 707 Assert.IsTrue (typeof (A<int>.B).GetGenericTypeDefinition ().GetMethod ("Baz").ContainsGenericParameters); 708 } 709 710 [Test] IsGenericMethodDefinition()711 public void IsGenericMethodDefinition () 712 { 713 MethodInfo m1 = typeof (A<>).GetMethod ("Foo"); 714 Assert.IsTrue (m1.IsGenericMethod, "#A1"); 715 Assert.IsTrue (m1.IsGenericMethodDefinition, "#A2"); 716 717 MethodInfo m2 = typeof (A<int>).GetMethod ("Foo"); 718 Assert.IsTrue (m2.IsGenericMethod, "#B1"); 719 Assert.IsTrue (m2.IsGenericMethodDefinition, "#B2"); 720 721 MethodInfo m3 = m2.MakeGenericMethod (typeof (int)); 722 Assert.IsTrue (m3.IsGenericMethod, "#C1"); 723 Assert.IsFalse (m3.IsGenericMethodDefinition, "#C2"); 724 } 725 726 [Test] GetGenericMethodDefinition()727 public void GetGenericMethodDefinition () 728 { 729 MethodInfo mi1 = typeof (MyList<>).GetMethod ("ConvertAll"); 730 MethodInfo mi2 = typeof (MyList<int>).GetMethod ("ConvertAll"); 731 732 Assert.AreEqual ("MonoTests.System.Reflection.MethodInfoTest+Foo`2[T,TOutput]", 733 mi1.GetParameters () [0].ParameterType.ToString (), "#A1"); 734 Assert.AreEqual ("MonoTests.System.Reflection.MethodInfoTest+Foo`2[System.Int32,TOutput]", 735 mi2.GetParameters () [0].ParameterType.ToString (), "#A2"); 736 Assert.IsTrue (mi1.IsGenericMethod, "#A3"); 737 Assert.IsTrue (mi1.IsGenericMethodDefinition, "#A4"); 738 Assert.IsTrue (mi2.IsGenericMethod, "#A5"); 739 Assert.IsTrue (mi2.IsGenericMethodDefinition, "#A6"); 740 741 MethodInfo mi3 = mi2.GetGenericMethodDefinition (); 742 743 Assert.IsTrue (mi3.IsGenericMethod, "#B1"); 744 Assert.IsTrue (mi3.IsGenericMethodDefinition, "#B2"); 745 Assert.AreSame (mi2, mi3, "#B3"); 746 747 MethodInfo mi4 = mi2.MakeGenericMethod (typeof (short)); 748 Assert.IsTrue (mi4.IsGenericMethod, "#C1"); 749 Assert.IsFalse (mi4.IsGenericMethodDefinition, "#C2"); 750 Assert.AreSame (mi2, mi4.GetGenericMethodDefinition (), "#C3"); 751 } 752 TestMethod123(int a, int b)753 public void TestMethod123(int a, int b) {} 754 755 [Test] GetParametersDontReturnInternedArray()756 public void GetParametersDontReturnInternedArray () 757 { 758 var method = typeof (MethodInfoTest).GetMethod ("TestMethod123"); 759 var parms = method.GetParameters (); 760 Assert.AreNotSame (parms, method.GetParameters (), "#1"); 761 762 parms [0] = null; 763 Assert.IsNotNull (method.GetParameters () [0], "#2"); 764 } 765 766 [Test] Bug354757()767 public void Bug354757 () 768 { 769 MethodInfo gmd = (typeof (MyList <int>)).GetMethod ("ConvertAll"); 770 MethodInfo oi = gmd.MakeGenericMethod (gmd.GetGenericArguments ()); 771 Assert.AreSame (gmd, oi); 772 } 773 774 [Test] 775 [ExpectedException (typeof (ArgumentException))] 776 #if MOBILE 777 [Category ("NotWorking")] // #10552 778 #endif MakeGenericMethodRespectConstraints()779 public void MakeGenericMethodRespectConstraints () 780 { 781 var m = typeof (MethodInfoTest).GetMethod ("TestMethod"); 782 m.MakeGenericMethod (typeof (Type)); 783 } 784 785 public void TestMethod <T> () where T : Exception 786 { 787 } 788 789 public class MyList<T> 790 { ConvertAll(Foo<T,TOutput> arg)791 public TOutput ConvertAll<TOutput> (Foo<T,TOutput> arg) 792 { 793 return default (TOutput); 794 } ConvertAll2(MyList<T> arg)795 public T ConvertAll2 (MyList<T> arg) 796 { 797 return default (T); 798 } 799 } 800 801 public class Foo<T,TOutput> 802 { 803 } 804 805 class GenericHelper<T> 806 { Test(T t)807 public void Test (T t) 808 { 809 } 810 } 811 interface IMethodInvoke<out T> 812 { Test()813 T Test (); 814 } 815 816 class MethodInvoke : IMethodInvoke<string> 817 { Test()818 public string Test () 819 { 820 return "MethodInvoke"; 821 } 822 } 823 824 [Test] GetInterfaceMapWorksWithVariantIfaces()825 public void GetInterfaceMapWorksWithVariantIfaces () 826 { 827 var m0 = typeof (IMethodInvoke<object>).GetMethod ("Test"); 828 var m1 = typeof (IMethodInvoke<string>).GetMethod ("Test"); 829 var obj = new MethodInvoke (); 830 831 Assert.AreEqual ("MethodInvoke", m0.Invoke (obj, new Object [0])); 832 Assert.AreEqual ("MethodInvoke", m1.Invoke (obj, new Object [0])); 833 } 834 835 Bug12856()836 public int? Bug12856 () 837 { 838 return null; 839 } 840 841 [Test] //Bug #12856 MethodToStringShouldPrintFullNameOfGenericStructs()842 public void MethodToStringShouldPrintFullNameOfGenericStructs () 843 { 844 var m = GetType ().GetMethod ("Bug12856"); 845 Assert.AreEqual ("System.Nullable`1[System.Int32] Bug12856()", m.ToString (), "#1"); 846 } 847 848 [Test] GetReflectedType()849 public void GetReflectedType () // #12205 850 { 851 // public method declared in base type, queried from a derived type 852 MethodInfo mi = typeof (TestInheritedMethodB).GetMethod ("TestMethod2"); 853 Assert.AreEqual (mi.ReflectedType, typeof (TestInheritedMethodB), "#1"); 854 855 // public method declared in a generic class, 856 // queried from a non-generic class derived 857 // from an instantiation of the generic class. 858 mi = typeof (DerivedFromGenericBase).GetMethod ("f2"); 859 Assert.AreEqual (mi.ReflectedType, typeof (DerivedFromGenericBase), "#2"); 860 861 // public method declared in a generic class, 862 // queried from the generic type defintion of 863 // a generic derived class. 864 mi = typeof (GenericMid<,>).GetMethod ("f2"); 865 Assert.AreEqual (mi.ReflectedType, typeof (GenericMid<,>), "#3"); 866 867 // public method declared in a generic class, 868 // queried from an instantiation of a generic 869 // derived class. 870 mi = typeof (GenericMid<int,int>).GetMethod ("f2"); 871 Assert.AreEqual (mi.ReflectedType, typeof (GenericMid<int,int>), "#4"); 872 873 } 874 875 #if !MONOTOUCH && !FULL_AOT_RUNTIME 876 class GenericClass<T> 877 { Method()878 public void Method () 879 { 880 T lv = default(T); 881 Console.WriteLine(lv); 882 } 883 Method2(T a0, K a1)884 public void Method2<K> (T a0, K a1) 885 { 886 T var0 = a0; 887 K var1 = a1; 888 Console.WriteLine (var0); 889 Console.WriteLine (var1); 890 } 891 } 892 893 [Test] TestLocalVariableTypes()894 public void TestLocalVariableTypes () 895 { 896 var typeofT = typeof (GenericClass<>).GetGenericArguments () [0]; 897 var typeofK = typeof (GenericClass<>).GetMethod ("Method2").GetGenericArguments () [0]; 898 899 var type = typeof (GenericClass<>).GetMethod("Method").GetMethodBody().LocalVariables[0].LocalType; 900 Assert.AreEqual (typeofT, type); 901 Assert.AreEqual (typeof (GenericClass<>), type.DeclaringType); 902 903 bool foundTypeOfK = false; 904 bool foundExpectedType = false; 905 906 MethodBody mb = typeof (GenericClass<>).GetMethod("Method2").GetMethodBody(); 907 foreach (LocalVariableInfo lvi in mb.LocalVariables) { 908 if (lvi.LocalType == typeofK) { 909 foundTypeOfK = true; 910 Assert.AreEqual (typeof (GenericClass<>), lvi.LocalType.DeclaringType, "#1-1"); 911 } else if (lvi.LocalType == typeofT) { 912 foundExpectedType = true; 913 Assert.AreEqual (typeof (GenericClass<>), lvi.LocalType.DeclaringType, "#1-2"); 914 } 915 } 916 917 Assert.IsTrue (foundTypeOfK, "#1-3"); 918 if (mb.LocalVariables.Count < 2) 919 Assert.Ignore ("Code built in release mode - 'T var0' optmized out"); 920 else 921 Assert.IsTrue (foundExpectedType, "#1-4"); 922 923 foundTypeOfK = false; 924 foundExpectedType = false; 925 mb = typeof (GenericClass<int>).GetMethod("Method2").GetMethodBody(); 926 foreach (LocalVariableInfo lvi in mb.LocalVariables) { 927 if (lvi.LocalType == typeofK) { 928 foundTypeOfK = true; 929 Assert.AreEqual (typeof (GenericClass<>), lvi.LocalType.DeclaringType, "#2-1"); 930 } else if (lvi.LocalType == typeof (int)) { 931 foundExpectedType = true; 932 } 933 } 934 935 Assert.IsTrue (foundTypeOfK, "#2-3"); 936 if (mb.LocalVariables.Count < 2) 937 Assert.Ignore ("Code built in release mode - 'int var0' optmized out"); 938 else 939 Assert.IsTrue (foundExpectedType, "#2-4"); 940 } 941 #endif 942 } 943 944 // Helper class 945 class RefOnlyMethodClass 946 { 947 // Helper static method RefOnlyMethod()948 static void RefOnlyMethod () 949 { 950 } 951 } 952 953 public class MethodHandleTest<T> 954 { 955 private List<T> _myList = new List<T> (); 956 MethodHandleTest()957 public MethodHandleTest () 958 { 959 _myList.Add (default (T)); 960 } 961 962 public List<T> MyList { 963 get { return _myList; } 964 set { _myList = value; } 965 } 966 } 967 } 968