2009-06-06 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / Managed.Windows.Forms / Test / System.Windows.Forms / ListBindingHelperTest.cs
1 //
2 // ListBindingHelperTest.cs: Test cases for ListBindingHelper class.
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23 // Author:
24 //      Carlos Alberto Cortez <calberto.cortez@gmail.com>
25 //
26 // (C) 2008 Novell, Inc. (http://www.novell.com)
27 //
28
29 #if NET_2_0
30
31 using System;
32 using System.ComponentModel;
33 using System.Collections;
34 using System.Collections.Specialized;
35 using System.Collections.Generic;
36 using System.Data;
37 using System.Windows.Forms;
38
39 using NUnit.Framework;
40
41 namespace MonoTests.System.Windows.Forms
42 {
43         [TestFixture]
44         public class ListBindingHelperTest : TestHelper
45         {
46                 [Test]
47                 public void GetListTest ()
48                 {
49                         ListSource lsource = new ListSource (true);
50                         Stack stack = new Stack ();
51                         stack.Push (3);
52
53                         Assert.IsTrue (ListBindingHelper.GetList (lsource) is SimpleItem [], "#A1");
54                         Assert.AreEqual ("NonList", ListBindingHelper.GetList ("NonList"), "#A2");
55                         Assert.AreEqual (null, ListBindingHelper.GetList (null), "#A3");
56                         Assert.AreEqual (stack, ListBindingHelper.GetList (stack), "#A4"); // IEnumerable
57
58                         Assert.IsTrue (ListBindingHelper.GetList (lsource, String.Empty) is SimpleItem [], "#B1");
59                         Assert.AreEqual ("NonList", ListBindingHelper.GetList ("NonList", String.Empty), "#B2");
60                         Assert.AreEqual (null, ListBindingHelper.GetList (null, "DontExist"), "#B3");
61                         Assert.IsTrue (ListBindingHelper.GetList (lsource, null) is SimpleItem [], "#B4");
62
63                         ListContainer list_container = new ListContainer ();
64                         Assert.AreEqual (new object [0], ListBindingHelper.GetList (list_container, "List"), "#C1");
65
66                         // Even if IListSource.ContainsListCollection is false, we return the result of GetList ()
67                         lsource = new ListSource (false);
68                         Assert.IsTrue (ListBindingHelper.GetList (lsource) is SimpleItem [], "#D1");
69
70                         // DataMember is not if IList type
71                         Assert.AreEqual (new SimpleItem (), ListBindingHelper.GetList (list_container, "NonList"), "#E1");
72
73                         // List (IEnumerable)
74                         stack.Clear ();
75                         stack.Push (new SimpleItem (3));
76                         stack.Push (new SimpleItem (7));
77                         object obj = ListBindingHelper.GetList (stack, "Value");
78                         Assert.IsTrue (obj != null, "#F1");
79                         Assert.IsTrue (obj is int, "#F2");
80                         Assert.AreEqual (7, (int) obj, "#F3");
81
82                         // ListSource returning an IEnumerable,
83                         // which in turn retrieves dataMember
84                         obj = ListBindingHelper.GetList (lsource, "Value");
85                         Assert.IsTrue (obj != null, "#G1");
86                         Assert.IsTrue (obj is int, "#G2");
87                         Assert.AreEqual (0, (int)obj, "#G3");
88
89                         // Empty IEnumerable - valid property for list item type
90                         // Since it's empty, it needs to check whether the datamember is
91                         // a valid value, and thus we need the datasource to also be IList
92                         // Then we need a parameterized IEnumerable, which returns null.
93                         // *Observation: if it is empty and it doesn't implement IList,
94                         // it doesn't have a way to get the properties, and will throw an exc
95                         StringCollection str_coll = new StringCollection ();
96                         obj = ListBindingHelper.GetList (str_coll, "Length");
97                         Assert.IsNull (obj, "#H1");
98
99                         // IEnumerable that returns instances of ICustomTypeDescriptor
100                         // Use DataTable as source, which returns, when enumerating,
101                         // instances of DataRowView, which in turn implement ICustomTypeDescriptor
102                         DataTable table = new DataTable ();
103                         table.Columns.Add ("Id", typeof (int));
104                         table.Rows.Add (666);
105                         object l = ListBindingHelper.GetList (table, "Id");
106                         Assert.AreEqual (666, l, "#J1");
107
108                         try {
109                                 ListBindingHelper.GetList (list_container, "DontExist");
110                                 Assert.Fail ("#EXC1");
111                         } catch (ArgumentException) {
112                         }
113
114                         // Empty IEnumerable not implementing IList
115                         // Don't have a way to know whether at least datamember is valid or not.
116                         try {
117                                 stack.Clear ();
118                                 obj = ListBindingHelper.GetList (stack, "Value");
119                                 Assert.Fail ("#EXC3");
120                         } catch (ArgumentException) {
121                         }
122
123                 }
124
125                 internal class ListSource : IListSource
126                 {
127                         bool contains_collection;
128
129                         public ListSource (bool containsCollection)
130                         {
131                                 contains_collection = containsCollection;
132                         }
133
134                         public bool ContainsListCollection {
135                                 get {
136                                         return contains_collection;
137                                 }
138                         }
139
140                         public IList GetList ()
141                         {
142                                 return new SimpleItem [] { new SimpleItem () };
143                         }
144                 }
145
146                 class SuperContainer
147                 {
148                         public ListContainer ListContainer
149                         {
150                                 get
151                                 {
152                                         return new ListContainer ();
153                                 }
154                         }
155                 }
156
157                 class ListContainer
158                 {
159                         public IList List {
160                                 get {
161                                         return new SimpleItem [0];
162                                 }
163                         }
164
165                         public SimpleItem NonList {
166                                 get {
167                                         return new SimpleItem ();
168                                 }
169                         }
170                 }
171
172                 class SimpleItem
173                 {
174                         int value;
175
176                         public SimpleItem ()
177                         {
178                         }
179
180                         public SimpleItem (int value)
181                         {
182                                 this.value = value;
183                         }
184
185                         public int Value
186                         {
187                                 get
188                                 {
189                                         return value;
190                                 }
191                                 set
192                                 {
193                                         this.value = value;
194                                 }
195                         }
196
197                         public override int GetHashCode ()
198                         {
199                                 return base.GetHashCode ();
200                         }
201
202                         public override bool Equals (object obj)
203                         {
204                                 return value == ((SimpleItem)obj).value;
205                         }
206                 }
207
208                 [Test]
209                 public void GetListItemPropertiesTest ()
210                 {
211                         SimpleItem [] items = new SimpleItem [0];
212                         PropertyDescriptorCollection properties = ListBindingHelper.GetListItemProperties (items);
213
214                         Assert.AreEqual (1, properties.Count, "#A1");
215                         Assert.AreEqual ("Value", properties [0].Name, "#A2");
216
217                         List<SimpleItem> items_list = new List<SimpleItem> ();
218                         properties = ListBindingHelper.GetListItemProperties (items_list);
219
220                         Assert.AreEqual (1, properties.Count, "#B1");
221                         Assert.AreEqual ("Value", properties [0].Name, "#B2");
222
223                         // Empty arraylist
224                         ArrayList items_arraylist = new ArrayList ();
225                         properties = ListBindingHelper.GetListItemProperties (items_arraylist);
226
227                         Assert.AreEqual (0, properties.Count, "#C1");
228
229                         // Non empty arraylist
230                         items_arraylist.Add (new SimpleItem ());
231                         properties = ListBindingHelper.GetListItemProperties (items_arraylist);
232
233                         Assert.AreEqual (1, properties.Count, "#D1");
234                         Assert.AreEqual ("Value", properties [0].Name, "#D2");
235
236                         // non list object
237                         properties = ListBindingHelper.GetListItemProperties (new SimpleItem ());
238
239                         Assert.AreEqual (1, properties.Count, "#E1");
240                         Assert.AreEqual ("Value", properties [0].Name, "#E2");
241
242                         // null value
243                         properties = ListBindingHelper.GetListItemProperties (null);
244
245                         Assert.AreEqual (0, properties.Count, "#F1");
246
247                         // ListSource
248                         properties = ListBindingHelper.GetListItemProperties (new ListSource (true));
249
250                         Assert.AreEqual (1, properties.Count, "#G1");
251                         Assert.AreEqual ("Value", properties [0].Name, "#G2");
252
253                         // ITypedList
254                         DataTable table = new DataTable ();
255                         table.Columns.Add ("Name", typeof (string));
256
257                         properties = ListBindingHelper.GetListItemProperties (table);
258                         Assert.AreEqual (1, properties.Count, "#H1");
259                         Assert.AreEqual ("Name", properties [0].Name, "#H2");
260                 }
261
262                 // tests for the overloads of the method
263                 [Test]
264                 [NUnit.Framework.Category ("NotWorking")]
265                 public void GetListItemPropertiesTest2 ()
266                 {
267                         ListContainer list_container = new ListContainer ();
268                         PropertyDescriptorCollection list_properties = TypeDescriptor.GetProperties (list_container);
269                         PropertyDescriptor property = list_properties ["List"];
270
271                         PropertyDescriptorCollection property_coll = ListBindingHelper.GetListItemProperties (list_container,
272                                 new PropertyDescriptor [] { property });
273                         Assert.AreEqual (1, property_coll.Count, "#A1");
274                         Assert.AreEqual ("Value", property_coll [0].Name, "#A2");
275
276                         // Empty property descriptor array 
277                         // Returns list_container properties, since it's not a list
278                         property_coll = ListBindingHelper.GetListItemProperties (list_container, new PropertyDescriptor [0]);
279                         Assert.AreEqual (2, property_coll.Count, "#B1");
280
281                         // Non list property
282                         // Returns the propeties of the type of that property
283                         property = list_properties ["NonList"];
284                         property_coll = ListBindingHelper.GetListItemProperties (list_container,
285                                 new PropertyDescriptor [] { property });
286                         Assert.AreEqual (1, property_coll.Count, "#C1");
287                         Assert.AreEqual ("Value", property_coll [0].Name, "#C2");
288
289                         // Pass two properties
290                         property = list_properties ["List"];
291                         PropertyDescriptor property2 = list_properties ["NonList"];
292                         property_coll = ListBindingHelper.GetListItemProperties (list_container,
293                                 new PropertyDescriptor [] { property2, property });
294                         Assert.AreEqual (0, property_coll.Count, "#D1");
295
296                         //
297                         // Third overload - doble re-direction
298                         //
299                         SuperContainer super_container = new SuperContainer ();
300                         property = list_properties ["List"];
301
302                         property_coll = ListBindingHelper.GetListItemProperties (super_container, "ListContainer",
303                                 new PropertyDescriptor [] { property });
304                         Assert.AreEqual (1, property_coll.Count, "#E1");
305                 }
306
307                 [Test]
308                 public void GetListItemTypeTest ()
309                 {
310                         List<int> list = new List<int> ();
311                         DateTime [] date_list = new DateTime [0];
312                         StringCollection string_coll = new StringCollection ();
313
314                         Assert.AreEqual (typeof (int), ListBindingHelper.GetListItemType (list), "#A1");
315                         Assert.AreEqual (typeof (DateTime), ListBindingHelper.GetListItemType (date_list), "#A2");
316                         Assert.AreEqual (typeof (string), ListBindingHelper.GetListItemType (string_coll), "#A4");
317
318                         // Returns the type of the first item if could enumerate
319                         ArrayList arraylist = new ArrayList ();
320                         arraylist.Add ("hellou");
321                         arraylist.Add (3.1416);
322                         Assert.AreEqual (typeof (string), ListBindingHelper.GetListItemType (arraylist), "#B1");
323
324                         // Returns the type of the public Item property, not the explicit one
325                         ListView.ColumnHeaderCollection col_collection = new ListView.ColumnHeaderCollection (null);
326                         Assert.AreEqual (typeof (ColumnHeader), ListBindingHelper.GetListItemType (col_collection), "#C1");
327
328                         ListContainer list_container = new ListContainer ();
329                         String str = "A";
330                         Assert.AreEqual (typeof (IList), ListBindingHelper.GetListItemType (list_container, "List"), "#D1");
331                         Assert.AreEqual (typeof (int), ListBindingHelper.GetListItemType (str, "Length"), "#D2");
332                         // Property doesn't exist - fallback to object type
333                         Assert.AreEqual (typeof (object), ListBindingHelper.GetListItemType (str, "DoesntExist"), "#D3");
334
335                         // finally, objects that are not array nor list
336                         Assert.AreEqual (typeof (double), ListBindingHelper.GetListItemType (3.1416), "#E1");
337                         Assert.AreEqual (null, ListBindingHelper.GetListItemType (null), "#E2");
338
339                         // bug #507120 - an IEnumerator instance with a Current value returning null,
340                         // falling back to IList.this detection, if possible
341                         Assert.AreEqual (typeof (string), ListBindingHelper.GetListItemType (new NullEnumerable (), null), "#F1");
342                 }
343
344                 // useless class that help us with a simple enumerator with a null Current property
345                 // and implementing IList to let the ListBindingHelper get info from the this [] property
346                 class NullEnumerable : IList, ICollection, IEnumerable
347                 {
348                         public IEnumerator GetEnumerator ()
349                         {
350                                 return new NullEnumerator ();
351                         }
352
353                         class NullEnumerator : IEnumerator
354                         {
355                                 int pos = -1;
356
357                                 // the idea is that we just move one time - the first time
358                                 public bool MoveNext ()
359                                 {
360                                         if (pos > -1)
361                                                 return false;
362
363                                         pos = 0;
364                                         return true;
365                                 }
366
367                                 public void Reset ()
368                                 {
369                                         pos = -1;
370                                 }
371
372                                 public object Current {
373                                         get {
374                                                 return null;
375                                         }
376                                 }
377                         }
378
379                         // make this return a string, and hide the interface impl,
380                         // so we are sure ListBindingHelper is actually accessing this property
381                         public string this [int index] {
382                                 get {
383                                         if (index != 0)
384                                                 throw new ArgumentOutOfRangeException ("index");
385
386                                         return null;
387                                 }
388                                 set {
389                                 }
390                         }
391
392                         object IList.this [int index] {
393                                 get {
394                                         return this [index];
395                                 }
396                                 set {
397                                 }
398                         }
399
400                         public int Add (object o)
401                         {
402                                 return 0;
403                         }
404
405                         public void Clear ()
406                         {
407                         }
408
409                         public bool Contains (object o)
410                         {
411                                 return false;
412                         }
413
414                         public int IndexOf (object o)
415                         {
416                                 return -1;
417                         }
418
419                         public void Insert (int index, object o)
420                         {
421                         }
422
423                         public void Remove (object o)
424                         {
425                         }
426
427                         public void RemoveAt (int index)
428                         {
429                         }
430
431                         public bool IsFixedSize {
432                                 get {
433                                         return true;
434                                 }
435                         }
436
437                         public bool IsReadOnly {
438                                 get {
439                                         return true;
440                                 }
441                         }
442
443                         public void CopyTo (Array array, int offset)
444                         {
445                         }
446
447                         public int Count {
448                                 get {
449                                         return 1;
450                                 }
451                         }
452
453                         public bool IsSynchronized {
454                                 get {
455                                         return false;
456                                 }
457                         }
458
459                         public object SyncRoot {
460                                 get {
461                                         return this;
462                                 }
463                         }
464                 }
465
466                 [Test]
467                 public void GetListNameTest ()
468                 {
469                         List<int> list = new List<int> ();
470                         int [] arr = new int [0];
471                         SimpleItem item = new SimpleItem ();
472
473                         Assert.AreEqual (typeof (int).Name, ListBindingHelper.GetListName (list, null), "1");
474                         Assert.AreEqual (typeof (int).Name, ListBindingHelper.GetListName (arr, null), "2");
475                         Assert.AreEqual (typeof (SimpleItem).Name, ListBindingHelper.GetListName (item, null), "3");
476                         Assert.AreEqual (String.Empty, ListBindingHelper.GetListName (null, null), "4");
477                 }
478         }
479 }
480
481 #endif