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