1 // HashtableTest.cs - NUnit Test Cases for the System.Collections.Hashtable class
4 // (C) Ximian, Inc. http://www.ximian.com
9 using System
.Collections
;
12 using System
.Runtime
.Serialization
;
13 using System
.Runtime
.Serialization
.Formatters
;
14 using System
.Runtime
.Serialization
.Formatters
.Binary
;
16 using NUnit
.Framework
;
20 namespace MonoTests
.System
.Collections
{
23 /// <summary>Hashtable test.</summary>
25 public class HashtableTest
: Assertion
{
28 public void TestCtor1() {
29 Hashtable h
= new Hashtable();
30 AssertNotNull("No hash table", h
);
34 public void TestCtor2() {
36 bool errorThrown
= false;
38 Hashtable h
= new Hashtable((IDictionary
) null);
39 } catch (ArgumentNullException
) {
42 Assert("null hashtable error not thrown",
46 string[] keys
= {"this", "is", "a", "test"}
;
47 char[] values
= {'a', 'b', 'c', 'd'}
;
48 Hashtable h1
= new Hashtable();
49 for (int i
= 0; i
< keys
.Length
; i
++) {
50 h1
[keys
[i
]] = values
[i
];
52 Hashtable h2
= new Hashtable(h1
);
53 for (int i
= 0; i
< keys
.Length
; i
++) {
54 AssertEquals("No match for key " + keys
[i
],
55 values
[i
], h2
[keys
[i
]]);
61 [ExpectedException (typeof (ArgumentOutOfRangeException
))]
62 public void TestCtor3 ()
64 Hashtable h
= new Hashtable ();
65 Hashtable hh
= new Hashtable (h
, Single
.NaN
);
69 [ExpectedException (typeof (ArgumentException
))]
70 public void TestCtor4 ()
72 Hashtable ht
= new Hashtable (Int32
.MaxValue
, 0.1f
, null, null);
76 public void TestCtor5 ()
78 // tests if negative capacity throws exception
80 Hashtable ht
= new Hashtable (-10, 0.1f
, null, null);
81 Assert("must throw ArgumentOutOfRange exception, param: capacity", false);
82 } catch (ArgumentOutOfRangeException e
) {
83 Assert("ParamName is not capacity", e
.ParamName
== "capacity");
86 // tests if loadFactor out of range throws exception (low)
88 Hashtable ht
= new Hashtable (100, 0.01f
, null, null);
89 Assert("must throw ArgumentOutOfRange exception, param: loadFactor, too low value", false);
90 } catch (ArgumentOutOfRangeException e
)
92 Assert("ParamName is not loadFactor",e
.ParamName
== "loadFactor");
95 // tests if loadFactor out of range throws exception (high)
98 Hashtable ht
= new Hashtable (100, 2f
, null, null);
99 Assert("must throw ArgumentOutOfRange exception, param: loadFactor, too high value", false);
101 catch (ArgumentOutOfRangeException e
)
103 Assert("ParamName is not loadFactor", e
.ParamName
== "loadFactor");
108 // TODO - Ctors for capacity and load (how to test? any access?)
109 // TODO - Ctors with IComparer, IHashCodeProvider, Serialization
112 public void TestCount() {
113 Hashtable h
= new Hashtable();
114 AssertEquals("new table - count zero", 0, h
.Count
);
116 for (int i
= 1; i
<= max
; i
++) {
118 AssertEquals("Count wrong for " + i
,
121 for (int i
= 1; i
<= max
; i
++) {
123 AssertEquals("Count shouldn't change at " + i
,
129 public void TestIsFixedSize() {
130 Hashtable h
= new Hashtable();
131 AssertEquals("hashtable not fixed by default",
132 false, h
.IsFixedSize
);
133 // TODO - any way to get a fixed-size hashtable?
136 public void TestIsReadOnly() {
137 Hashtable h
= new Hashtable();
138 AssertEquals("hashtable not read-only by default",
139 false, h
.IsReadOnly
);
140 // TODO - any way to get a read-only hashtable?
144 public void TestIsSynchronized ()
146 Hashtable h
= new Hashtable ();
147 Assert ("hashtable not synched by default", !h
.IsSynchronized
);
149 Hashtable h2
= Hashtable
.Synchronized (h
);
150 Assert ("hashtable should by synched", h2
.IsSynchronized
);
152 Hashtable h3
= (Hashtable
) h2
.Clone ();
153 Assert ("Cloned Hashtable should by synched", h3
.IsSynchronized
);
157 public void TestItem() {
159 bool errorThrown
= false;
161 Hashtable h
= new Hashtable();
163 } catch (ArgumentNullException e
) {
165 AssertEquals("ParamName is not \"key\"", "key", e
.ParamName
);
167 Assert("null hashtable error not thrown",
170 // TODO - if read-only and/or fixed-size is possible,
171 // test 'NotSupportedException' here
174 Hashtable h
= new Hashtable();
176 for (int i
= 1; i
<= max
; i
++) {
178 AssertEquals("value wrong for " + i
,
185 public void TestKeys() {
186 string[] keys
= {"this", "is", "a", "test"}
;
187 string[] keys2
= {"new", "keys"}
;
188 char[] values1
= {'a', 'b', 'c', 'd'}
;
189 char[] values2
= {'e', 'f', 'g', 'h'}
;
190 ICollection keysReference
, keysReference2
;
191 Hashtable h1
= new Hashtable();
192 for (int i
= 0; i
< keys
.Length
; i
++) {
193 h1
[keys
[i
]] = values1
[i
];
195 AssertEquals("keys wrong size",
196 keys
.Length
, h1
.Keys
.Count
);
197 for (int i
= 0; i
< keys
.Length
; i
++) {
198 h1
[keys
[i
]] = values2
[i
];
200 AssertEquals("keys wrong size 2",
201 keys
.Length
, h1
.Keys
.Count
);
203 // MS .NET Always returns the same reference when calling Keys property
204 keysReference
= h1
.Keys
;
205 keysReference2
= h1
.Keys
;
206 AssertEquals("keys references differ", keysReference
, keysReference2
);
208 for (int i
= 0; i
< keys2
.Length
; i
++)
210 h1
[keys2
[i
]] = values2
[i
];
212 AssertEquals("keys wrong size 3",
213 keys
.Length
+keys2
.Length
, h1
.Keys
.Count
);
214 AssertEquals("keys wrong size 4",
215 keys
.Length
+keys2
.Length
, keysReference
.Count
);
220 public void TestValues() {
221 string[] keys
= {"this", "is", "a", "test"}
;
222 char[] values1
= {'a', 'b', 'c', 'd'}
;
223 char[] values2
= {'e', 'f', 'g', 'h'}
;
224 Hashtable h1
= new Hashtable();
225 for (int i
= 0; i
< keys
.Length
; i
++) {
226 h1
[keys
[i
]] = values1
[i
];
228 AssertEquals("values wrong size",
229 keys
.Length
, h1
.Values
.Count
);
230 for (int i
= 0; i
< keys
.Length
; i
++) {
231 h1
[keys
[i
]] = values2
[i
];
233 AssertEquals("values wrong size 2",
234 keys
.Length
, h1
.Values
.Count
);
236 // MS .NET Always returns the same reference when calling Values property
237 ICollection valuesReference1
= h1
.Values
;
238 ICollection valuesReference2
= h1
.Values
;
239 AssertEquals("values references differ", valuesReference1
, valuesReference2
);
243 public void TestAdd() {
245 bool errorThrown
= false;
247 Hashtable h
= new Hashtable();
249 } catch (ArgumentNullException e
) {
251 AssertEquals("ParamName is not 'key'", "key", e
.ParamName
);
253 Assert("null add error not thrown",
257 bool errorThrown
= false;
259 Hashtable h
= new Hashtable();
262 } catch (ArgumentException
) {
265 Assert("re-add error not thrown",
268 // TODO - hit NotSupportedException
270 Hashtable h
= new Hashtable();
272 for (int i
= 1; i
<= max
; i
++) {
274 AssertEquals("value wrong for " + i
,
281 public void TestClear() {
282 // TODO - hit NotSupportedException
283 Hashtable h
= new Hashtable();
284 AssertEquals("new table - count zero", 0, h
.Count
);
286 for (int i
= 1; i
<= max
; i
++) {
289 Assert("table don't gots stuff", h
.Count
> 0);
291 AssertEquals("Table should be cleared",
296 public void TestClone() {
298 char[] c1
= {'a', 'b', 'c'}
;
299 char[] c2
= {'d', 'e', 'f'}
;
300 Hashtable h1
= new Hashtable();
301 for (int i
= 0; i
< c1
.Length
; i
++) {
304 Hashtable h2
= (Hashtable
)h1
.Clone();
305 AssertNotNull("got no clone!", h2
);
306 AssertNotNull("clone's got nothing!", h2
[c1
[0]]);
307 for (int i
= 0; i
< c1
.Length
; i
++) {
308 AssertEquals("Hashtable match",
309 h1
[c1
[i
]], h2
[c1
[i
]]);
313 char[] c1
= {'a', 'b', 'c'}
;
314 char[] c20
= {'1', '2'}
;
315 char[] c21
= {'3', '4'}
;
316 char[] c22
= {'5', '6'}
;
317 char[][] c2
= {c20, c21, c22}
;
318 Hashtable h1
= new Hashtable();
319 for (int i
= 0; i
< c1
.Length
; i
++) {
322 Hashtable h2
= (Hashtable
)h1
.Clone();
323 AssertNotNull("got no clone!", h2
);
324 AssertNotNull("clone's got nothing!", h2
[c1
[0]]);
325 for (int i
= 0; i
< c1
.Length
; i
++) {
326 AssertEquals("Hashtable match",
327 h1
[c1
[i
]], h2
[c1
[i
]]);
330 ((char[])h1
[c1
[0]])[0] = 'z';
331 AssertEquals("shallow copy", h1
[c1
[0]], h2
[c1
[0]]);
336 public void TestContains() {
338 bool errorThrown
= false;
340 Hashtable h
= new Hashtable();
341 bool result
= h
.Contains(null);
342 } catch (ArgumentNullException e
) {
344 AssertEquals("ParamName is not 'key'", "key", e
.ParamName
);
346 Assert("null add error not thrown",
350 Hashtable h
= new Hashtable();
351 for (int i
= 0; i
< 10000; i
+= 2)
355 for (int i
= 0; i
< 10000; i
+= 2)
357 Assert("hashtable must contain"+i
.ToString(), h
.Contains(i
));
358 Assert("hashtable does not contain "+((int)(i
+1)).ToString(), !h
.Contains(i
+1));
364 public void TestContainsKey() {
366 bool errorThrown
= false;
369 Hashtable h
= new Hashtable();
370 bool result
= h
.Contains(null);
372 catch (ArgumentNullException e
)
375 AssertEquals("ParamName is not 'key'", "key", e
.ParamName
);
377 Assert("null add error not thrown",
381 Hashtable h
= new Hashtable();
382 for (int i
= 0; i
< 1000; i
+= 2)
386 for (int i
= 0; i
< 1000; i
+= 2)
388 Assert("hashtable must contain"+i
.ToString(), h
.Contains(i
));
389 Assert("hashtable does not contain "+((int)(i
+1)).ToString(), !h
.Contains(i
+1));
396 public void TestContainsValue() {
398 Hashtable h
= new Hashtable();
400 Assert("blue? it's in there!",
401 h
.ContainsValue("blue"));
402 Assert("green? no way!",
403 !h
.ContainsValue("green"));
404 Assert("null? no way!",
405 !h
.ContainsValue(null));
407 Assert("null? it's in there!",
408 h
.ContainsValue(null));
414 public void TestCopyTo() {
416 bool errorThrown
= false;
418 Hashtable h
= new Hashtable();
420 } catch (ArgumentNullException e
) {
422 AssertEquals("ParamName is not \"array\"", "array", e
.ParamName
);
424 Assert("null hashtable error not thrown",
428 bool errorThrown
= false;
430 Hashtable h
= new Hashtable();
431 Object
[] o
= new Object
[1];
433 } catch (ArgumentOutOfRangeException e
) {
435 AssertEquals("ParamName is not \"arrayIndex\"", "arrayIndex", e
.ParamName
);
437 Assert("out of range error not thrown",
441 bool errorThrown
= false;
443 Hashtable h
= new Hashtable();
444 Object
[,] o
= new Object
[1,1];
446 } catch (ArgumentException
) {
449 Assert("multi-dim array error not thrown",
453 bool errorThrown
= false;
455 Hashtable h
= new Hashtable();
456 h
['a'] = 1; // no error if table is empty
457 Object
[] o
= new Object
[5];
459 } catch (ArgumentException
) {
462 Assert("no room in array error not thrown",
466 bool errorThrown
= false;
468 Hashtable h
= new Hashtable();
472 Object
[] o
= new Object
[2];
474 } catch (ArgumentException
) {
477 Assert("table too big error not thrown",
481 bool errorThrown
= false;
483 Hashtable h
= new Hashtable();
487 Char
[] o
= new Char
[3];
489 } catch (InvalidCastException
) {
492 Assert("invalid cast error not thrown",
497 Hashtable h
= new Hashtable();
500 DictionaryEntry
[] o
= new DictionaryEntry
[2];
502 AssertEquals("first copy fine.", 'a', o
[0].Key
);
503 AssertEquals("first copy fine.", 1, o
[0].Value
);
504 AssertEquals("second copy fine.", 'b', o
[1].Key
);
505 AssertEquals("second copy fine.", 2, o
[1].Value
);
510 public void TestGetEnumerator() {
511 String
[] s1
= {"this", "is", "a", "test"}
;
512 Char
[] c1
= {'a', 'b', 'c', 'd'}
;
513 Hashtable h1
= new Hashtable();
514 for (int i
= 0; i
< s1
.Length
; i
++) {
517 IDictionaryEnumerator en
= h1
.GetEnumerator();
518 AssertNotNull("No enumerator", en
);
520 for (int i
= 0; i
< s1
.Length
; i
++) {
522 Assert("Not enumerating for " + en
.Key
,
523 Array
.IndexOf(s1
, en
.Key
) >= 0);
524 Assert("Not enumerating for " + en
.Value
,
525 Array
.IndexOf(c1
, en
.Value
) >= 0);
529 // TODO - GetObjectData
530 // TODO - OnDeserialization
532 public void TestSerialization () {
533 Random r
= new Random();
534 string filename
= "hashtable_" + r
.Next(99999).ToString() + ".dat";
535 Hashtable table1
= new Hashtable();
538 BinaryFormatter formatter
= new BinaryFormatter();
540 for (int i
= 0; i
< 100; i
++) {
541 table1
[i
] = "TestString Key: " + i
.ToString();
543 str
= File
.OpenWrite(filename
);
544 formatter
.Serialize(str
, table1
);
547 str
= File
.OpenRead(filename
);
548 table2
= (Hashtable
) formatter
.Deserialize(str
);
551 File
.Delete(filename
);
554 foreach (DictionaryEntry de
in table1
) {
555 int key1
= (int) de
.Key
;
556 string val1
= (string) de
.Value
;
557 string val2
= (string) table2
[key1
];
564 Assert("Binary Serialization Error", result
);
568 public void TestRemove() {
570 bool errorThrown
= false;
572 Hashtable h
= new Hashtable();
574 } catch (ArgumentNullException e
) {
576 AssertEquals("ParamName is not \"key\"", "key", e
.ParamName
);
578 Assert("null hashtable error not thrown",
582 string[] keys
= {"this", "is", "a", "test"}
;
583 char[] values
= {'a', 'b', 'c', 'd'}
;
584 Hashtable h
= new Hashtable();
585 for (int i
= 0; i
< keys
.Length
; i
++) {
586 h
[keys
[i
]] = values
[i
];
588 AssertEquals("not enough in table",
591 AssertEquals("not enough in table",
594 AssertEquals("Wrong count in table",
597 AssertEquals("Wrong count in table",
603 public void TestSynchronized() {
605 bool errorThrown
= false;
607 Hashtable h
= Hashtable
.Synchronized(null);
608 } catch (ArgumentNullException e
) {
610 AssertEquals("ParamName is not \"table\"", "table", e
.ParamName
);
612 Assert("null hashtable error not thrown",
616 Hashtable h
= new Hashtable();
617 Assert("hashtable not synced by default",
619 Hashtable h2
= Hashtable
.Synchronized(h
);
620 Assert("hashtable should by synced",
626 protected Hashtable ht
;
627 private static Random rnd
;
630 public void SetUp() {
635 private void SetDefaultData() {
637 ht
.Add("k1","another");
639 ht
.Add("k3","hashtable");
643 public void TestAddRemoveClear() {
653 } catch (ArgumentException
) {thrown=true;}
654 Assert("Must throw ArgumentException!",thrown
);
658 Assert(ht
["k2"].Equals("cool"));
663 public void TestCopyTo2() {
665 Object
[] entries
=new Object
[ht
.Count
];
666 ht
.CopyTo(entries
,0);
667 Assert("Not an entry.",entries
[0] is DictionaryEntry
);
671 public void CopyTo_Empty ()
673 Hashtable ht
= new Hashtable ();
674 AssertEquals ("Count", 0, ht
.Count
);
675 object[] array
= new object [ht
.Count
];
676 ht
.CopyTo (array
, 0);
680 public void TestUnderHeavyLoad() {
683 String
[] cache
=new String
[max
*2];
686 for (int i
=0;i
<max
;i
++) {
687 int id
=rnd
.Next()&0xFFFF;
688 String key
=""+id
+"-key-"+id
;
689 String val
="value-"+id
;
700 for (int i
=0;i
<n
;i
++) {
702 String val
=ht
[key
] as String
;
703 String err
="ht[\""+key
+"\"]=\""+val
+
704 "\", expected \""+cache
[i
+max
]+"\"";
705 Assert(err
,val
!=null && val
.Equals(cache
[i
+max
]));
711 for (int i
=r1
;i
<r2
;i
++) {
716 for (int i
=0;i
<n
;i
++) {
718 Assert(ht
[cache
[i
]]==null);
721 String val
=ht
[key
] as String
;
722 String err
="ht[\""+key
+"\"]=\""+val
+
723 "\", expected \""+cache
[i
+max
]+"\"";
724 Assert(err
,val
!=null && val
.Equals(cache
[i
+max
]));
728 ICollection keys
=ht
.Keys
;
730 foreach (Object key
in keys
) {
731 Assert((key
as String
) != null);
734 Assert(nKeys
==ht
.Count
);
737 ICollection vals
=ht
.Values
;
739 foreach (Object val
in vals
) {
740 Assert((val
as String
) != null);
743 Assert(nVals
==ht
.Count
);
749 /// Test hashtable with CaseInsensitiveHashCodeProvider
750 /// and CaseInsensitive comparer.
753 public void TestCaseInsensitive ()
755 // Not very meaningfull test, just to make
756 // sure that hcp is set properly set.
757 Hashtable ciHashtable
= new Hashtable(11,1.0f
,CaseInsensitiveHashCodeProvider
.Default
,CaseInsensitiveComparer
.Default
);
758 ciHashtable
["key1"] = "value";
759 ciHashtable
["key2"] = "VALUE";
760 Assert(ciHashtable
["key1"].Equals ("value"));
761 Assert(ciHashtable
["key2"].Equals ("VALUE"));
763 ciHashtable
["KEY1"] = "new_value";
764 Assert(ciHashtable
["key1"].Equals ("new_value"));
769 public void TestCopyConstructor ()
773 Hashtable htCopy
= new Hashtable (ht
);
775 Assert(ht
.Count
== htCopy
.Count
);
779 public void TestEnumerator ()
783 IEnumerator e
= ht
.GetEnumerator ();
785 while (e
.MoveNext ()) {}
787 Assert (!e
.MoveNext ());
792 [ExpectedException (typeof (ArgumentNullException
))]
793 public void GetObjectData_NullSerializationInfo ()
796 ht
.GetObjectData (null, new StreamingContext ());