Merge pull request #1304 from slluis/mac-proxy-autoconfig
[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         // 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                 [DllImport ("libfoo", EntryPoint="foo", CharSet=CharSet.Unicode, ExactSpelling=false, PreserveSig=true, SetLastError=true, BestFitMapping=true, ThrowOnUnmappableChar=true)]
58                 public static extern void dllImportMethod ();
59                 [MethodImplAttribute(MethodImplOptions.PreserveSig)]
60                 public void preserveSigMethod ()
61                 {
62                 }
63
64                 [MethodImplAttribute(MethodImplOptions.Synchronized)]
65                 public void synchronizedMethod ()
66                 {
67                 }
68
69                 [Test]
70                 public void IsDefined_AttributeType_Null ()
71                 {
72                         MethodInfo mi = typeof (MethodInfoTest).GetMethod ("foo");
73
74                         try {
75                                 mi.IsDefined ((Type) null, false);
76                                 Assert.Fail ("#1");
77                         } catch (ArgumentNullException ex) {
78                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
79                                 Assert.IsNull (ex.InnerException, "#3");
80                                 Assert.IsNotNull (ex.Message, "#4");
81                                 Assert.IsNotNull (ex.ParamName, "#5");
82                                 Assert.AreEqual ("attributeType", ex.ParamName, "#6");
83                         }
84                 }
85
86                 [Test]
87                 public void TestInvokeByRefReturnMethod ()
88                 {
89                         try {
90                                 MethodInfo m = typeof (int[]).GetMethod ("Address");
91                                 m.Invoke (new int[1], new object[] { 0 });
92                                 Assert.Fail ("#1");
93                         } catch (NotSupportedException e) {
94                                 Assert.AreEqual (typeof (NotSupportedException), e.GetType (), "#2");
95                                 Assert.IsNull (e.InnerException, "#3");
96                                 Assert.IsNotNull (e.Message, "#4");
97                         }
98                 }
99
100 #if NET_2_0
101                 [Test]
102                 public void PseudoCustomAttributes ()
103                 {
104                         Type t = typeof (MethodInfoTest);
105
106                         DllImportAttribute attr = (DllImportAttribute)((t.GetMethod ("dllImportMethod").GetCustomAttributes (typeof (DllImportAttribute), true)) [0]);
107
108                         Assert.AreEqual (CallingConvention.Winapi, attr.CallingConvention, "#1");
109                         Assert.AreEqual ("foo", attr.EntryPoint, "#2");
110                         Assert.AreEqual ("libfoo", attr.Value, "#3");
111                         Assert.AreEqual (CharSet.Unicode, attr.CharSet, "#4");
112                         Assert.AreEqual (false, attr.ExactSpelling, "#5");
113                         Assert.AreEqual (true, attr.PreserveSig, "#6");
114                         Assert.AreEqual (true, attr.SetLastError, "#7");
115                         Assert.AreEqual (true, attr.BestFitMapping, "#8");
116                         Assert.AreEqual (true, attr.ThrowOnUnmappableChar, "#9");
117
118                         PreserveSigAttribute attr2 = (PreserveSigAttribute)((t.GetMethod ("preserveSigMethod").GetCustomAttributes (true)) [0]);
119
120                         // This doesn't work under MS.NET
121                         /*
122                           MethodImplAttribute attr3 = (MethodImplAttribute)((t.GetMethod ("synchronizedMethod").GetCustomAttributes (true)) [0]);
123                         */
124                 }
125
126                 [return: MarshalAs (UnmanagedType.Interface)]
127                 public void ReturnTypeMarshalAs ()
128                 {
129                 }
130
131                 [Test]
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                         public 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                 [Test]
321                 public void GetMethodBody_Abstract ()
322                 {
323                         MethodBody mb = typeof (ICloneable).GetMethod ("Clone").GetMethodBody ();
324                         Assert.IsNull (mb);
325                 }
326
327                 [Test]
328                 public void GetMethodBody_Runtime ()
329                 {
330                         MethodBody mb = typeof (AsyncCallback).GetMethod ("Invoke").GetMethodBody ();
331                         Assert.IsNull (mb);
332                 }
333
334                 [Test]
335                 public void GetMethodBody_Pinvoke ()
336                 {
337                         MethodBody mb = typeof (MethodInfoTest).GetMethod ("dllImportMethod").GetMethodBody ();
338                         Assert.IsNull (mb);
339                 }
340
341                 [Test]
342                 public void GetMethodBody_Icall ()
343                 {
344                         foreach (MethodInfo mi in typeof (object).GetMethods (BindingFlags.Public|BindingFlags.NonPublic|BindingFlags.Instance))
345                                 if ((mi.GetMethodImplementationFlags () & MethodImplAttributes.InternalCall) != 0) {
346                                         MethodBody mb = mi.GetMethodBody ();
347                                         Assert.IsNull (mb);
348                                 }
349                 }
350
351                 public static void locals_method ()
352                 {
353                         byte[] b = new byte [10];
354
355                         unsafe {
356                                 /* This generates a pinned local */
357                                 fixed (byte *p = &b [0]) {
358                                 }
359                         }
360                 }
361
362                 [Test]
363                 public void GetMethodBody ()
364                 {
365 #if MONOTOUCH && !DEBUG
366                         Assert.Ignore ("Release app (on devices) are stripped of (managed) IL so this test would fail");
367 #endif
368                         MethodBody mb = typeof (MethodInfoTest).GetMethod ("locals_method").GetMethodBody ();
369
370                         Assert.IsTrue (mb.InitLocals, "#1");
371                         Assert.IsTrue (mb.LocalSignatureMetadataToken > 0, "#2");
372
373                         IList<LocalVariableInfo> locals = mb.LocalVariables;
374
375                         // This might break with different compilers etc.
376                         Assert.AreEqual (2, locals.Count, "#3");
377
378                         Assert.IsTrue ((locals [0].LocalType == typeof (byte[])) || (locals [1].LocalType == typeof (byte[])), "#4");
379                         if (locals [0].LocalType == typeof (byte[]))
380                                 Assert.AreEqual (false, locals [0].IsPinned, "#5");
381                         else
382                                 Assert.AreEqual (false, locals [1].IsPinned, "#6");
383                 }
384
385                 public int return_parameter_test ()
386                 {
387                         return 0;
388                 }
389
390                 [Test]
391                 public void GetMethodFromHandle_Generic ()
392                 {
393                         MethodHandleTest<int> test = new MethodHandleTest<int> ();
394                         RuntimeMethodHandle mh = test.GetType ().GetProperty ("MyList")
395                                 .GetGetMethod ().MethodHandle;
396                         MethodBase mb = MethodInfo.GetMethodFromHandle (mh,
397                                 typeof (MethodHandleTest<int>).TypeHandle);
398                         Assert.IsNotNull (mb, "#1");
399                         List<int> list = (List<int>) mb.Invoke (test, null);
400                         Assert.IsNotNull (list, "#2");
401                         Assert.AreEqual (1, list.Count, "#3");
402                 }
403
404                 [Test]
405                 public void ReturnParameter ()
406                 {
407                         ParameterInfo pi = typeof (MethodInfoTest).GetMethod ("return_parameter_test").ReturnParameter;
408                         Assert.AreEqual (typeof (int), pi.ParameterType, "#1");
409                         Assert.AreEqual (-1, pi.Position, "#2");
410                         // MS always return false here
411                         //Assert.IsTrue (pi.IsRetval, "#3");
412                 }
413
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
432                 [Test]
433                 [ExpectedException (typeof (TargetInvocationException))]
434                 public void InvokeInvalidOpExceptionThrow () {
435                         MethodInfo mi = typeof (MethodInfoTest).GetMethod ("ThrowMethod");
436                         mi.Invoke(null, null);
437                 }
438
439                 public static void ThrowMethod () {
440                         throw new InvalidOperationException ();
441                 }
442
443                 [Test]
444                 public void InvokeGenericVtype ()
445                 {
446                         KeyValuePair<string, uint> kvp = new KeyValuePair<string, uint> ("a", 21);
447                         Type type = kvp.GetType ();
448                         Type [] arguments = type.GetGenericArguments ();
449                         MethodInfo method = typeof (MethodInfoTest).GetMethod ("Go");
450                         MethodInfo generic_method = method.MakeGenericMethod (arguments);
451                         kvp = (KeyValuePair<string, uint>)generic_method.Invoke (null, new object [] { kvp });
452
453                         Assert.AreEqual ("a", kvp.Key, "#1");
454                         Assert.AreEqual (21, kvp.Value, "#2");
455                 }
456
457                 public static KeyValuePair<T1, T2> Go <T1, T2> (KeyValuePair <T1, T2> kvp)
458                 {
459                         return kvp;
460                 }
461
462                 [Test] // bug #81997
463                 public void InvokeGenericInst ()
464                 {
465                         List<string> str = null;
466
467                         object [] methodArgs = new object [] { str };
468                         MethodInfo mi = typeof (MethodInfoTest).GetMethod ("GenericRefMethod");
469                         mi.Invoke (null, methodArgs);
470                         Assert.IsNotNull (methodArgs [0], "#A1");
471                         Assert.IsNull (str, "#A2");
472                         Assert.IsTrue (methodArgs [0] is List<string>, "#A3");
473
474                         List<string> refStr = methodArgs [0] as List<string>;
475                         Assert.IsNotNull (refStr, "#B1");
476                         Assert.AreEqual (1, refStr.Count, "#B2");
477                         Assert.AreEqual ("test", refStr [0], "#B3");
478                 }
479
480                 public static void GenericRefMethod (ref List<string> strArg)
481                 {
482                         strArg = new List<string> ();
483                         strArg.Add ("test");
484                 }
485
486                 public void MakeGenericMethodArgsMismatchFoo<T> ()
487                 {
488                 }
489
490                 [Test]
491                 public void MakeGenericMethodArgsMismatch ()
492                 {
493                         MethodInfo gmi = this.GetType ().GetMethod (
494                                 "MakeGenericMethodArgsMismatchFoo");
495                         try {
496                                 gmi.MakeGenericMethod ();
497                                 Assert.Fail ("#1");
498                         } catch (ArgumentException ex) {
499                                 // The type or method has 1 generic parameter(s),
500                                 // but 0 generic argument(s) were provided. A
501                                 // generic argument must be provided for each
502                                 // generic parameter
503                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
504                                 Assert.IsNull (ex.InnerException, "#3");
505                                 Assert.IsNotNull (ex.Message, "#4");
506                                 Assert.IsNull (ex.ParamName, "#5");
507                         }
508                 }
509
510                 public void SimpleGenericMethod<TFoo, TBar> () {}
511
512                 [Test]
513                 public void MakeGenericMethodWithNullArray ()
514                 {
515                         MethodInfo gmi = this.GetType ().GetMethod ("SimpleGenericMethod");
516                         try {
517                                 gmi.MakeGenericMethod ((Type []) null);
518                                 Assert.Fail ("#1");
519                         } catch (ArgumentNullException ex) {
520                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
521                                 Assert.IsNull (ex.InnerException, "#3");
522                                 Assert.IsNotNull (ex.Message, "#4");
523                                 Assert.AreEqual ("methodInstantiation", ex.ParamName, "#5");
524                         }
525                 }
526
527                 [Test]
528                 public void MakeGenericMethodWithNullValueInTypesArray ()
529                 {
530                         MethodInfo gmi = this.GetType ().GetMethod ("SimpleGenericMethod");
531                         try {
532                                 gmi.MakeGenericMethod (new Type [] { typeof (int), null });
533                                 Assert.Fail ("#1");
534                         } catch (ArgumentNullException ex) {
535                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
536                                 Assert.IsNull (ex.InnerException, "#3");
537                                 Assert.IsNotNull (ex.Message, "#4");
538                                 Assert.IsNull (ex.ParamName, "#5");
539                         }
540                 }
541
542                 [Test]
543                 public void MakeGenericMethodWithNonGenericMethodDefinitionMethod ()
544                 {
545                         MethodInfo gmi = this.GetType ().GetMethod ("SimpleGenericMethod");
546                         MethodInfo inst = gmi.MakeGenericMethod (typeof (int), typeof (double));
547                         try {
548                                 inst.MakeGenericMethod (typeof (int), typeof (double));
549                                 Assert.Fail ("#1");
550                         } catch (InvalidOperationException ex) {
551                         }
552                 }
553 #if !MONOTOUCH
554                 public TFoo SimpleGenericMethod2<TFoo, TBar> () { return default (TFoo); }
555                 /*Test for the uggly broken behavior of SRE.*/
556                 [Test]
557                 public void MakeGenericMethodWithSreTypeResultsInStupidMethodInfo ()
558                 {
559                         AssemblyName assemblyName = new AssemblyName ();
560                         assemblyName.Name = "MonoTests.System.Reflection.Emit.MethodInfoTest";
561                         AssemblyBuilder assembly = Thread.GetDomain ().DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.RunAndSave, ".");
562                         ModuleBuilder module = assembly.DefineDynamicModule ("module1", "tst.dll");
563                         TypeBuilder tb = module.DefineType ("Test", TypeAttributes.Public);
564
565                         MethodInfo gmi = this.GetType ().GetMethod ("SimpleGenericMethod2");
566                         MethodInfo ins = gmi.MakeGenericMethod (typeof (int), tb);
567
568                         Assert.AreSame (tb, ins.GetGenericArguments () [1], "#1");
569                         /*broken ReturnType*/
570                         Assert.AreSame (gmi.GetGenericArguments () [0], ins.ReturnType, "#2");
571                 }
572 #endif
573                 public static int? pass_nullable (int? i)
574                 {
575                         return i;
576                 }
577
578                 [Test]
579                 public void NullableTests ()
580                 {
581                         MethodInfo mi = typeof (MethodInfoTest).GetMethod ("pass_nullable");
582                         Assert.AreEqual (102, mi.Invoke (null, new object [] { 102 }), "#1");
583                         Assert.AreEqual (null, mi.Invoke (null, new object [] { null }), "#2");
584
585                         // Test conversion of vtype to a nullable type for the this argument
586                         PropertyInfo pi = typeof (Nullable <int>).GetProperty ("HasValue");
587                         Assert.AreEqual (true, pi.GetGetMethod ().Invoke (10, null));
588                         PropertyInfo pi2 = typeof (Nullable <int>).GetProperty ("Value");
589                         Assert.AreEqual (10, pi2.GetGetMethod ().Invoke (10, null));
590                 }
591
592                 public static void foo_generic<T> ()
593                 {
594                 }
595
596                 [Test]
597                 public void IsGenericMethod ()
598                 {
599                         MethodInfo mi = typeof (MethodInfoTest).GetMethod ("foo_generic");
600                         Assert.AreEqual (true, mi.IsGenericMethod, "#1");
601                         MethodInfo mi2 = mi.MakeGenericMethod (new Type[] { typeof (int) });
602                         Assert.AreEqual (true, mi2.IsGenericMethod, "#2");
603                         MethodInfo mi3 = typeof (GenericHelper<int>).GetMethod ("Test");
604                         Assert.AreEqual (false, mi3.IsGenericMethod, "#3");
605                 }
606
607                 class A<T>
608                 {
609                         public static void Foo<T2> (T2 i)
610                         {
611                         }
612
613                         public static void Bar ()
614                         {
615                         }
616
617                         public class B
618                         {
619                                 public static void Baz ()
620                                 {
621                                 }
622                         }
623                 }
624
625                 [Test]
626                 public void ContainsGenericParameters ()
627                 {
628                         // Non-generic method in open generic type
629                         Assert.IsTrue (typeof (A<int>).GetGenericTypeDefinition ().GetMethod ("Bar").ContainsGenericParameters);
630                         // open generic method in closed generic type
631                         Assert.IsTrue (typeof (A<int>).GetMethod ("Foo").ContainsGenericParameters);
632                         // non-generic method in closed generic type
633                         Assert.IsFalse (typeof (A<int>).GetMethod ("Bar").ContainsGenericParameters);
634                         // closed generic method in closed generic type
635                         Assert.IsFalse (typeof (A<int>).GetMethod ("Foo").MakeGenericMethod (new Type [] { typeof (int) }).ContainsGenericParameters);
636                         // non-generic method in non-generic nested type of closed generic type
637                         Assert.IsFalse (typeof (A<int>.B).GetMethod ("Baz").ContainsGenericParameters);
638                         // non-generic method in non-generic nested type of open generic type
639                         Assert.IsTrue (typeof (A<int>.B).GetGenericTypeDefinition ().GetMethod ("Baz").ContainsGenericParameters);
640                 }
641
642                 [Test]
643                 public void IsGenericMethodDefinition ()
644                 {
645                         MethodInfo m1 = typeof (A<>).GetMethod ("Foo");
646                         Assert.IsTrue (m1.IsGenericMethod, "#A1");
647                         Assert.IsTrue (m1.IsGenericMethodDefinition, "#A2");
648
649                         MethodInfo m2 = typeof (A<int>).GetMethod ("Foo");
650                         Assert.IsTrue (m2.IsGenericMethod, "#B1");
651                         Assert.IsTrue (m2.IsGenericMethodDefinition, "#B2");
652
653                         MethodInfo m3 = m2.MakeGenericMethod (typeof (int));
654                         Assert.IsTrue (m3.IsGenericMethod, "#C1");
655                         Assert.IsFalse (m3.IsGenericMethodDefinition, "#C2");
656                 }
657
658                 [Test]
659                 public void GetGenericMethodDefinition ()
660                 {
661                         MethodInfo mi1 = typeof (MyList<>).GetMethod ("ConvertAll");
662                         MethodInfo mi2 = typeof (MyList<int>).GetMethod ("ConvertAll");
663
664                         Assert.AreEqual ("MonoTests.System.Reflection.MethodInfoTest+Foo`2[T,TOutput]",
665                                          mi1.GetParameters () [0].ParameterType.ToString (), "#A1");
666                         Assert.AreEqual ("MonoTests.System.Reflection.MethodInfoTest+Foo`2[System.Int32,TOutput]",
667                                          mi2.GetParameters () [0].ParameterType.ToString (), "#A2");
668                         Assert.IsTrue (mi1.IsGenericMethod, "#A3");
669                         Assert.IsTrue (mi1.IsGenericMethodDefinition, "#A4");
670                         Assert.IsTrue (mi2.IsGenericMethod, "#A5");
671                         Assert.IsTrue (mi2.IsGenericMethodDefinition, "#A6");
672
673                         MethodInfo mi3 = mi2.GetGenericMethodDefinition ();
674
675                         Assert.IsTrue (mi3.IsGenericMethod, "#B1");
676                         Assert.IsTrue (mi3.IsGenericMethodDefinition, "#B2");
677                         Assert.AreSame (mi2, mi3, "#B3");
678
679                         MethodInfo mi4 = mi2.MakeGenericMethod (typeof (short));
680                         Assert.IsTrue (mi4.IsGenericMethod, "#C1");
681                         Assert.IsFalse (mi4.IsGenericMethodDefinition, "#C2");
682                         Assert.AreSame (mi2, mi4.GetGenericMethodDefinition (), "#C3");
683                 }
684
685                 public void TestMethod123(int a, int b) {}
686
687                 [Test]
688                 public void GetParametersDontReturnInternedArray ()
689                 {
690                         var method = typeof (MethodInfoTest).GetMethod ("TestMethod123");
691                         var parms = method.GetParameters ();
692                         Assert.AreNotSame (parms, method.GetParameters (), "#1");
693
694                         parms [0] = null;
695                         Assert.IsNotNull (method.GetParameters () [0], "#2");
696                 }
697
698                 [Test]
699                 public void Bug354757 ()
700                 {
701                         MethodInfo gmd = (typeof (MyList <int>)).GetMethod ("ConvertAll");
702                         MethodInfo oi = gmd.MakeGenericMethod (gmd.GetGenericArguments ());
703                         Assert.AreSame (gmd, oi);
704                 }
705
706                 [Test]
707                 [ExpectedException (typeof (ArgumentException))]
708 #if MOBILE
709                 [Category ("NotWorking")] // #10552
710 #endif
711                 public void MakeGenericMethodRespectConstraints ()
712                 {
713                         var m = typeof (MethodInfoTest).GetMethod ("TestMethod");
714                         m.MakeGenericMethod (typeof (Type));
715                 }
716
717                 public void TestMethod <T> () where T : Exception
718                 {
719                 }
720
721                 public class MyList<T>
722                 {
723                         public TOutput ConvertAll<TOutput> (Foo<T,TOutput> arg)
724                         {
725                                 return default (TOutput);
726                         }
727                         public T ConvertAll2 (MyList<T> arg)
728                         {
729                                 return default (T);
730                         }
731                 }
732
733                 public class Foo<T,TOutput>
734                 {
735                 }
736
737                 class GenericHelper<T>
738                 {
739                         public void Test (T t)
740                         {
741                         }
742                 }
743 #endif
744 #if NET_4_0
745                 interface IMethodInvoke<out T>
746                 {
747                     T Test ();
748                 }
749
750                 class MethodInvoke : IMethodInvoke<string>
751                 {
752                     public string Test ()
753                     {
754                         return "MethodInvoke";
755                     }
756                 }
757
758                 [Test]
759                 public void GetInterfaceMapWorksWithVariantIfaces ()
760                 {
761                         var m0 = typeof (IMethodInvoke<object>).GetMethod ("Test");
762                         var m1 = typeof (IMethodInvoke<string>).GetMethod ("Test");
763                         var obj = new MethodInvoke ();
764
765                         Assert.AreEqual ("MethodInvoke", m0.Invoke (obj, new Object [0]));
766                         Assert.AreEqual ("MethodInvoke", m1.Invoke (obj, new Object [0]));
767                 }
768 #endif
769
770
771                 public int? Bug12856 ()
772                 {
773                         return null;
774                 }
775
776                 [Test] //Bug #12856
777                 public void MethodToStringShouldPrintFullNameOfGenericStructs ()
778                 {
779                         var m = GetType ().GetMethod ("Bug12856");
780                         Assert.AreEqual ("System.Nullable`1[System.Int32] Bug12856()", m.ToString (), "#1");
781                 }
782
783 #if !MONOTOUCH
784                 class GenericClass<T>
785                 {
786                         public void Method ()
787                         {
788                                 T lv = default(T);
789                                 Console.WriteLine(lv);
790                         }
791
792                         public void Method2<K> (T a0, K a1)
793                         {
794                                 T var0 = a0;
795                                 K var1 = a1;
796                                 Console.WriteLine (var0);
797                                 Console.WriteLine (var1);
798                         }
799                 }
800
801                 [Test]
802                 public void TestLocalVariableTypes ()
803                 {
804                         var typeofT = typeof (GenericClass<>).GetGenericArguments () [0];
805                         var typeofK = typeof (GenericClass<>).GetMethod ("Method2").GetGenericArguments () [0];
806
807                         var type = typeof (GenericClass<>).GetMethod("Method").GetMethodBody().LocalVariables[0].LocalType;
808                         Assert.AreEqual (typeofT, type);
809                         Assert.AreEqual (typeof (GenericClass<>), type.DeclaringType);
810
811                         type = typeof (GenericClass<>).GetMethod("Method2").GetMethodBody().LocalVariables[0].LocalType;
812                         Assert.AreEqual (typeofT, type);
813                         Assert.AreEqual (typeof (GenericClass<>), type.DeclaringType);
814
815                         type = typeof (GenericClass<>).GetMethod("Method2").GetMethodBody().LocalVariables[1].LocalType;
816                         Assert.AreEqual (typeofK, type);
817                         Assert.AreEqual (typeof (GenericClass<>), type.DeclaringType);
818
819                         type = typeof (GenericClass<int>).GetMethod("Method2").GetMethodBody().LocalVariables[0].LocalType;
820                         Assert.AreEqual (typeof (int), type);
821
822                         type = typeof (GenericClass<int>).GetMethod("Method2").GetMethodBody().LocalVariables[1].LocalType;
823                         Assert.AreEqual (typeofK, type);
824                         Assert.AreEqual (typeof (GenericClass<>), type.DeclaringType);
825                 }
826 #endif
827         }
828         
829 #if NET_2_0
830         // Helper class
831         class RefOnlyMethodClass 
832         {
833                 // Helper static method
834                 static void RefOnlyMethod ()
835                 {
836                 }
837         }
838
839         public class MethodHandleTest<T>
840         {
841                 private List<T> _myList = new List<T> ();
842
843                 public MethodHandleTest ()
844                 {
845                         _myList.Add (default (T));
846                 }
847
848                 public List<T> MyList {
849                         get { return _myList; }
850                         set { _myList = value; }
851                 }
852         }
853 #endif
854 }