New test.
[mono.git] / mcs / class / corlib / Test / System.Reflection / BinderTests.cs
1 //
2 // System.Reflection.BinderTests - Tests Type.DefaultBinder
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (c) 2004 Novell, Inc. (http://www.novell.com)
8 //
9
10 using NUnit.Framework;
11 using System;
12 using System.IO;
13 using System.Reflection;
14
15 namespace MonoTests.System.Reflection
16 {
17         enum MyEnum {
18                 Zero,
19                 One,
20                 Two
21         }
22         
23         class SampleClass {
24                 public static void SampleMethod (object o) { }
25
26                 public Type this[decimal i] {
27                         get { return i.GetType (); }
28                 }
29
30                 public Type this[object i] {
31                         get { return i.GetType (); }
32                 }
33
34         }
35         
36         class SingleIndexer {
37                 public Type this [int i] {
38                         get { return i.GetType (); }
39                 }
40         }
41         
42         class MultiIndexer
43         {
44                 public Type this[byte i] {
45                         get { return i.GetType (); }
46                 }
47
48                 public Type this[sbyte i] {
49                         get { return i.GetType (); }
50                 }
51
52                 public Type this[short i] {
53                         get { return i.GetType (); }
54                 }
55
56                 public Type this[ushort i] {
57                         get { return i.GetType (); }
58                 }
59
60                 public Type this[int i] {
61                         get { return i.GetType (); }
62                 }
63
64                 public Type this[uint i] {
65                         get { return i.GetType (); }
66                 }
67
68                 public Type this[long i] {
69                         get { return i.GetType (); }
70                 }
71
72                 public Type this[ulong i] {
73                         get { return i.GetType (); }
74                 }
75
76                 public Type this[float i] {
77                         get { return i.GetType (); }
78                 }
79
80                 public Type this[double i] {
81                         get { return i.GetType (); }
82                 }
83
84                 public Type this[decimal i] {
85                         get { return i.GetType (); }
86                 }
87
88                 public Type this[object i] {
89                         get { return i.GetType (); }
90                 }
91
92                 public Type this[Enum i] {
93                         get { return i.GetType (); }
94                 }
95         }
96
97         [TestFixture]
98         public class BinderTest
99         {
100                 Binder binder = Type.DefaultBinder;
101
102                 [Test]
103                 [ExpectedException (typeof (ArgumentException))]
104                 public void SelectPropertyTestNull1 ()
105                 {
106                         // The second argument is the one
107                         binder.SelectProperty (0, null, null, null, null);
108                 }
109
110                 [Test]
111                 [ExpectedException (typeof (ArgumentException))]
112                 public void SelectPropertyTestEmpty ()
113                 {
114                         // The second argument is the one
115                         binder.SelectProperty (0, new PropertyInfo [] {}, null, null, null);
116                 }
117
118                 [Test]
119                 [ExpectedException (typeof (AmbiguousMatchException))]
120                 public void AmbiguousProperty1 () // Bug 58381
121                 {
122                         Type type = typeof (MultiIndexer);
123                         PropertyInfo pi = type.GetProperty ("Item");
124                 }
125
126                 [Test]
127                 public void SelectAndInvokeAllProperties1 ()
128                 {
129                         Type type = typeof (MultiIndexer);
130                         PropertyInfo [] props = type.GetProperties (BindingFlags.DeclaredOnly |
131                                                                     BindingFlags.Public |
132                                                                     BindingFlags.Instance);
133
134                         // These don't cause an AmbiguousMatchException
135                         Type [] types = { typeof (byte), typeof (short),
136                                           typeof (int), typeof (long),
137                                           typeof (MyEnum) };
138
139                         /* MS matches short for sbyte!!! */
140                         /* MS matches int for ushort!!! */
141                         /* MS matches long for uint!!! */
142                         /** These do weird things under MS if used together and then in separate arrays *
143                         Type [] types = { typeof (ulong), typeof (float), typeof (double),
144                                           typeof (decimal), typeof (object) };
145                         */
146
147                         MultiIndexer obj = new MultiIndexer ();
148
149                         foreach (Type t in types) {
150                                 PropertyInfo prop = null;
151                                 try {
152                                         prop = binder.SelectProperty (0, props, null, new Type [] {t}, null);
153                                 } catch (Exception e) {
154                                         throw new Exception ("Type: " + t, e);
155                                 }
156                                 Type gotten = (Type) prop.GetValue (obj, new object [] {Activator.CreateInstance (t)});
157                                 Assert.AreEqual (t, gotten);
158                         }
159                 }
160
161                 [Test]
162                 public void SelectAndInvokeAllProperties2 ()
163                 {
164                         Type type = typeof (MultiIndexer);
165                         PropertyInfo [] props = type.GetProperties (BindingFlags.DeclaredOnly |
166                                                                     BindingFlags.Public |
167                                                                     BindingFlags.Instance);
168
169                         Type [] types = { typeof (ushort), typeof (char) };
170
171                         MultiIndexer obj = new MultiIndexer ();
172                         PropertyInfo prop1 = binder.SelectProperty (0, props, null, new Type [] {types [0]}, null);
173                         PropertyInfo prop2 = binder.SelectProperty (0, props, null, new Type [] {types [1]}, null);
174                         Assert.AreEqual (prop1, prop2);
175                 }
176
177                 [Test]
178                 public void Select1Match2 ()
179                 {
180                         Type type = typeof (SingleIndexer);
181                         PropertyInfo [] props = type.GetProperties (BindingFlags.DeclaredOnly |
182                                                                     BindingFlags.Public |
183                                                                     BindingFlags.Instance);
184                         PropertyInfo prop = binder.SelectProperty (0, props, null, new Type [0], null);
185                         Assert.IsNull (prop, "empty");
186                 }
187                 
188                 [Test]
189                 public void Select1Match ()
190                 {
191                         Type type = typeof (SingleIndexer);
192                         PropertyInfo [] props = type.GetProperties (BindingFlags.DeclaredOnly |
193                                                                     BindingFlags.Public |
194                                                                     BindingFlags.Instance);
195
196                         PropertyInfo prop;
197                         
198                         prop = binder.SelectProperty (0, props, null, new Type [] { typeof (long) }, null);
199                         Assert.IsNull (prop, "long");
200                         prop = binder.SelectProperty (0, props, null, new Type [] { typeof (int) }, null);
201                         Assert.IsNotNull (prop, "int");
202                         prop = binder.SelectProperty (0, props, null, new Type [] { typeof (short) }, null);
203                         Assert.IsNotNull (prop, "short");
204                 }
205
206                 [Test]
207                 public void ArgNullOnMethod () // see bug 58846. We throwed nullref here.
208                 {
209                         Type type = typeof (SampleClass);
210                         BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod;
211                         type.InvokeMember ("SampleMethod", flags, null, null, new object[] { null });
212                 }
213
214                 [Test]
215                 public void ArgNullOnProperty ()
216                 {
217                         Type type = typeof (SampleClass);
218                         PropertyInfo [] props = type.GetProperties (BindingFlags.DeclaredOnly |
219                                                                     BindingFlags.Public |
220                                                                     BindingFlags.Instance);
221
222                         PropertyInfo prop = binder.SelectProperty (0, props, null, new Type [] {null}, null);
223                         Assert.IsNotNull (prop);
224                 }
225
226                 [Test] // bug #41691
227                 public void BindToMethodNamedArgs ()
228                 {
229                         Type t = typeof (Bug41691);
230
231                         StringWriter sw = new StringWriter ();
232                         sw.NewLine = "\n";
233
234                         object[] argValues = new object [] {"Hello", "World", "Extra", sw};
235                         string [] argNames = new string [] {"firstName", "lastName"};
236
237                         t.InvokeMember ("PrintName",
238                                         BindingFlags.InvokeMethod,
239                                         null,
240                                         null,
241                                         argValues,
242                                         null,
243                                         null,
244                                         argNames);
245
246                         Assert.AreEqual ("Hello\nExtra\nWorld\n", sw.ToString ());
247                 }
248
249                 public class Bug41691
250                 {
251                         public static void PrintName (string lastName, string firstName, string extra, TextWriter output)
252                         {
253                                 output.WriteLine (firstName);
254                                 output.WriteLine (extra);
255                                 output.WriteLine (lastName);
256                         }
257                 }
258
259                 [Test] // bug #42457
260                 public void GetMethodAmbiguity ()
261                 {
262                         object IntegerObject = 5;
263                         object IntArrayObject = new int[] {5, 2, 5};
264                         object StringArrayObject = new string [] {"One", "Two"};
265                         object [] IntParam = new object [] {IntegerObject};
266                         object [] IntArrayParam = new object [] {IntArrayObject};
267                         object [] StringArrayParam = new object [] {StringArrayObject};
268
269                         object be = this;
270                         Type betype = this.GetType ();
271
272                         string name1 = "Bug42457Method";
273                         string name2 = "Bug42457Method2";
274
275                         MethodInfo mi_obj = betype.GetMethod (name1, Type.GetTypeArray (IntParam));
276                         mi_obj.Invoke (be, IntParam);
277                         Assert.AreEqual (1, bug42457, "#1");
278                         MethodInfo mi_arr = betype.GetMethod (name1, Type.GetTypeArray (IntArrayParam));
279                         mi_arr.Invoke (be, IntArrayParam);
280                         Assert.AreEqual (2, bug42457, "#2");
281                         MethodInfo mi_str = betype.GetMethod (name1, Type.GetTypeArray (StringArrayParam));
282                         mi_str.Invoke (be, StringArrayParam);
283                         Assert.AreEqual (3, bug42457, "#3");
284
285                         MethodInfo m2_obj = betype.GetMethod (name2, Type.GetTypeArray (IntParam));
286                         m2_obj.Invoke (be, IntParam);
287                         Assert.AreEqual (1, bug42457_2, "#4");
288                         MethodInfo m2_arr = betype.GetMethod (name2, Type.GetTypeArray (IntArrayParam));
289                         m2_arr.Invoke (be, IntArrayParam);
290                         Assert.AreEqual (2, bug42457_2, "#5");
291                         MethodInfo m2_str = betype.GetMethod (name2, Type.GetTypeArray(StringArrayParam));
292                         m2_str.Invoke (be, StringArrayParam);
293                         Assert.AreEqual (3, bug42457_2, "#6");
294                 }
295
296                 static void MethodWithLongParam(long param)
297                 {
298                 }
299
300                 [Test]
301                 public void TestExactBinding ()
302                 {
303                         Type[] types = new Type[] { typeof(int) };
304                         Assert.AreEqual (null, typeof (BinderTest).GetMethod("MethodWithLongParam", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.ExactBinding,  null, types, null));
305                 }
306
307                 public void Bug42457Method (object thing)
308                 {
309                         bug42457 = 1;
310                 }
311
312                 public void Bug42457Method (Array thing)
313                 {
314                         bug42457 = 2;
315                 }
316
317                 public void Bug42457Method (string [] thing)
318                 {
319                         bug42457 = 3;
320                 }
321
322                 public void Bug42457Method2 (object thing)
323                 {
324                         bug42457_2 = 1;
325                 }
326
327                 public void Bug42457Method2 (Array thing)
328                 {
329                         bug42457_2 = 2;
330                 }
331
332                 public void Bug42457Method2 (string [] thing)
333                 {
334                         bug42457_2 = 3;
335                 }
336
337                 int bug42457, bug42457_2;
338
339                 [Test] // bug #77079
340                 public void GetMethodAvoidAmbiguity2 ()
341                 {
342                         Type tType = this.GetType ();
343                         Bug77079A a = new Bug77079C ();
344
345                         tType.InvokeMember ("Bug77079",
346                                 BindingFlags.Public | BindingFlags.InvokeMethod | 
347                                 BindingFlags.Instance,
348                                 null, this, new object[] {a});
349                         Assert.AreEqual (2, bug77079);
350                 }
351
352                 int bug77079;
353
354                 public void Bug77079 (Bug77079A a)
355                 {
356                         bug77079 = 1;
357                 }
358
359                 public void Bug77079 (Bug77079B a)
360                 {
361                         bug77079 = 2;
362                 }
363
364                 public class Bug77079A
365                 {
366                 }
367
368                 public class Bug77079B : Bug77079A
369                 {
370                 }
371
372                 public class Bug77079C : Bug77079B
373                 {
374                 }
375         }
376 }
377