2 // PropertyInfoTest.cs - NUnit Test Cases for PropertyInfo
5 // Gert Driesen (drieseng@users.sourceforge.net)
7 // (C) 2004-2007 Gert Driesen
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
31 using System.Reflection;
32 using System.Runtime.InteropServices;
33 using System.Threading;
35 using System.Reflection.Emit;
39 using NUnit.Framework;
41 namespace MonoTests.System.Reflection
44 public class PropertyInfoTest
47 public void GetAccessorsTest ()
49 Type type = typeof (TestClass);
50 PropertyInfo property = type.GetProperty ("ReadOnlyProperty");
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");
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");
62 property = typeof (Base).GetProperty ("P");
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");
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");
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");
85 property = typeof (TestClass).GetProperty ("Private",
86 BindingFlags.NonPublic | BindingFlags.Instance);
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");
95 methods = property.GetAccessors (false);
96 Assert.AreEqual (0, methods.Length, "#G");
98 methods = property.GetAccessors ();
99 Assert.AreEqual (0, methods.Length, "#H");
101 property = typeof (TestClass).GetProperty ("PrivateSetter");
103 methods = property.GetAccessors (true);
104 Assert.AreEqual (2, methods.Length, "#H1");
105 Assert.IsNotNull (methods [0], "#H2");
106 Assert.IsNotNull (methods [1], "#H3");
107 Assert.IsTrue (HasMethod (methods, "get_PrivateSetter"), "#H4");
108 Assert.IsTrue (HasMethod (methods, "set_PrivateSetter"), "#H5");
110 methods = property.GetAccessors (false);
111 Assert.AreEqual (1, methods.Length, "#I1");
112 Assert.IsNotNull (methods [0], "#I2");
113 Assert.AreEqual ("get_PrivateSetter", methods [0].Name, "#I3");
115 methods = property.GetAccessors ();
116 Assert.AreEqual (1, methods.Length, "#J1");
117 Assert.IsNotNull (methods [0], "#J2");
118 Assert.AreEqual ("get_PrivateSetter", methods [0].Name, "#J3");
122 public void GetCustomAttributes ()
125 PropertyInfo p = typeof (Base).GetProperty ("P");
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");
134 p = typeof (Base).GetProperty ("T");
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");
145 p = typeof (Base).GetProperty ("Z");
147 attrs = p.GetCustomAttributes (false);
148 Assert.AreEqual (0, attrs.Length, "#C1");
149 attrs = p.GetCustomAttributes (true);
150 Assert.AreEqual (0, attrs.Length, "#C2");
154 public void GetCustomAttributes_Inherited ()
157 PropertyInfo p = typeof (Derived).GetProperty ("P");
159 attrs = p.GetCustomAttributes (false);
160 Assert.AreEqual (0, attrs.Length, "#A1");
161 attrs = p.GetCustomAttributes (true);
162 Assert.AreEqual (0, attrs.Length, "#A3");
164 p = typeof (Derived).GetProperty ("T");
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");
175 p = typeof (Derived).GetProperty ("Z");
177 attrs = p.GetCustomAttributes (false);
178 Assert.AreEqual (0, attrs.Length, "#C1");
179 attrs = p.GetCustomAttributes (true);
180 Assert.AreEqual (0, attrs.Length, "#C2");
184 public void IsDefined_AttributeType_Null ()
186 Type derived = typeof (Derived);
187 PropertyInfo pi = derived.GetProperty ("P");
190 pi.IsDefined ((Type) null, false);
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");
202 public void AccessorsReflectedType ()
204 PropertyInfo pi = typeof (Derived).GetProperty ("T");
205 Assert.AreEqual (typeof (Derived), pi.GetGetMethod ().ReflectedType);
206 Assert.AreEqual (typeof (Derived), pi.GetSetMethod ().ReflectedType);
209 [Test] // bug #399985
210 public void SetValue_Enum ()
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");
220 public class ThisAttribute : Attribute
227 public virtual string P {
234 public virtual string T {
239 public virtual string Z {
247 public override string P {
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 ();
258 Assert.AreEqual (2, idx.Length, "#1");
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");
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");
274 var idx2 = p.GetIndexParameters ();
276 //No interning exposed
277 Assert.AreNotSame (idx, idx2, "#14");
278 Assert.AreNotSame (idx [0], idx2 [1], "#15");
282 public void GetIndexParameterReturnsObjectsBoundToTheProperty ()
284 RunTest (typeof (TestA), false);
285 RunTest (typeof (TestB), true);
289 public int this[double a, string b] {
295 public int this[double a, string b] {
302 public void GetIndexParameterReturnedObjectsCustomAttributes () {
303 var pa = typeof (TestC).GetProperty ("Item").GetIndexParameters () [0];
304 Assert.IsTrue (pa.IsDefined (typeof (ParamArrayAttribute), false), "#1");
306 var pb = typeof (TestD).GetProperty ("Item").GetIndexParameters () [0];
307 Assert.IsTrue (pb.IsDefined (typeof (ParamArrayAttribute), false), "#2");
309 Assert.AreEqual (1, Attribute.GetCustomAttributes (pa).Length, "#3");
310 Assert.AreEqual (1, Attribute.GetCustomAttributes (pb).Length, "#4");
312 Assert.AreEqual (0, pa.GetOptionalCustomModifiers ().Length, "#5");
313 Assert.AreEqual (0, pb.GetRequiredCustomModifiers ().Length, "#6");
317 public int this[params double[] a] {
323 public int this[params double[] a] {
328 static string CreateTempAssembly ()
339 path = Path.Combine (Path.GetTempPath (), "tmp" + num.ToString ("x") + ".dll");
342 f = new FileStream (path, FileMode.CreateNew);
349 return "tmp" + num.ToString ("x") + ".dll";
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 ();
365 var assembly = Thread.GetDomain ().DefineDynamicAssembly (assemblyName, AssemblyBuilderAccess.RunAndSave, Path.GetTempPath ());
366 var module = assembly.DefineDynamicModule ("module1", an);
368 var tb = module.DefineType ("Test", TypeAttributes.Public);
369 var prop = tb.DefineProperty ("Prop", PropertyAttributes.HasDefault, typeof (string), new Type [0]);
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);
376 var setter = tb.DefineMethod ("set_Prop", MethodAttributes.Public, null, new Type [1] { typeof (string) });
377 setter.GetILGenerator ().Emit (OpCodes.Ret);
379 prop.SetConstant ("test");
380 prop.SetGetMethod (getter);
381 prop.SetSetMethod (setter);
385 File.Delete (Path.Combine (Path.GetTempPath (), an));
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");
393 File.Delete (Path.Combine (Path.GetTempPath (), an));
395 var pa = typeof (TestE).GetProperty ("PropE");
397 pa.GetConstantValue ();
399 } catch (InvalidOperationException) {
406 public string Property {
407 get { return typeof (T).FullName; }
411 public int? nullable_field;
413 public int? NullableProperty {
414 get { return nullable_field; }
415 set { nullable_field = value; }
419 public void NullableTests ()
421 PropertyInfoTest t = new PropertyInfoTest ();
423 PropertyInfo pi = typeof(PropertyInfoTest).GetProperty("NullableProperty");
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));
432 public void Bug77160 ()
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));
441 public void ToStringTest ()
443 var pa = typeof (TestC).GetProperty ("Item");
444 Assert.AreEqual ("Int32 Item [Double[]]", pa.ToString ());
447 static bool HasAttribute (object [] attrs, Type attributeType)
449 foreach (object attr in attrs)
450 if (attr.GetType () == attributeType)
455 static bool HasMethod (MethodInfo [] methods, string name)
457 foreach (MethodInfo method in methods)
458 if (method.Name == name)
463 private class TestClass
465 private AttributeTargets _targets = AttributeTargets.Assembly;
467 public AttributeTargets Targets {
468 get { return _targets; }
469 set { _targets = value; }
472 public string ReadOnlyProperty {
473 get { return string.Empty; }
476 private string Private {
481 public string PrivateSetter {
487 [Test] // bug #633671
488 public void DeclaringTypeOfPropertyFromInheritedTypePointsToBase ()
490 var inherit1 = typeof(InheritsFromClassWithNullableDateTime);
491 var siblingProperty = inherit1.GetProperty("Property1");
493 Assert.AreEqual (typeof (ClassWithNullableDateTime), siblingProperty.DeclaringType, "#1");
494 Assert.AreEqual (typeof (InheritsFromClassWithNullableDateTime), siblingProperty.ReflectedType, "#2");
496 //The check is done twice since the bug is related to getting those 2 properties multiple times.
497 Assert.AreEqual (typeof (ClassWithNullableDateTime), siblingProperty.DeclaringType, "#3");
498 Assert.AreEqual (typeof (InheritsFromClassWithNullableDateTime), siblingProperty.ReflectedType, "#4");
502 public class ClassWithNullableDateTime
504 public DateTime? Property1 { get; set; }
507 public class InheritsFromClassWithNullableDateTime : ClassWithNullableDateTime
511 public static int ThrowingProperty {
513 throw new ObjectDisposedException("TestClass");
518 public void GetException () {
519 var prop = typeof(PropertyInfoTest).GetProperty("ThrowingProperty");
521 prop.GetValue (null, null);
523 } catch (TargetInvocationException ex) {
524 Assert.IsTrue (ex.InnerException is ObjectDisposedException);
528 public class DefaultValueTest
530 public string this[int val, string param = "test"]
532 get{ return val + param; }
538 public void PropertyWithDefaultValue ()
540 var parameters = typeof (DefaultValueTest).GetProperty ("Item").GetIndexParameters ();
541 var defaultParam = parameters[parameters.Length - 1];
542 Assert.AreEqual ("param", defaultParam.Name, "#1");
543 Assert.AreEqual ("test", defaultParam.DefaultValue, "#2");