Add [Category ("NotWorking")] to failing test.
[mono.git] / mcs / class / corlib / Test / System.Reflection / PropertyInfoTest.cs
1 //
2 // PropertyInfoTest.cs - NUnit Test Cases for PropertyInfo
3 //
4 // Author:
5 //      Gert Driesen (drieseng@users.sourceforge.net)
6 //
7 // (C) 2004-2007 Gert Driesen
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29
30 using System;
31 using System.Reflection;
32 using System.Runtime.InteropServices;
33 using System.Threading;
34 #if !MONOTOUCH
35 using System.Reflection.Emit;
36 #endif
37 using System.IO;
38
39 using NUnit.Framework;
40
41 namespace MonoTests.System.Reflection
42 {
43         [TestFixture]
44         public class PropertyInfoTest
45         {
46                 [Test]
47                 public void GetAccessorsTest ()
48                 {
49                         Type type = typeof (TestClass);
50                         PropertyInfo property = type.GetProperty ("ReadOnlyProperty");
51
52                         MethodInfo [] methods = property.GetAccessors (true);
53                         Assert.AreEqual (1, methods.Length, "#A1");
54                         Assert.IsNotNull (methods [0], "#A2");
55                         Assert.AreEqual ("get_ReadOnlyProperty", methods [0].Name, "#A3");
56
57                         methods = property.GetAccessors (false);
58                         Assert.AreEqual (1, methods.Length, "#B1");
59                         Assert.IsNotNull (methods [0], "#B2");
60                         Assert.AreEqual ("get_ReadOnlyProperty", methods [0].Name, "#B3");
61
62                         property = typeof (Base).GetProperty ("P");
63
64                         methods = property.GetAccessors (true);
65                         Assert.AreEqual (2, methods.Length, "#C1");
66                         Assert.IsNotNull (methods [0], "#C2");
67                         Assert.IsNotNull (methods [1], "#C3");
68                         Assert.IsTrue (HasMethod (methods, "get_P"), "#C4");
69                         Assert.IsTrue (HasMethod (methods, "set_P"), "#C5");
70
71                         methods = property.GetAccessors (false);
72                         Assert.AreEqual (2, methods.Length, "#D1");
73                         Assert.IsNotNull (methods [0], "#D2");
74                         Assert.IsNotNull (methods [1], "#D3");
75                         Assert.IsTrue (HasMethod (methods, "get_P"), "#D4");
76                         Assert.IsTrue (HasMethod (methods, "set_P"), "#D5");
77
78                         methods = property.GetAccessors ();
79                         Assert.AreEqual (2, methods.Length, "#E1");
80                         Assert.IsNotNull (methods [0], "#E2");
81                         Assert.IsNotNull (methods [1], "#E3");
82                         Assert.IsTrue (HasMethod (methods, "get_P"), "#E4");
83                         Assert.IsTrue (HasMethod (methods, "set_P"), "#E5");
84
85                         property = typeof (TestClass).GetProperty ("Private",
86                                 BindingFlags.NonPublic | BindingFlags.Instance);
87
88                         methods = property.GetAccessors (true);
89                         Assert.AreEqual (2, methods.Length, "#F1");
90                         Assert.IsNotNull (methods [0], "#F2");
91                         Assert.IsNotNull (methods [1], "#F3");
92                         Assert.IsTrue (HasMethod (methods, "get_Private"), "#F4");
93                         Assert.IsTrue (HasMethod (methods, "set_Private"), "#F5");
94
95                         methods = property.GetAccessors (false);
96                         Assert.AreEqual (0, methods.Length, "#G");
97
98                         methods = property.GetAccessors ();
99                         Assert.AreEqual (0, methods.Length, "#H");
100
101 #if NET_2_0
102                         property = typeof (TestClass).GetProperty ("PrivateSetter");
103
104                         methods = property.GetAccessors (true);
105                         Assert.AreEqual (2, methods.Length, "#H1");
106                         Assert.IsNotNull (methods [0], "#H2");
107                         Assert.IsNotNull (methods [1], "#H3");
108                         Assert.IsTrue (HasMethod (methods, "get_PrivateSetter"), "#H4");
109                         Assert.IsTrue (HasMethod (methods, "set_PrivateSetter"), "#H5");
110
111                         methods = property.GetAccessors (false);
112                         Assert.AreEqual (1, methods.Length, "#I1");
113                         Assert.IsNotNull (methods [0], "#I2");
114                         Assert.AreEqual ("get_PrivateSetter", methods [0].Name, "#I3");
115
116                         methods = property.GetAccessors ();
117                         Assert.AreEqual (1, methods.Length, "#J1");
118                         Assert.IsNotNull (methods [0], "#J2");
119                         Assert.AreEqual ("get_PrivateSetter", methods [0].Name, "#J3");
120 #endif
121                 }
122
123                 [Test]
124                 public void GetCustomAttributes ()
125                 {
126                         object [] attrs;
127                         PropertyInfo p = typeof (Base).GetProperty ("P");
128
129                         attrs = p.GetCustomAttributes (false);
130                         Assert.AreEqual (1, attrs.Length, "#A1");
131                         Assert.AreEqual (typeof (ThisAttribute), attrs [0].GetType (), "#A2");
132                         attrs = p.GetCustomAttributes (true);
133                         Assert.AreEqual (1, attrs.Length, "#A3");
134                         Assert.AreEqual (typeof (ThisAttribute), attrs [0].GetType (), "#A4");
135
136                         p = typeof (Base).GetProperty ("T");
137
138                         attrs = p.GetCustomAttributes (false);
139                         Assert.AreEqual (2, attrs.Length, "#B1");
140                         Assert.IsTrue (HasAttribute (attrs, typeof (ThisAttribute)), "#B2");
141                         Assert.IsTrue (HasAttribute (attrs, typeof (ComVisibleAttribute)), "#B3");
142                         attrs = p.GetCustomAttributes (true);
143                         Assert.AreEqual (2, attrs.Length, "#B41");
144                         Assert.IsTrue (HasAttribute (attrs, typeof (ThisAttribute)), "#B5");
145                         Assert.IsTrue (HasAttribute (attrs, typeof (ComVisibleAttribute)), "#B6");
146
147                         p = typeof (Base).GetProperty ("Z");
148
149                         attrs = p.GetCustomAttributes (false);
150                         Assert.AreEqual (0, attrs.Length, "#C1");
151                         attrs = p.GetCustomAttributes (true);
152                         Assert.AreEqual (0, attrs.Length, "#C2");
153                 }
154
155                 [Test]
156                 public void GetCustomAttributes_Inherited ()
157                 {
158                         object [] attrs;
159                         PropertyInfo p = typeof (Derived).GetProperty ("P");
160
161                         attrs = p.GetCustomAttributes (false);
162                         Assert.AreEqual (0, attrs.Length, "#A1");
163                         attrs = p.GetCustomAttributes (true);
164                         Assert.AreEqual (0, attrs.Length, "#A3");
165
166                         p = typeof (Derived).GetProperty ("T");
167
168                         attrs = p.GetCustomAttributes (false);
169                         Assert.AreEqual (2, attrs.Length, "#B1");
170                         Assert.IsTrue (HasAttribute (attrs, typeof (ThisAttribute)), "#B2");
171                         Assert.IsTrue (HasAttribute (attrs, typeof (ComVisibleAttribute)), "#B3");
172                         attrs = p.GetCustomAttributes (true);
173                         Assert.AreEqual (2, attrs.Length, "#B41");
174                         Assert.IsTrue (HasAttribute (attrs, typeof (ThisAttribute)), "#B5");
175                         Assert.IsTrue (HasAttribute (attrs, typeof (ComVisibleAttribute)), "#B6");
176
177                         p = typeof (Derived).GetProperty ("Z");
178
179                         attrs = p.GetCustomAttributes (false);
180                         Assert.AreEqual (0, attrs.Length, "#C1");
181                         attrs = p.GetCustomAttributes (true);
182                         Assert.AreEqual (0, attrs.Length, "#C2");
183                 }
184
185                 [Test]
186                 public void IsDefined_AttributeType_Null ()
187                 {
188                         Type derived = typeof (Derived);
189                         PropertyInfo pi = derived.GetProperty ("P");
190
191                         try {
192                                 pi.IsDefined ((Type) null, false);
193                                 Assert.Fail ("#1");
194                         } catch (ArgumentNullException ex) {
195                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
196                                 Assert.IsNull (ex.InnerException, "#3");
197                                 Assert.IsNotNull (ex.Message, "#4");
198                                 Assert.IsNotNull (ex.ParamName, "#5");
199                                 Assert.AreEqual ("attributeType", ex.ParamName, "#6");
200                         }
201                 }
202
203                 [Test]
204                 public void AccessorsReflectedType ()
205                 {
206                         PropertyInfo pi = typeof (Derived).GetProperty ("T");
207                         Assert.AreEqual (typeof (Derived), pi.GetGetMethod ().ReflectedType);
208                         Assert.AreEqual (typeof (Derived), pi.GetSetMethod ().ReflectedType);
209                 }
210
211                 [Test] // bug #399985
212                 public void SetValue_Enum ()
213                 {
214                         TestClass t = new TestClass ();
215                         PropertyInfo pi = t.GetType ().GetProperty ("Targets");
216                         pi.SetValue (t, AttributeTargets.Field, null);
217                         Assert.AreEqual (AttributeTargets.Field, t.Targets, "#1");
218                         pi.SetValue (t, (int) AttributeTargets.Interface, null);
219                         Assert.AreEqual (AttributeTargets.Interface, t.Targets, "#2");
220                 }
221
222                 public class ThisAttribute : Attribute
223                 {
224                 }
225
226                 class Base
227                 {
228                         [ThisAttribute]
229                         public virtual string P {
230                                 get { return null; }
231                                 set { }
232                         }
233
234                         [ThisAttribute]
235                         [ComVisible (false)]
236                         public virtual string T {
237                                 get { return null; }
238                                 set { }
239                         }
240
241                         public virtual string Z {
242                                 get { return null; }
243                                 set { }
244                         }
245                 }
246
247                 class Derived : Base
248                 {
249                         public override string P {
250                                 get { return null; }
251                                 set { }
252                         }
253                 }
254
255                 static void RunTest (Type t, bool use_getter) {
256                         var p = t.GetProperty ("Item");
257                         var idx = p.GetIndexParameters ();
258                         var m_args = t.GetMethod (use_getter ? "get_Item" : "set_Item").GetParameters ();
259
260                         Assert.AreEqual (2, idx.Length, "#1");
261
262                         Assert.AreEqual (typeof (double), idx [0].ParameterType, "#2");
263                         Assert.AreEqual (p, idx [0].Member, "#3");
264                         Assert.AreEqual ("a", idx [0].Name, "#4");
265                         Assert.AreEqual (0, idx [0].Position, "#5");
266                         Assert.AreEqual (m_args [0].MetadataToken, idx [0].MetadataToken, "#6");
267                         Assert.AreEqual (ParameterAttributes.None, idx [0].Attributes, "#7");
268
269                         Assert.AreEqual (typeof (string), idx [1].ParameterType, "#8");
270                         Assert.AreEqual (p, idx [1].Member, "#9");
271                         Assert.AreEqual ("b", idx [1].Name, "#10");
272                         Assert.AreEqual (1, idx [1].Position, "#11");
273                         Assert.AreEqual (m_args [1].MetadataToken, idx [1].MetadataToken, "#12");
274                         Assert.AreEqual (ParameterAttributes.None, idx [1].Attributes, "#13");
275
276                         var idx2 = p.GetIndexParameters ();
277
278                         //No interning exposed
279                         Assert.AreNotSame (idx, idx2, "#14");
280                         Assert.AreNotSame (idx [0], idx2 [1], "#15");
281                 }
282
283                 [Test]
284                 public void GetIndexParameterReturnsObjectsBoundToTheProperty ()
285                 {
286                         RunTest (typeof (TestA), false);
287                         RunTest (typeof (TestB), true);
288                 }
289
290                 public class TestA {
291                         public int this[double a, string b] {
292                                 set {}
293                         }
294                 }
295
296                 public class TestB {
297                         public int this[double a, string b] {
298                                 get { return 1; }
299                                 set {}
300                         }
301                 }
302
303                 [Test]
304                 public void GetIndexParameterReturnedObjectsCustomAttributes () {
305                         var pa = typeof (TestC).GetProperty ("Item").GetIndexParameters () [0];
306                         Assert.IsTrue (pa.IsDefined (typeof (ParamArrayAttribute), false), "#1");
307
308                         var pb = typeof (TestD).GetProperty ("Item").GetIndexParameters () [0];
309                         Assert.IsTrue (pb.IsDefined (typeof (ParamArrayAttribute), false), "#2");
310
311                         Assert.AreEqual (1, Attribute.GetCustomAttributes (pa).Length, "#3");
312                         Assert.AreEqual (1, Attribute.GetCustomAttributes (pb).Length, "#4");
313
314                         Assert.AreEqual (0, pa.GetOptionalCustomModifiers ().Length, "#5");
315                         Assert.AreEqual (0, pb.GetRequiredCustomModifiers ().Length, "#6");
316                 }
317
318                 public class TestC {
319                         public int this[params double[] a] {
320                                 get { return 99; }
321                         }
322                 }
323
324                 public class TestD {
325                         public int this[params double[] a] {
326                                 set { }
327                         }
328                 }
329
330                 static string CreateTempAssembly ()
331                 {
332                         FileStream f = null;
333                         string path;
334                         Random rnd;
335                         int num = 0;
336
337                         rnd = new Random ();
338                         do {
339                                 num = rnd.Next ();
340                                 num++;
341                                 path = Path.Combine (Path.GetTempPath (), "tmp" + num.ToString ("x") + ".dll");
342
343                                 try {
344                                         f = new FileStream (path, FileMode.CreateNew);
345                                 } catch { }
346                         } while (f == null);
347
348                         f.Close ();
349
350
351                         return "tmp" + num.ToString ("x") + ".dll";
352                 }
353
354                 public class TestE {
355                         public int PropE {
356                                 get { return 99; }
357                         }
358                 }
359 #if !MONOTOUCH
360                 [Test]
361                 public void ConstantValue () {
362                         /*This test looks scary because we can't generate a default value with C# */
363                         var assemblyName = new AssemblyName ();
364                         assemblyName.Name = "MonoTests.System.Reflection.Emit.PropertyInfoTest";
365                         string an = CreateTempAssembly ();
366
367                         var assembly = Thread.GetDomain ().DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.RunAndSave, Path.GetTempPath ());
368                         var module = assembly.DefineDynamicModule ("module1", an);
369
370                         var tb = module.DefineType ("Test", TypeAttributes.Public);
371                         var prop = tb.DefineProperty ("Prop", PropertyAttributes.HasDefault, typeof (string), new Type [0]);
372
373                         var getter = tb.DefineMethod ("get_Prop", MethodAttributes.Public, typeof (string), new Type [0]);
374                         var ilgen = getter.GetILGenerator ();
375                         ilgen.Emit (OpCodes.Ldnull);
376                         ilgen.Emit (OpCodes.Ret);
377
378                         var setter = tb.DefineMethod ("set_Prop", MethodAttributes.Public, null, new Type [1] { typeof (string) });
379                         setter.GetILGenerator ().Emit (OpCodes.Ret);
380
381                         prop.SetConstant ("test");
382                         prop.SetGetMethod (getter);
383                         prop.SetSetMethod (setter);
384
385                         tb.CreateType ();
386
387                         File.Delete (Path.Combine (Path.GetTempPath (), an));
388                         assembly.Save (an);
389
390                         var asm = Assembly.LoadFrom (Path.Combine (Path.GetTempPath (), an));
391                         var t = asm.GetType ("Test");
392                         var p = t.GetProperty ("Prop");
393                         Assert.AreEqual ("test", p.GetConstantValue (), "#1");
394
395                         File.Delete (Path.Combine (Path.GetTempPath (), an));
396
397                         var pa = typeof (TestE).GetProperty ("PropE");
398                         try {
399                                 pa.GetConstantValue ();
400                                 Assert.Fail ("#2");
401                         } catch (InvalidOperationException) {
402                         }
403                 }
404 #endif
405
406                 public class A<T>
407                 {
408                         public string Property {
409                                 get { return typeof (T).FullName; }
410                         }
411                 }
412
413                 public int? nullable_field;
414
415                 public int? NullableProperty {
416                         get { return nullable_field; }
417                         set { nullable_field = value; }
418                 }
419
420                 [Test]
421                 public void NullableTests ()
422                 {
423                         PropertyInfoTest t = new PropertyInfoTest ();
424
425                         PropertyInfo pi = typeof(PropertyInfoTest).GetProperty("NullableProperty");
426
427                         pi.SetValue (t, 100, null);
428                         Assert.AreEqual (100, pi.GetValue (t, null));
429                         pi.SetValue (t, null, null);
430                         Assert.AreEqual (null, pi.GetValue (t, null));
431                 }
432
433                 [Test]
434                 public void Bug77160 ()
435                 {
436                         object instance = new A<string> ();
437                         Type type = instance.GetType ();
438                         PropertyInfo property = type.GetProperty ("Property");
439                         Assert.AreEqual (typeof (string).FullName, property.GetValue (instance, null));
440                 }
441
442                 [Test]
443                 public void ToStringTest ()
444                 {
445                         var pa = typeof (TestC).GetProperty ("Item");
446                         Assert.AreEqual ("Int32 Item [System.Double[]]", pa.ToString ());
447                 }
448
449                 static bool HasAttribute (object [] attrs, Type attributeType)
450                 {
451                         foreach (object attr in attrs)
452                                 if (attr.GetType () == attributeType)
453                                         return true;
454                         return false;
455                 }
456
457                 static bool HasMethod (MethodInfo [] methods, string name)
458                 {
459                         foreach (MethodInfo method in methods)
460                                 if (method.Name == name)
461                                         return true;
462                         return false;
463                 }
464
465                 private class TestClass
466                 {
467                         private AttributeTargets _targets = AttributeTargets.Assembly;
468
469                         public AttributeTargets Targets {
470                                 get { return _targets; }
471                                 set { _targets = value; }
472                         }
473
474                         public string ReadOnlyProperty {
475                                 get { return string.Empty; }
476                         }
477
478                         private string Private {
479                                 get { return null; }
480                                 set { }
481                         }
482
483 #if NET_2_0
484                         public string PrivateSetter {
485                                 get { return null; }
486                                 private set { }
487                         }
488 #endif
489                 }
490
491                 [Test] // bug #633671
492                 public void DeclaringTypeOfPropertyFromInheritedTypePointsToBase ()
493                 {
494                         var inherit1 = typeof(InheritsFromClassWithNullableDateTime);
495                         var siblingProperty = inherit1.GetProperty("Property1");
496
497                         Assert.AreEqual (typeof (ClassWithNullableDateTime), siblingProperty.DeclaringType, "#1");
498                         Assert.AreEqual (typeof (InheritsFromClassWithNullableDateTime), siblingProperty.ReflectedType, "#2");
499
500                         //The check is done twice since the bug is related to getting those 2 properties multiple times.
501                         Assert.AreEqual (typeof (ClassWithNullableDateTime), siblingProperty.DeclaringType, "#3");
502                         Assert.AreEqual (typeof (InheritsFromClassWithNullableDateTime), siblingProperty.ReflectedType, "#4");
503                 }
504                 
505         
506                 public class ClassWithNullableDateTime
507                 {
508                         public DateTime? Property1 { get; set; }
509                 }
510         
511                 public class InheritsFromClassWithNullableDateTime : ClassWithNullableDateTime
512                 {
513                 }
514
515                 public static int ThrowingProperty {
516                         get {
517                                 throw new ObjectDisposedException("TestClass");
518                         }
519                 }
520
521                 [Test]
522                 public void GetException () {
523                         var prop = typeof(PropertyInfoTest).GetProperty("ThrowingProperty");
524                         try {
525                                 prop.GetValue (null, null);
526                                 Assert.Fail ();
527                         } catch (TargetInvocationException ex) {
528                                 Assert.IsTrue (ex.InnerException is ObjectDisposedException);
529                         }
530                 }
531
532                 public class DefaultValueTest
533                 {
534                         public string this[int val, string param = "test"]
535                         {
536                                 get{ return val + param; }
537                         }
538                 }
539
540
541                 [Test]
542                 public void PropertyWithDefaultValue ()
543                 {
544                         var parameters = typeof (DefaultValueTest).GetProperty ("Item").GetIndexParameters ();
545                         var defaultParam = parameters[parameters.Length - 1];
546                         Assert.AreEqual ("param", defaultParam.Name, "#1");
547                         Assert.AreEqual ("test", defaultParam.DefaultValue, "#2");
548                 }
549         }
550 }