Normalize line endings.
[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 using System.Reflection.Emit;
35 using System.IO;
36
37 using NUnit.Framework;
38
39 namespace MonoTests.System.Reflection
40 {
41         [TestFixture]
42         public class PropertyInfoTest
43         {
44                 [Test]
45                 public void GetAccessorsTest ()
46                 {
47                         Type type = typeof (TestClass);
48                         PropertyInfo property = type.GetProperty ("ReadOnlyProperty");
49
50                         MethodInfo [] methods = property.GetAccessors (true);
51                         Assert.AreEqual (1, methods.Length, "#A1");
52                         Assert.IsNotNull (methods [0], "#A2");
53                         Assert.AreEqual ("get_ReadOnlyProperty", methods [0].Name, "#A3");
54
55                         methods = property.GetAccessors (false);
56                         Assert.AreEqual (1, methods.Length, "#B1");
57                         Assert.IsNotNull (methods [0], "#B2");
58                         Assert.AreEqual ("get_ReadOnlyProperty", methods [0].Name, "#B3");
59
60                         property = typeof (Base).GetProperty ("P");
61
62                         methods = property.GetAccessors (true);
63                         Assert.AreEqual (2, methods.Length, "#C1");
64                         Assert.IsNotNull (methods [0], "#C2");
65                         Assert.IsNotNull (methods [1], "#C3");
66                         Assert.IsTrue (HasMethod (methods, "get_P"), "#C4");
67                         Assert.IsTrue (HasMethod (methods, "set_P"), "#C5");
68
69                         methods = property.GetAccessors (false);
70                         Assert.AreEqual (2, methods.Length, "#D1");
71                         Assert.IsNotNull (methods [0], "#D2");
72                         Assert.IsNotNull (methods [1], "#D3");
73                         Assert.IsTrue (HasMethod (methods, "get_P"), "#D4");
74                         Assert.IsTrue (HasMethod (methods, "set_P"), "#D5");
75
76                         methods = property.GetAccessors ();
77                         Assert.AreEqual (2, methods.Length, "#E1");
78                         Assert.IsNotNull (methods [0], "#E2");
79                         Assert.IsNotNull (methods [1], "#E3");
80                         Assert.IsTrue (HasMethod (methods, "get_P"), "#E4");
81                         Assert.IsTrue (HasMethod (methods, "set_P"), "#E5");
82
83                         property = typeof (TestClass).GetProperty ("Private",
84                                 BindingFlags.NonPublic | BindingFlags.Instance);
85
86                         methods = property.GetAccessors (true);
87                         Assert.AreEqual (2, methods.Length, "#F1");
88                         Assert.IsNotNull (methods [0], "#F2");
89                         Assert.IsNotNull (methods [1], "#F3");
90                         Assert.IsTrue (HasMethod (methods, "get_Private"), "#F4");
91                         Assert.IsTrue (HasMethod (methods, "set_Private"), "#F5");
92
93                         methods = property.GetAccessors (false);
94                         Assert.AreEqual (0, methods.Length, "#G");
95
96                         methods = property.GetAccessors ();
97                         Assert.AreEqual (0, methods.Length, "#H");
98
99 #if NET_2_0
100                         property = typeof (TestClass).GetProperty ("PrivateSetter");
101
102                         methods = property.GetAccessors (true);
103                         Assert.AreEqual (2, methods.Length, "#H1");
104                         Assert.IsNotNull (methods [0], "#H2");
105                         Assert.IsNotNull (methods [1], "#H3");
106                         Assert.IsTrue (HasMethod (methods, "get_PrivateSetter"), "#H4");
107                         Assert.IsTrue (HasMethod (methods, "set_PrivateSetter"), "#H5");
108
109                         methods = property.GetAccessors (false);
110                         Assert.AreEqual (1, methods.Length, "#I1");
111                         Assert.IsNotNull (methods [0], "#I2");
112                         Assert.AreEqual ("get_PrivateSetter", methods [0].Name, "#I3");
113
114                         methods = property.GetAccessors ();
115                         Assert.AreEqual (1, methods.Length, "#J1");
116                         Assert.IsNotNull (methods [0], "#J2");
117                         Assert.AreEqual ("get_PrivateSetter", methods [0].Name, "#J3");
118 #endif
119                 }
120
121                 [Test]
122                 public void GetCustomAttributes ()
123                 {
124                         object [] attrs;
125                         PropertyInfo p = typeof (Base).GetProperty ("P");
126
127                         attrs = p.GetCustomAttributes (false);
128                         Assert.AreEqual (1, attrs.Length, "#A1");
129                         Assert.AreEqual (typeof (ThisAttribute), attrs [0].GetType (), "#A2");
130                         attrs = p.GetCustomAttributes (true);
131                         Assert.AreEqual (1, attrs.Length, "#A3");
132                         Assert.AreEqual (typeof (ThisAttribute), attrs [0].GetType (), "#A4");
133
134                         p = typeof (Base).GetProperty ("T");
135
136                         attrs = p.GetCustomAttributes (false);
137                         Assert.AreEqual (2, attrs.Length, "#B1");
138                         Assert.IsTrue (HasAttribute (attrs, typeof (ThisAttribute)), "#B2");
139                         Assert.IsTrue (HasAttribute (attrs, typeof (ComVisibleAttribute)), "#B3");
140                         attrs = p.GetCustomAttributes (true);
141                         Assert.AreEqual (2, attrs.Length, "#B41");
142                         Assert.IsTrue (HasAttribute (attrs, typeof (ThisAttribute)), "#B5");
143                         Assert.IsTrue (HasAttribute (attrs, typeof (ComVisibleAttribute)), "#B6");
144
145                         p = typeof (Base).GetProperty ("Z");
146
147                         attrs = p.GetCustomAttributes (false);
148                         Assert.AreEqual (0, attrs.Length, "#C1");
149                         attrs = p.GetCustomAttributes (true);
150                         Assert.AreEqual (0, attrs.Length, "#C2");
151                 }
152
153                 [Test]
154                 public void GetCustomAttributes_Inherited ()
155                 {
156                         object [] attrs;
157                         PropertyInfo p = typeof (Derived).GetProperty ("P");
158
159                         attrs = p.GetCustomAttributes (false);
160                         Assert.AreEqual (0, attrs.Length, "#A1");
161                         attrs = p.GetCustomAttributes (true);
162                         Assert.AreEqual (0, attrs.Length, "#A3");
163
164                         p = typeof (Derived).GetProperty ("T");
165
166                         attrs = p.GetCustomAttributes (false);
167                         Assert.AreEqual (2, attrs.Length, "#B1");
168                         Assert.IsTrue (HasAttribute (attrs, typeof (ThisAttribute)), "#B2");
169                         Assert.IsTrue (HasAttribute (attrs, typeof (ComVisibleAttribute)), "#B3");
170                         attrs = p.GetCustomAttributes (true);
171                         Assert.AreEqual (2, attrs.Length, "#B41");
172                         Assert.IsTrue (HasAttribute (attrs, typeof (ThisAttribute)), "#B5");
173                         Assert.IsTrue (HasAttribute (attrs, typeof (ComVisibleAttribute)), "#B6");
174
175                         p = typeof (Derived).GetProperty ("Z");
176
177                         attrs = p.GetCustomAttributes (false);
178                         Assert.AreEqual (0, attrs.Length, "#C1");
179                         attrs = p.GetCustomAttributes (true);
180                         Assert.AreEqual (0, attrs.Length, "#C2");
181                 }
182
183                 [Test]
184                 public void IsDefined_AttributeType_Null ()
185                 {
186                         Type derived = typeof (Derived);
187                         PropertyInfo pi = derived.GetProperty ("P");
188
189                         try {
190                                 pi.IsDefined ((Type) null, false);
191                                 Assert.Fail ("#1");
192                         } catch (ArgumentNullException ex) {
193                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
194                                 Assert.IsNull (ex.InnerException, "#3");
195                                 Assert.IsNotNull (ex.Message, "#4");
196                                 Assert.IsNotNull (ex.ParamName, "#5");
197                                 Assert.AreEqual ("attributeType", ex.ParamName, "#6");
198                         }
199                 }
200
201                 [Test]
202                 public void AccessorsReflectedType ()
203                 {
204                         PropertyInfo pi = typeof (Derived).GetProperty ("T");
205                         Assert.AreEqual (typeof (Derived), pi.GetGetMethod ().ReflectedType);
206                         Assert.AreEqual (typeof (Derived), pi.GetSetMethod ().ReflectedType);
207                 }
208
209                 [Test] // bug #399985
210                 public void SetValue_Enum ()
211                 {
212                         TestClass t = new TestClass ();
213                         PropertyInfo pi = t.GetType ().GetProperty ("Targets");
214                         pi.SetValue (t, AttributeTargets.Field, null);
215                         Assert.AreEqual (AttributeTargets.Field, t.Targets, "#1");
216                         pi.SetValue (t, (int) AttributeTargets.Interface, null);
217                         Assert.AreEqual (AttributeTargets.Interface, t.Targets, "#2");
218                 }
219
220                 public class ThisAttribute : Attribute
221                 {
222                 }
223
224                 class Base
225                 {
226                         [ThisAttribute]
227                         public virtual string P {
228                                 get { return null; }
229                                 set { }
230                         }
231
232                         [ThisAttribute]
233                         [ComVisible (false)]
234                         public virtual string T {
235                                 get { return null; }
236                                 set { }
237                         }
238
239                         public virtual string Z {
240                                 get { return null; }
241                                 set { }
242                         }
243                 }
244
245                 class Derived : Base
246                 {
247                         public override string P {
248                                 get { return null; }
249                                 set { }
250                         }
251                 }
252
253                 static void RunTest (Type t, bool use_getter) {
254                         var p = t.GetProperty ("Item");
255                         var idx = p.GetIndexParameters ();
256                         var m_args = t.GetMethod (use_getter ? "get_Item" : "set_Item").GetParameters ();
257
258                         Assert.AreEqual (2, idx.Length, "#1");
259
260                         Assert.AreEqual (typeof (double), idx [0].ParameterType, "#2");
261                         Assert.AreEqual (p, idx [0].Member, "#3");
262                         Assert.AreEqual ("a", idx [0].Name, "#4");
263                         Assert.AreEqual (0, idx [0].Position, "#5");
264                         Assert.AreEqual (m_args [0].MetadataToken, idx [0].MetadataToken, "#6");
265                         Assert.AreEqual (ParameterAttributes.None, idx [0].Attributes, "#7");
266
267                         Assert.AreEqual (typeof (string), idx [1].ParameterType, "#8");
268                         Assert.AreEqual (p, idx [1].Member, "#9");
269                         Assert.AreEqual ("b", idx [1].Name, "#10");
270                         Assert.AreEqual (1, idx [1].Position, "#11");
271                         Assert.AreEqual (m_args [1].MetadataToken, idx [1].MetadataToken, "#12");
272                         Assert.AreEqual (ParameterAttributes.None, idx [1].Attributes, "#13");
273
274                         var idx2 = p.GetIndexParameters ();
275
276                         //No interning exposed
277                         Assert.AreNotSame (idx, idx2, "#14");
278                         Assert.AreNotSame (idx [0], idx2 [1], "#15");
279                 }
280
281                 [Test]
282                 public void GetIndexParameterReturnsObjectsBoundToTheProperty ()
283                 {
284                         RunTest (typeof (TestA), false);
285                         RunTest (typeof (TestB), true);
286                 }
287
288                 public class TestA {
289                         public int this[double a, string b] {
290                                 set {}
291                         }
292                 }
293
294                 public class TestB {
295                         public int this[double a, string b] {
296                                 get { return 1; }
297                                 set {}
298                         }
299                 }
300
301                 [Test]
302                 public void GetIndexParameterReturnedObjectsCustomAttributes () {
303                         var pa = typeof (TestC).GetProperty ("Item").GetIndexParameters () [0];
304                         Assert.IsTrue (pa.IsDefined (typeof (ParamArrayAttribute), false), "#1");
305
306                         var pb = typeof (TestD).GetProperty ("Item").GetIndexParameters () [0];
307                         Assert.IsTrue (pb.IsDefined (typeof (ParamArrayAttribute), false), "#2");
308
309                         Assert.AreEqual (1, Attribute.GetCustomAttributes (pa).Length, "#3");
310                         Assert.AreEqual (1, Attribute.GetCustomAttributes (pb).Length, "#4");
311
312                         Assert.AreEqual (0, pa.GetOptionalCustomModifiers ().Length, "#5");
313                         Assert.AreEqual (0, pb.GetRequiredCustomModifiers ().Length, "#6");
314                 }
315
316                 public class TestC {
317                         public int this[params double[] a] {
318                                 get { return 99; }
319                         }
320                 }
321
322                 public class TestD {
323                         public int this[params double[] a] {
324                                 set { }
325                         }
326                 }
327
328                 static string CreateTempAssembly ()
329                 {
330                         FileStream f = null;
331                         string path;
332                         Random rnd;
333                         int num = 0;
334
335                         rnd = new Random ();
336                         do {
337                                 num = rnd.Next ();
338                                 num++;
339                                 path = Path.Combine (Path.GetTempPath (), "tmp" + num.ToString ("x") + ".dll");
340
341                                 try {
342                                         f = new FileStream (path, FileMode.CreateNew);
343                                 } catch { }
344                         } while (f == null);
345
346                         f.Close ();
347
348
349                         return "tmp" + num.ToString ("x") + ".dll";
350                 }
351
352                 public class TestE {
353                         public int PropE {
354                                 get { return 99; }
355                         }
356                 }
357
358                 [Test]
359                 public void ConstantValue () {
360                         /*This test looks scary because we can't generate a default value with C# */
361                         var assemblyName = new AssemblyName ();
362                         assemblyName.Name = "MonoTests.System.Reflection.Emit.PropertyInfoTest";
363                         string an = CreateTempAssembly ();
364
365                         var assembly = Thread.GetDomain ().DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.RunAndSave, Path.GetTempPath ());
366                         var module = assembly.DefineDynamicModule ("module1", an);
367
368                         var tb = module.DefineType ("Test", TypeAttributes.Public);
369                         var prop = tb.DefineProperty ("Prop", PropertyAttributes.HasDefault, typeof (string), new Type [0]);
370
371                         var getter = tb.DefineMethod ("get_Prop", MethodAttributes.Public, typeof (string), new Type [0]);
372                         var ilgen = getter.GetILGenerator ();
373                         ilgen.Emit (OpCodes.Ldnull);
374                         ilgen.Emit (OpCodes.Ret);
375
376                         var setter = tb.DefineMethod ("set_Prop", MethodAttributes.Public, null, new Type [1] { typeof (string) });
377                         setter.GetILGenerator ().Emit (OpCodes.Ret);
378
379                         prop.SetConstant ("test");
380                         prop.SetGetMethod (getter);
381                         prop.SetSetMethod (setter);
382
383                         tb.CreateType ();
384
385                         File.Delete (Path.Combine (Path.GetTempPath (), an));
386                         assembly.Save (an);
387
388                         var asm = Assembly.LoadFrom (Path.Combine (Path.GetTempPath (), an));
389                         var t = asm.GetType ("Test");
390                         var p = t.GetProperty ("Prop");
391                         Assert.AreEqual ("test", p.GetConstantValue (), "#1");
392
393                         File.Delete (Path.Combine (Path.GetTempPath (), an));
394
395                         var pa = typeof (TestE).GetProperty ("PropE");
396                         try {
397                                 pa.GetConstantValue ();
398                                 Assert.Fail ("#2");
399                         } catch (InvalidOperationException) {
400                         }
401                 }
402
403 #if NET_2_0
404                 public class A<T>
405                 {
406                         public string Property {
407                                 get { return typeof (T).FullName; }
408                         }
409                 }
410
411                 public int? nullable_field;
412
413                 public int? NullableProperty {
414                         get { return nullable_field; }
415                         set { nullable_field = value; }
416                 }
417
418                 [Test]
419                 public void NullableTests ()
420                 {
421                         PropertyInfoTest t = new PropertyInfoTest ();
422
423                         PropertyInfo pi = typeof(PropertyInfoTest).GetProperty("NullableProperty");
424
425                         pi.SetValue (t, 100, null);
426                         Assert.AreEqual (100, pi.GetValue (t, null));
427                         pi.SetValue (t, null, null);
428                         Assert.AreEqual (null, pi.GetValue (t, null));
429                 }
430
431                 [Test]
432                 public void Bug77160 ()
433                 {
434                         object instance = new A<string> ();
435                         Type type = instance.GetType ();
436                         PropertyInfo property = type.GetProperty ("Property");
437                         Assert.AreEqual (typeof (string).FullName, property.GetValue (instance, null));
438                 }
439 #endif
440
441
442                 static bool HasAttribute (object [] attrs, Type attributeType)
443                 {
444                         foreach (object attr in attrs)
445                                 if (attr.GetType () == attributeType)
446                                         return true;
447                         return false;
448                 }
449
450                 static bool HasMethod (MethodInfo [] methods, string name)
451                 {
452                         foreach (MethodInfo method in methods)
453                                 if (method.Name == name)
454                                         return true;
455                         return false;
456                 }
457
458                 private class TestClass
459                 {
460                         private AttributeTargets _targets = AttributeTargets.Assembly;
461
462                         public AttributeTargets Targets {
463                                 get { return _targets; }
464                                 set { _targets = value; }
465                         }
466
467                         public string ReadOnlyProperty {
468                                 get { return string.Empty; }
469                         }
470
471                         private string Private {
472                                 get { return null; }
473                                 set { }
474                         }
475
476 #if NET_2_0
477                         public string PrivateSetter {
478                                 get { return null; }
479                                 private set { }
480                         }
481 #endif
482                 }
483         }
484 }