2 // FieldInfoTest - NUnit Test Cases for the FieldInfo class
5 // Zoltan Varga (vargaz@freemail.hu)
6 // Gert Driesen (drieseng@users.sourceforge.net)
8 // (c) 2003 Ximian, Inc. (http://www.ximian.com)
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Threading;
33 using System.Reflection;
35 using System.Reflection.Emit;
37 using System.Runtime.InteropServices;
39 using NUnit.Framework;
41 namespace MonoTests.System.Reflection
43 [StructLayout(LayoutKind.Explicit, Pack = 4, Size = 64)]
50 [StructLayout(LayoutKind.Sequential)]
53 [MarshalAsAttribute(UnmanagedType.Bool)]
56 [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)]
59 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=100)]
62 [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof (Marshal1), MarshalCookie="5")]
65 [MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal1), MarshalCookie = "5")]
72 public class Class3 : Class2
77 public class FieldInfoTest
83 public void IsDefined_AttributeType_Null ()
85 Type type = typeof (FieldInfoTest);
86 FieldInfo field = type.GetField ("i");
89 field.IsDefined ((Type) null, false);
91 } catch (ArgumentNullException ex) {
92 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
93 Assert.IsNull (ex.InnerException, "#3");
94 Assert.IsNotNull (ex.Message, "#4");
95 Assert.IsNotNull (ex.ParamName, "#5");
96 Assert.AreEqual ("attributeType", ex.ParamName, "#6");
101 public void GetCustomAttributes ()
106 fi = typeof (Class2).GetField ("f5");
108 attrs = fi.GetCustomAttributes (false);
109 Assert.AreEqual (1, attrs.Length, "#B1");
110 Assert.AreEqual (typeof (ObsoleteAttribute), attrs [0].GetType (), "#B2");
111 attrs = fi.GetCustomAttributes (true);
112 Assert.AreEqual (1, attrs.Length, "#B3");
113 Assert.AreEqual (typeof (ObsoleteAttribute), attrs [0].GetType (), "#B4");
114 attrs = fi.GetCustomAttributes (typeof (MarshalAsAttribute), false);
115 Assert.AreEqual (0, attrs.Length, "#B5");
116 attrs = fi.GetCustomAttributes (typeof (MarshalAsAttribute), true);
117 Assert.AreEqual (0, attrs.Length, "#B6");
118 attrs = fi.GetCustomAttributes (typeof (ObsoleteAttribute), false);
119 Assert.AreEqual (1, attrs.Length, "#B7");
120 Assert.AreEqual (typeof (ObsoleteAttribute), attrs [0].GetType (), "#B8");
121 attrs = fi.GetCustomAttributes (typeof (ObsoleteAttribute), true);
122 Assert.AreEqual (1, attrs.Length, "#B9");
123 Assert.AreEqual (typeof (ObsoleteAttribute), attrs [0].GetType (), "#B10");
125 fi = typeof (Class3).GetField ("f5");
127 attrs = fi.GetCustomAttributes (false);
128 Assert.AreEqual (1, attrs.Length, "#D1");
129 Assert.AreEqual (typeof (ObsoleteAttribute), attrs [0].GetType (), "#D2");
130 attrs = fi.GetCustomAttributes (true);
131 Assert.AreEqual (1, attrs.Length, "#D3");
132 Assert.AreEqual (typeof (ObsoleteAttribute), attrs [0].GetType (), "#D4");
133 attrs = fi.GetCustomAttributes (typeof (MarshalAsAttribute), false);
134 Assert.AreEqual (0, attrs.Length, "#D5");
135 attrs = fi.GetCustomAttributes (typeof (MarshalAsAttribute), true);
136 Assert.AreEqual (0, attrs.Length, "#D6");
137 attrs = fi.GetCustomAttributes (typeof (ObsoleteAttribute), false);
138 Assert.AreEqual (1, attrs.Length, "#D7");
139 Assert.AreEqual (typeof (ObsoleteAttribute), attrs [0].GetType (), "#D8");
140 attrs = fi.GetCustomAttributes (typeof (ObsoleteAttribute), true);
141 Assert.AreEqual (1, attrs.Length, "#D9");
142 Assert.AreEqual (typeof (ObsoleteAttribute), attrs [0].GetType (), "#D10");
145 [Test] // GetFieldFromHandle (RuntimeFieldHandle)
146 public void GetFieldFromHandle1_Handle_Zero ()
148 RuntimeFieldHandle fh = new RuntimeFieldHandle ();
151 FieldInfo.GetFieldFromHandle (fh);
153 } catch (ArgumentException ex) {
154 // Handle is not initialized
155 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
156 Assert.IsNull (ex.InnerException, "#3");
157 Assert.IsNotNull (ex.Message, "#4");
158 Assert.IsNull (ex.ParamName, "#5");
163 [Test] // GetFieldFromHandle (RuntimeFieldHandle, RuntimeTypeHandle)
164 public void GetFieldFromHandle2_DeclaringType_Zero ()
166 RuntimeTypeHandle th = new RuntimeTypeHandle ();
167 FieldInfo fi1 = typeof (Class2).GetField ("f5");
168 RuntimeFieldHandle fh = fi1.FieldHandle;
170 FieldInfo fi2 = FieldInfo.GetFieldFromHandle (fh, th);
171 Assert.IsNotNull (fi2, "#1");
172 Assert.AreSame (fi1.DeclaringType, fi2.DeclaringType, "#2");
173 Assert.AreEqual (fi1.FieldType, fi2.FieldType, "#3");
174 Assert.AreEqual (fi1.Name, fi2.Name, "#4");
177 [Test] // GetFieldFromHandle (RuntimeFieldHandle, RuntimeTypeHandle)
178 public void GetFieldFromHandle2_Handle_Generic ()
180 FieldInfoTest<string> instance = new FieldInfoTest<string> ();
181 Type t = instance.GetType ();
183 FieldInfo fi1 = t.GetField ("TestField");
184 RuntimeFieldHandle fh = fi1.FieldHandle;
185 RuntimeTypeHandle th = t.TypeHandle;
187 FieldInfo fi2 = FieldInfo.GetFieldFromHandle (fh, th);
188 Assert.IsNotNull (fi2, "#1");
189 Assert.AreSame (t, fi2.DeclaringType, "#2");
190 Assert.AreEqual (typeof (string), fi2.FieldType, "#3");
191 Assert.AreEqual ("TestField", fi2.Name, "#4");
194 [Test] // GetFieldFromHandle (RuntimeFieldHandle, RuntimeTypeHandle)
195 [Category ("NotWorking")]
196 [Category ("NotDotNet")] // https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=343449
197 public void GetFieldFromHandle2_Handle_GenericDefinition ()
199 Type t1 = typeof (FieldInfoTest<>);
200 FieldInfo fi1 = t1.GetField ("TestField");
201 RuntimeFieldHandle fh = fi1.FieldHandle;
203 FieldInfoTest<string> instance = new FieldInfoTest<string> ();
204 Type t2 = instance.GetType ();
205 RuntimeTypeHandle th = t2.TypeHandle;
207 FieldInfo fi2 = FieldInfo.GetFieldFromHandle (fh, th);
208 Assert.IsNotNull (fi2, "#1");
209 Assert.AreSame (t2, fi2.DeclaringType, "#2");
210 Assert.AreEqual (typeof (string), fi2.FieldType, "#3");
211 Assert.AreEqual ("TestField", fi2.Name, "#4");
214 [Test] // GetFieldFromHandle (RuntimeFieldHandle, RuntimeTypeHandle)
215 public void GetFieldFromHandle2_Handle_Zero ()
217 object instance = new Class2 ();
218 RuntimeTypeHandle th = Type.GetTypeHandle (instance);
219 RuntimeFieldHandle fh = new RuntimeFieldHandle ();
222 FieldInfo.GetFieldFromHandle (fh, th);
224 } catch (ArgumentException ex) {
225 // Handle is not initialized
226 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
227 Assert.IsNull (ex.InnerException, "#3");
228 Assert.IsNotNull (ex.Message, "#4");
229 Assert.IsNull (ex.ParamName, "#5");
234 [ExpectedException (typeof (ArgumentException))]
235 public void GetFieldFromHandle2_Incompatible ()
237 RuntimeFieldHandle fh = typeof (FieldInfoTest<int>).GetField ("TestField").FieldHandle;
239 FieldInfoTest<string> instance = new FieldInfoTest<string> ();
240 Type t2 = instance.GetType ();
241 RuntimeTypeHandle th = t2.TypeHandle;
243 FieldInfo fi2 = FieldInfo.GetFieldFromHandle (fh, th);
248 public void PseudoCustomAttributes ()
251 Type t = typeof (FieldInfoTest);
254 Assert.AreEqual (1, t.GetField ("i").GetCustomAttributes (typeof (NonSerializedAttribute), true).Length);
256 Assert.AreEqual (0, t.GetField ("i").GetCustomAttributes (typeof (NonSerializedAttribute), true).Length);
259 attrs = typeof (Class1).GetField ("i").GetCustomAttributes (true);
261 Assert.AreEqual (1, attrs.Length, "#B1");
262 FieldOffsetAttribute field_attr = (FieldOffsetAttribute) attrs [0];
263 Assert.AreEqual (32, field_attr.Value, "#B2");
265 Assert.AreEqual (0, attrs.Length, "#B1");
268 MarshalAsAttribute attr;
270 attrs = typeof (Class2).GetField ("f0").GetCustomAttributes (true);
272 Assert.AreEqual (1, attrs.Length, "#C1");
273 attr = (MarshalAsAttribute) attrs [0];
274 Assert.AreEqual (UnmanagedType.Bool, attr.Value, "#C2");
276 Assert.AreEqual (0, attrs.Length, "#C1");
279 attrs = typeof (Class2).GetField ("f1").GetCustomAttributes (true);
281 Assert.AreEqual (1, attrs.Length, "#D1");
282 attr = (MarshalAsAttribute) attrs [0];
283 Assert.AreEqual (UnmanagedType.LPArray, attr.Value, "#D2");
284 Assert.AreEqual (UnmanagedType.LPStr, attr.ArraySubType, "#D3");
286 Assert.AreEqual (0, attrs.Length, "#D1");
289 attrs = typeof (Class2).GetField ("f2").GetCustomAttributes (true);
291 Assert.AreEqual (1, attrs.Length, "#E1");
292 attr = (MarshalAsAttribute) attrs [0];
293 Assert.AreEqual (UnmanagedType.ByValTStr, attr.Value, "#E2");
294 Assert.AreEqual (100, attr.SizeConst, "#E3");
296 Assert.AreEqual (0, attrs.Length, "#E1");
299 attrs = typeof (Class2).GetField ("f3").GetCustomAttributes (true);
301 Assert.AreEqual (1, attrs.Length, "#F1");
302 attr = (MarshalAsAttribute) attrs [0];
303 Assert.AreEqual (UnmanagedType.CustomMarshaler, attr.Value, "#F2");
304 Assert.AreEqual ("5", attr.MarshalCookie, "#F3");
305 Assert.AreEqual (typeof (Marshal1), Type.GetType (attr.MarshalType), "#F4");
307 Assert.AreEqual (0, attrs.Length, "#F1");
310 attrs = typeof (Class3).GetField ("f3").GetCustomAttributes (false);
312 Assert.AreEqual (1, attrs.Length, "#G1");
313 attr = (MarshalAsAttribute) attrs [0];
314 Assert.AreEqual (UnmanagedType.CustomMarshaler, attr.Value, "#G2");
315 Assert.AreEqual ("5", attr.MarshalCookie, "#G3");
316 Assert.AreEqual (typeof (Marshal1), Type.GetType (attr.MarshalType), "#G4");
318 Assert.AreEqual (0, attrs.Length, "#G1");
321 attrs = typeof (Class3).GetField ("f3").GetCustomAttributes (true);
323 Assert.AreEqual (1, attrs.Length, "#H1");
324 attr = (MarshalAsAttribute) attrs [0];
325 Assert.AreEqual (UnmanagedType.CustomMarshaler, attr.Value, "#H2");
326 Assert.AreEqual ("5", attr.MarshalCookie, "#H3");
327 Assert.AreEqual (typeof (Marshal1), Type.GetType (attr.MarshalType), "#H4");
329 Assert.AreEqual (0, attrs.Length, "#H1");
333 attrs = typeof (Class2).GetField ("f3").GetCustomAttributes (true);
335 Assert.AreEqual (1, attrs.Length, "#I1");
336 attr = (MarshalAsAttribute) attrs [0];
337 Assert.AreEqual (UnmanagedType.CustomMarshaler, attr.Value, "#I2");
338 Assert.AreEqual ("5", attr.MarshalCookie, "#I3");
339 Assert.AreEqual (typeof (Marshal1), Type.GetType (attr.MarshalType), "#I4");
341 Assert.AreEqual (0, attrs.Length, "#I1");
346 public static int static_field;
350 [ExpectedException (typeof (ArgumentException))]
351 public void GetValueWrongObject ()
355 typeof (Foo).GetField ("field").GetValue (typeof (int));
358 public void GetValueWrongObjectStatic ()
362 // This is allowed in MS.NET
363 typeof (Foo).GetField ("static_field").GetValue (typeof (int));
367 #if !TARGET_JVM // ReflectionOnlyLoad not supported for TARGET_JVM
369 [ExpectedException (typeof (InvalidOperationException))]
370 public void GetValueOnRefOnlyAssembly ()
372 Assembly assembly = Assembly.ReflectionOnlyLoad (typeof (FieldInfoTest).Assembly.FullName);
373 Type t = assembly.GetType (typeof (RefOnlyFieldClass).FullName);
374 FieldInfo f = t.GetField ("RefOnlyField", BindingFlags.Static | BindingFlags.NonPublic);
379 [ExpectedException (typeof (InvalidOperationException))]
380 public void SetValueOnRefOnlyAssembly ()
382 Assembly assembly = Assembly.ReflectionOnlyLoad (typeof (FieldInfoTest).Assembly.FullName);
383 Type t = assembly.GetType (typeof (RefOnlyFieldClass).FullName);
384 FieldInfo f = t.GetField ("RefOnlyField", BindingFlags.Static | BindingFlags.NonPublic);
385 f.SetValue (null, 8);
389 const int literal = 42;
392 [ExpectedException (typeof (FieldAccessException))]
393 public void SetValueOnLiteralField ()
395 FieldInfo f = typeof (FieldInfoTest).GetField ("literal", BindingFlags.Static | BindingFlags.NonPublic);
396 f.SetValue (null, 0);
399 public int? nullable_field;
401 public static int? static_nullable_field;
404 public void NullableTests ()
406 FieldInfoTest t = new FieldInfoTest ();
408 FieldInfo fi = typeof (FieldInfoTest).GetField ("nullable_field");
410 fi.SetValue (t, 101);
411 Assert.AreEqual (101, fi.GetValue (t));
412 fi.SetValue (t, null);
413 Assert.AreEqual (null, fi.GetValue (t));
415 FieldInfo fi2 = typeof (FieldInfoTest).GetField ("static_nullable_field");
417 fi2.SetValue (t, 101);
418 Assert.AreEqual (101, fi2.GetValue (t));
419 fi2.SetValue (t, null);
420 Assert.AreEqual (null, fi2.GetValue (t));
423 #if !TARGET_JVM // TypeBuilder not supported for TARGET_JVM
425 public void NonPublicTests ()
427 Assembly assembly = Assembly.ReflectionOnlyLoad (typeof (FieldInfoTest).Assembly.FullName);
429 Type t = assembly.GetType (typeof (NonPublicFieldClass).FullName);
431 // try to get non-public field
432 FieldInfo fi = t.GetField ("protectedField");
435 fi = t.GetField ("protectedField", BindingFlags.NonPublic | BindingFlags.Instance);
436 Assert.IsNotNull (fi);
441 public void GetRawDefaultValue ()
443 Assert.AreEqual (5, typeof (FieldInfoTest).GetField ("int_field").GetRawConstantValue ());
444 Assert.AreEqual (Int64.MaxValue, typeof (FieldInfoTest).GetField ("long_field").GetRawConstantValue ());
445 Assert.AreEqual (2, typeof (FieldInfoTest).GetField ("int_enum_field").GetRawConstantValue ());
446 Assert.AreEqual (typeof (int), typeof (FieldInfoTest).GetField ("int_enum_field").GetRawConstantValue ().GetType ());
447 Assert.AreEqual (2, typeof (FieldInfoTest).GetField ("long_enum_field").GetRawConstantValue ());
448 Assert.AreEqual (typeof (long), typeof (FieldInfoTest).GetField ("long_enum_field").GetRawConstantValue ().GetType ());
449 Assert.AreEqual ("Hello", typeof (FieldInfoTest).GetField ("string_field").GetRawConstantValue ());
450 Assert.AreEqual (null, typeof (FieldInfoTest).GetField ("object_field").GetRawConstantValue ());
454 [ExpectedException (typeof (InvalidOperationException))]
455 public void GetRawDefaultValueNoDefault ()
457 typeof (FieldInfoTest).GetField ("non_const_field").GetRawConstantValue ();
461 [ExpectedException (typeof (InvalidOperationException))]
462 public void GetValueOpenGeneric ()
464 typeof(Foo<>).GetField ("field").GetValue (null);
468 [ExpectedException (typeof (InvalidOperationException))]
469 public void SetValueOpenGeneric ()
471 typeof(Foo<>).GetField ("field").SetValue (null, 0);
475 public void GetValueOnConstantOfOpenGeneric ()
477 Assert.AreEqual (10, typeof(Foo<>).GetField ("constant").GetValue (null), "#1");
478 Assert.AreEqual ("waa", typeof(Foo<>).GetField ("sconstant").GetValue (null), "#2");
479 Assert.AreEqual (IntEnum.Third, typeof(Foo<>).GetField ("econstant").GetValue (null), "#3");
485 The whole point of this field is to make sure we don't create the vtable layout
486 when loading the value of constants for Foo<>. See bug #594942.
490 public static int field;
491 public const int constant = 10;
492 public const string sconstant = "waa";
493 public const IntEnum econstant = IntEnum.Third;
496 public enum IntEnum {
502 public enum LongEnum : long {
508 public const int int_field = 5;
509 public const long long_field = Int64.MaxValue;
510 public const IntEnum int_enum_field = IntEnum.Second;
511 public const LongEnum long_enum_field = LongEnum.Second;
512 public const string string_field = "Hello";
513 public const FieldInfoTest object_field = null;
514 public int non_const_field;
521 class RefOnlyFieldClass
524 static int RefOnlyField;
527 class NonPublicFieldClass
529 protected int protectedField;
532 public class FieldInfoTest<T>