merge -r 58784:58785
[mono.git] / mcs / class / corlib / Test / System.Collections.Generic / DictionaryTest.cs
1 //
2 // MonoTests.System.Collections.Generic.Test.DictionaryTest
3 //
4 // Authors:
5 //      Sureshkumar T (tsureshkumar@novell.com)
6 //      Ankit Jain (radical@corewars.org)
7 //      David Waite (mass@akuma.org)
8 //
9 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
10 // Copyright (C) 2005 David Waite (mass@akuma.org)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 #if NET_2_0
33
34 using System;
35 using System.Collections;
36 using System.Collections.Generic;
37 using System.IO;
38 using System.Runtime.Serialization.Formatters.Binary;
39 using System.Text;
40 using NUnit.Framework;
41
42 namespace MonoTests.System.Collections.Generic {
43         [TestFixture]
44         public class DictionaryTest {
45                 class MyClass {
46                         int a;
47                         int b;
48                         public MyClass (int a, int b)
49                         {
50                                 this.a = a;
51                                 this.b = b;
52                         }
53                         public override int GetHashCode ()
54                         {
55                                 return a + b;
56                         }
57         
58                         public override bool Equals (object obj)
59                         {
60                                 if (!(obj is MyClass))
61                                         return false;
62                                 return ((MyClass)obj).Value == a;
63                         }
64         
65         
66                         public int Value {
67                                 get { return a; }
68                         }
69         
70                 }
71         
72                 Dictionary <string, object> _dictionary = null;
73                 Dictionary <MyClass, MyClass> _dictionary2 = null;
74                 Dictionary <int, int> _dictionary3 = null;
75         
76                 [SetUp]
77                 public void SetUp ()
78                 {
79                         _dictionary = new Dictionary <string, object> ();
80                         _dictionary2 = new Dictionary <MyClass, MyClass> ();
81                         _dictionary3 = new Dictionary <int, int>();
82                 }
83         
84                 [Test]
85                 public void AddTest ()
86                 {
87                         _dictionary.Add ("key1", "value");
88                         Assert.AreEqual ("value", _dictionary ["key1"].ToString (), "Add failed!");
89                 }
90         
91                 [Test]
92                 public void AddTest2 ()
93                 {
94                         MyClass m1 = new MyClass (10,5);
95                         MyClass m2 = new MyClass (20,5);
96                         MyClass m3 = new MyClass (12,3);
97                         _dictionary2.Add (m1,m1);
98                         _dictionary2.Add (m2, m2);
99                         _dictionary2.Add (m3, m3);
100                         Assert.AreEqual (20, _dictionary2 [m2].Value, "#1");
101                         Assert.AreEqual (10, _dictionary2 [m1].Value, "#2");
102                         Assert.AreEqual (12, _dictionary2 [m3].Value, "#3");
103                 }
104
105                 [Test]
106                 public void AddTest3 ()
107                 {
108                         _dictionary3.Add (1, 2);
109                         _dictionary3.Add (2, 3);
110                         _dictionary3.Add (3, 4);
111                         Assert.AreEqual (2, _dictionary3[1], "#1");
112                         Assert.AreEqual (3, _dictionary3[2], "#2");
113                         Assert.AreEqual (4, _dictionary3[3], "#3");
114                 }
115
116                 [Test, ExpectedException(typeof(ArgumentNullException))]
117                 public void AddNullTest ()
118                 {
119                         _dictionary.Add (null, "");
120                 }
121         
122                 [Test, ExpectedException(typeof(ArgumentException))]
123                 public void AddDuplicateTest ()
124                 {
125                         _dictionary.Add("foo", "bar");
126                         _dictionary.Add("foo", "bar");
127                 }
128
129                 //Tests Add when resize takes place
130                 [Test]
131                 public void AddLargeTest ()
132                 {
133                         int i, numElems = 50;
134         
135                         for (i = 0; i < numElems; i++)
136                         {
137                                 _dictionary3.Add (i, i);
138                         }
139         
140                         i = 0;
141                         foreach (KeyValuePair <int, int> entry in _dictionary3)
142                         {
143                                 i++;
144                         }
145         
146                         Assert.AreEqual (i, numElems, "Add with resize failed!");
147                 }
148         
149                 [Test]
150                 public void IndexerGetExistingTest ()
151                 {
152                         _dictionary.Add ("key1", "value");
153                         Assert.AreEqual ("value", _dictionary ["key1"].ToString (), "Add failed!");
154                 }
155                 
156                 [Test, ExpectedException(typeof(KeyNotFoundException))]
157                 public void IndexerGetNonExistingTest ()
158                 {
159                         object foo = _dictionary ["foo"];
160                 }
161
162                 [Test, ExpectedException(typeof(ArgumentNullException))]
163                 public void IndexerGetNullTest()
164                 {
165                         object s = _dictionary[null];
166                 }
167
168                 [Test]
169                 public void IndexerSetExistingTest ()
170                 {
171                         _dictionary.Add ("key1", "value1");
172                         _dictionary ["key1"] =  "value2";
173                         Assert.AreEqual (1, _dictionary.Count);
174                         Assert.AreEqual ("value2", _dictionary ["key1"]);
175                 }
176
177                 [Test]
178                 public void IndexerSetNonExistingTest ()
179                 {
180                         _dictionary ["key1"] =  "value1";
181                         Assert.AreEqual (1, _dictionary.Count);
182                         Assert.AreEqual ("value1", _dictionary ["key1"]);
183                 }
184         
185                 [Test]
186                 public void RemoveTest ()
187                 {
188                         _dictionary.Add ("key1", "value1");
189                         _dictionary.Add ("key2", "value2");
190                         _dictionary.Add ("key3", "value3");
191                         _dictionary.Add ("key4", "value4");
192                         Assert.IsTrue (_dictionary.Remove ("key3"));
193                         Assert.IsFalse (_dictionary.Remove ("foo"));
194                         Assert.AreEqual (3, _dictionary.Count);
195                         Assert.IsFalse (_dictionary.ContainsKey ("key3"));
196                 }
197         
198                 [Test]
199                 public void RemoveTest2 ()
200                 {
201                         MyClass m1 = new MyClass (10, 5);
202                         MyClass m2 = new MyClass (20, 5);
203                         MyClass m3 = new MyClass (12, 3);
204                         _dictionary2.Add (m1, m1);
205                         _dictionary2.Add (m2, m2);
206                         _dictionary2.Add (m3, m3);
207                         _dictionary2.Remove (m1); // m2 is in rehash path
208                         Assert.AreEqual (20, _dictionary2 [m2].Value, "#4");
209                         
210                 }
211         
212                 [Test, ExpectedException(typeof(ArgumentNullException))]
213                 public void IndexerSetNullTest()
214                 {
215                         _dictionary[null] = "bar";
216                 }
217         
218                 [Test]
219                 public void ClearTest ()
220                 {
221                         _dictionary.Add ("key1", "value1");
222                         _dictionary.Add ("key2", "value2");
223                         _dictionary.Add ("key3", "value3");
224                         _dictionary.Add ("key4", "value4");
225                         _dictionary.Clear ();
226                         Assert.AreEqual (0, _dictionary.Count, "Clear method failed!");
227                         Assert.IsFalse (_dictionary.ContainsKey ("key2"));
228                 }
229         
230                 [Test]
231                 public void ContainsKeyTest ()
232                 {
233                         _dictionary.Add ("key1", "value1");
234                         _dictionary.Add ("key2", "value2");
235                         _dictionary.Add ("key3", "value3");
236                         _dictionary.Add ("key4", "value4");
237                         bool contains = _dictionary.ContainsKey ("key4");
238                         Assert.IsTrue (contains, "ContainsKey does not return correct value!");
239                         contains = _dictionary.ContainsKey ("key5");
240                         Assert.IsFalse (contains, "ContainsKey for non existant does not return correct value!");
241                 }
242         
243                 [Test]
244                 public void ContainsValueTest ()
245                 {
246                         _dictionary.Add ("key1", "value1");
247                         _dictionary.Add ("key2", "value2");
248                         _dictionary.Add ("key3", "value3");
249                         _dictionary.Add ("key4", "value4");
250                         bool contains = _dictionary.ContainsValue ("value2");
251                         Assert.IsTrue(contains, "ContainsValue does not return correct value!");
252                         contains = _dictionary.ContainsValue ("@@daisofja@@");
253                         Assert.IsFalse (contains, "ContainsValue for non existant does not return correct value!");
254                 }
255         
256                 [Test]
257                 public void TryGetValueTest()
258                 {
259                         _dictionary.Add ("key1", "value1");
260                         _dictionary.Add ("key2", "value2");
261                         _dictionary.Add ("key3", "value3");
262                         _dictionary.Add ("key4", "value4");
263                         object value = "";
264                         bool retrieved = _dictionary.TryGetValue ("key4", out value);
265                         Assert.IsTrue (retrieved);
266                         Assert.AreEqual ("value4", (string)value, "TryGetValue does not return value!");
267         
268                         retrieved = _dictionary.TryGetValue ("key7", out value);
269                         Assert.IsFalse (retrieved);
270                         Assert.IsNull (value, "value for non existant value should be null!");
271                 }
272         
273                 [Test]
274                 public void ValueTypeTest ()
275                 {
276                         Dictionary <int, float> dict = new Dictionary <int, float> ();
277                         dict.Add (10, 10.3f);
278                         dict.Add (11, 10.4f);
279                         dict.Add (12, 10.5f);
280                         Assert.AreEqual (10.4f, dict [11], "#5");
281                 }
282         
283                 private class MyTest
284                 {
285                         public string Name;
286                         public int RollNo;
287         
288                         public MyTest (string name, int number)
289                         {
290                                 Name = name;
291                                 RollNo = number;
292                         }
293
294                         public override int GetHashCode ()
295                         {
296                                 return Name.GetHashCode () ^ RollNo;
297                         }
298
299                         public override bool Equals (object obj)
300                         {
301                                 MyTest myt = obj as MyTest;
302                                 return myt.Name.Equals (this.Name) &&
303                                                 myt.RollNo.Equals (this.RollNo);
304                         }
305         
306                 }
307         
308                 [Test]
309                 public void ObjectAsKeyTest ()
310                 {
311                         Dictionary <object, object> dict = new Dictionary <object, object> ();
312                         MyTest key1, key2, key3;
313                         dict.Add ( (key1 = new MyTest ("key1", 234)), "value1");
314                         dict.Add ( (key2 = new MyTest ("key2", 444)), "value2");
315                         dict.Add ( (key3 = new MyTest ("key3", 5655)), "value3");
316         
317                         Assert.AreEqual ("value2", dict [key2], "value is not returned!");
318                         Assert.AreEqual ("value3", dict [key3], "neg: exception should not be thrown!");
319                 }
320         
321                 [Test, ExpectedException (typeof (ArgumentException))]
322                 public void IDictionaryAddTest ()
323                 {
324                         IDictionary iDict = _dictionary as IDictionary;
325                         iDict.Add ("key1", "value1");
326                         iDict.Add ("key2", "value3");
327                         Assert.AreEqual (2, iDict.Count, "IDictioanry interface add is not working!");
328         
329                         //Negative test case
330                         iDict.Add (12, "value");
331                         iDict.Add ("key", 34);
332                 }
333         
334                 [Test]
335                 public void IEnumeratorTest ()
336                 {
337                         _dictionary.Add ("key1", "value1");
338                         _dictionary.Add ("key2", "value2");
339                         _dictionary.Add ("key3", "value3");
340                         _dictionary.Add ("key4", "value4");
341                         IEnumerator itr = ((IEnumerable)_dictionary).GetEnumerator ();
342                         while (itr.MoveNext ()) {
343                                 object o = itr.Current;
344                                 Assert.AreEqual (typeof (DictionaryEntry), o.GetType (), "Current should return a type of DictionaryEntry");
345                                 DictionaryEntry entry = (DictionaryEntry)itr.Current;
346                                 if (entry.Key.ToString () == "key4")
347                                         entry.Value = "value33";
348                         }
349                         Assert.AreEqual ("value4", _dictionary ["key4"].ToString (), "");
350                 }
351         
352         
353                 [Test]
354                 public void IEnumeratorGenericTest ()
355                 {
356                         _dictionary.Add ("key1", "value1");
357                         _dictionary.Add ("key2", "value2");
358                         _dictionary.Add ("key3", "value3");
359                         _dictionary.Add ("key4", "value4");
360                         IEnumerator <KeyValuePair <string, object>> itr = ((IEnumerable <KeyValuePair <string, object>>)_dictionary).GetEnumerator ();
361                         while (itr.MoveNext ()) {
362                                 object o = itr.Current;
363                                 Assert.AreEqual (typeof (KeyValuePair <string, object>), o.GetType (), "Current should return a type of DictionaryEntry");
364                                 KeyValuePair <string, object> entry = (KeyValuePair <string, object>)itr.Current;
365                         }
366                         Assert.AreEqual ("value4", _dictionary ["key4"].ToString (), "");
367         
368                 }
369         
370                 [Test]
371                 public void IDictionaryEnumeratorTest ()
372                 {
373                         _dictionary.Add ("key1", "value1");
374                         _dictionary.Add ("key2", "value2");
375                         _dictionary.Add ("key3", "value3");
376                         _dictionary.Add ("key4", "value4");
377                         IDictionaryEnumerator itr = ((IDictionary)_dictionary).GetEnumerator ();
378                         while (itr.MoveNext ()) {
379                                 object o = itr.Current;
380                                 Assert.AreEqual (typeof (DictionaryEntry), o.GetType (), "Current should return a type of DictionaryEntry");
381                                 DictionaryEntry entry = (DictionaryEntry)itr.Current;
382                                 if (entry.Key.ToString () == "key4")
383                                         entry.Value = "value33";
384                         }
385                         Assert.AreEqual ("value4", _dictionary ["key4"].ToString (), "");
386         
387                 }
388         
389                 [Test]
390                 public void ForEachTest ()
391                 {
392                         _dictionary.Add ("key1", "value1");
393                         _dictionary.Add ("key2", "value2");
394                         _dictionary.Add ("key3", "value3");
395                         _dictionary.Add ("key4", "value4");
396         
397                         int i = 0;
398                         foreach (KeyValuePair <string, object> entry in _dictionary)
399                         {
400                                 i++;
401                         }
402                         Assert.AreEqual(4, i, "fail1: foreach entry failed!");
403         
404                         i = 0;
405                         foreach (DictionaryEntry entry in ((IEnumerable)_dictionary))
406                         {
407                                 i++;
408                         }
409                         Assert.AreEqual(4, i, "fail2: foreach entry failed!");
410         
411                         i = 0;
412                         foreach (DictionaryEntry entry in ((IDictionary)_dictionary))
413                         {
414                                 i++;
415                         }
416                         Assert.AreEqual (4, i, "fail3: foreach entry failed!");
417                 }
418         
419                 [Test]
420                 public void ResizeTest ()
421                 {
422                         Dictionary <string, object> dictionary = new Dictionary <string, object> (3);
423                         dictionary.Add ("key1", "value1");
424                         dictionary.Add ("key2", "value2");
425                         dictionary.Add ("key3", "value3");
426         
427                         Assert.AreEqual (3, dictionary.Count);
428         
429                         dictionary.Add ("key4", "value4");
430                         Assert.AreEqual (4, dictionary.Count);
431                         Assert.AreEqual ("value1", dictionary ["key1"].ToString (), "");
432                         Assert.AreEqual ("value2", dictionary ["key2"].ToString (), "");
433                         Assert.AreEqual ("value4", dictionary ["key4"].ToString (), "");
434                         Assert.AreEqual ("value3", dictionary ["key3"].ToString (), "");
435                 }
436         
437                 [Test]
438                 public void KeyCollectionTest ()
439                 {
440                         _dictionary.Add ("key1", "value1");
441                         _dictionary.Add ("key2", "value2");
442                         _dictionary.Add ("key3", "value3");
443                         _dictionary.Add ("key4", "value4");
444         
445                         ICollection <string> keys = ((IDictionary <string, object>)_dictionary).Keys;
446                         Assert.AreEqual (4, keys.Count);
447                         int i = 0;
448                         foreach (string key in keys)
449                         {
450                                 i++;
451                         }
452                         Assert.AreEqual(4, i);
453                 }
454
455                 [Test]
456                 public void KeyValueEnumeratorTest ()
457                 {
458                         IDictionary<int, int> d = new Dictionary<int, int>();
459
460                         // Values are chosen such that two keys map to the same bucket.
461                         // Default dictionary table size == 10
462                         d [9] = 1;
463                         d [10] = 2;
464                         d [19] = 3;
465
466                         Assert.AreEqual (d.Count, d.Keys.Count, "d and d.Keys don't appear to match");
467                         Assert.AreEqual (d.Values.Count, d.Keys.Count, "d.Keys and d.Values don't appear to match");
468
469                         int count = 0;
470                         foreach (int i in d.Values)
471                                 ++count;
472                         Assert.AreEqual (count, d.Values.Count, "d.Values doesn't have the correct number of elements");
473         
474                         count = 0;
475                         foreach (int i in d.Keys)
476                                 ++count;
477                         Assert.AreEqual (count, d.Keys.Count, "d.Keys doesn't have the correct number of elements");
478
479                         int nkeys = count;
480                         count = 0;
481                         foreach (int i in d.Keys) {
482                                 int foo = d [i];
483                                 if (count++ >= nkeys)
484                                         Assert.Fail ("Reading a value appears to trash enumerator state");
485                         }
486                 }
487
488                 [Test]          // bug 75073
489                 public void SliceCollectionsEnumeratorTest ()
490                 {
491                         Dictionary<string, int> values = new Dictionary<string, int> ();
492
493                         IEnumerator <string> ke = values.Keys.GetEnumerator ();
494                         IEnumerator <int>    ve = values.Values.GetEnumerator ();
495
496                         Assert.IsTrue (ke is Dictionary<string, int>.KeyCollection.Enumerator);
497                         Assert.IsTrue (ve is Dictionary<string, int>.ValueCollection.Enumerator);
498                 }
499
500                 [Test]
501                 public void PlainEnumeratorReturnTest ()
502                 {
503                         // Test that we return a DictionaryEntry for non-generic dictionary iteration
504                         _dictionary["foo"] = "bar";
505                         IEnumerator<KeyValuePair<string, object>> enumerator = _dictionary.GetEnumerator();
506                         Assert.IsTrue(enumerator.MoveNext());
507                         Assert.IsTrue(((IEnumerator)enumerator).Current is DictionaryEntry);
508                         Assert.IsTrue(((IDictionaryEnumerator)enumerator).Current is DictionaryEntry);
509                         Assert.IsFalse(((object) enumerator.Current) is DictionaryEntry);
510                 }
511
512                 [Test, ExpectedException (typeof (InvalidOperationException))]
513                 public void FailFastTest1 ()
514                 {
515                         Dictionary<int, int> d = new Dictionary<int, int> ();
516                         d [1] = 1;
517                         int count = 0;
518                         foreach (KeyValuePair<int, int> kv in d) {
519                                 d [kv.Key + 1] = kv.Value + 1;
520                                 if (count++ != 0)
521                                         Assert.Fail ("Should not be reached");
522                         }
523                         Assert.Fail ("Should not be reached");
524                 }
525
526                 [Test, ExpectedException (typeof (InvalidOperationException))]
527                 public void FailFastTest2 ()
528                 {
529                         Dictionary<int, int> d = new Dictionary<int, int> ();
530                         d [1] = 1;
531                         int count = 0;
532                         foreach (int i in d.Keys) {
533                                 d [i + 1] = i + 1;
534                                 if (count++ != 0)
535                                         Assert.Fail ("Should not be reached");
536                         }
537                         Assert.Fail ("Should not be reached");
538                 }
539
540                 [Test, ExpectedException (typeof (InvalidOperationException))]
541                 public void FailFastTest3 ()
542                 {
543                         Dictionary<int, int> d = new Dictionary<int, int> ();
544                         d [1] = 1;
545                         int count = 0;
546                         foreach (int i in d.Keys) {
547                                 d [i] = i;
548                                 if (count++ != 0)
549                                         Assert.Fail ("Should not be reached");
550                         }
551                         Assert.Fail ("Should not be reached");
552                 }
553
554                 [Test]
555                 public void SerializationTest()
556                 {
557                         for (int i = 0; i < 50; i++)
558                         {
559                                 _dictionary3.Add(i, i);
560                         }
561
562                         BinaryFormatter formatter = new BinaryFormatter();
563                         MemoryStream stream = new MemoryStream();
564                         formatter.Serialize(stream, _dictionary3);
565
566                         stream.Position = 0;
567                         object deserialized = formatter.Deserialize(stream);
568
569                         Assert.IsNotNull(deserialized);
570                         Assert.IsFalse(deserialized == _dictionary3);
571
572                         Assert.IsTrue(deserialized is Dictionary<int, int>);
573                         Dictionary<int, int> d3 = deserialized as Dictionary<int, int>;
574
575                         Assert.AreEqual(50, d3.Count);
576                         for (int i = 0; i < 50; i++)
577                         {
578                                 Assert.AreEqual(i, d3[i]);
579                         }
580                 }
581
582                 [Test]
583                 public void ZeroCapacity ()
584                 {
585                         Dictionary<int, int> x = new Dictionary <int, int> (0);
586                         x.Add (1, 2);
587                         
588                         x = new Dictionary <int, int> (0);
589                         x.Clear ();
590
591                         x = new Dictionary <int, int> (0);
592                         int aa = x.Count;
593                         
594                         x = new Dictionary <int, int> (0);
595                         try {
596                                 int j = x [1];
597                         } catch (KeyNotFoundException){
598                         }
599
600                         bool b;
601                         b = x.ContainsKey (10);
602                         b = x.ContainsValue (10);
603
604                         x = new Dictionary <int, int> (0);
605                         x.Remove (10);
606                         
607                         x = new Dictionary <int, int> (0);
608                         int intv;
609                         x.TryGetValue (1, out intv);
610
611                         object oa = x.Keys;
612                         object ob = x.Values;
613                         foreach (KeyValuePair<int,int> a in x){
614                         }
615
616                         
617                 }
618         }
619 }
620
621 #endif // NET_2_0