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