1 // HashtableTest.cs - NUnit Test Cases for the System.Collections.Hashtable class
2 //
3 //
4 // (C) Ximian, Inc.  http://www.ximian.com
5 //
6 
7 
8 using System;
9 using System.Collections;
10 using System.Reflection;
11 
12 using System.IO;
13 using System.Runtime.Serialization;
14 using System.Runtime.Serialization.Formatters;
15 using System.Runtime.Serialization.Formatters.Binary;
16 
17 using NUnit.Framework;
18 
19 
20 
21 namespace MonoTests.System.Collections {
22 
23 
24 /// <summary>Hashtable test.</summary>
25 [TestFixture]
26 public class HashtableTest {
27 
28         [Test]
TestCtor1()29 	public void TestCtor1() {
30 		Hashtable h = new Hashtable();
31 		Assert.IsNotNull (h, "No hash table");
32 	}
33 
34         [Test]
TestCtor2()35 	public void TestCtor2() {
36 		{
37 			bool errorThrown = false;
38 			try {
39 				Hashtable h = new Hashtable((IDictionary) null);
40 			} catch (ArgumentNullException) {
41 				errorThrown = true;
42 			}
43 			Assert.IsTrue (errorThrown, "null hashtable error not thrown");
44 		}
45 		{
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];
51 			}
52 			Hashtable h2 = new Hashtable(h1);
53 			for (int i = 0; i < keys.Length; i++) {
54 				Assert.AreEqual (values[i], h2[keys[i]], "No match for key " + keys[i]);
55 			}
56 		}
57 	}
58 
59         [Test]
60         [ExpectedException (typeof (ArgumentOutOfRangeException))]
TestCtor3()61         public void TestCtor3 ()
62         {
63                 Hashtable h = new Hashtable ();
64                 Hashtable hh = new Hashtable (h, Single.NaN);
65         }
66 
67         [Test]
68         [ExpectedException (typeof (ArgumentException))]
TestCtor4()69         public void TestCtor4 ()
70         {
71                 Hashtable ht = new Hashtable (Int32.MaxValue, 0.1f, null, null);
72         }
73 
74 	[Test]
TestCtor5()75 	public void TestCtor5 ()
76 	{
77 		// tests if negative capacity throws exception
78 		try {
79 			Hashtable ht = new Hashtable (-10, 0.1f, null, null);
80 			Assert.Fail ("must throw ArgumentOutOfRange exception, param: capacity");
81 		} catch (ArgumentOutOfRangeException e) {
82 			Assert.IsTrue (e.ParamName == "capacity", "ParamName is not capacity");
83 		}
84 
85 		// tests if loadFactor out of range throws exception (low)
86 		try {
87 			Hashtable ht = new Hashtable (100, 0.01f, null, null);
88 			Assert.Fail ("must throw ArgumentOutOfRange exception, param: loadFactor, too low value");
89 		} 	catch (ArgumentOutOfRangeException e)
90 		{
91 			Assert.IsTrue (e.ParamName == "loadFactor", "ParamName is not loadFactor");
92 		}
93 
94 		// tests if loadFactor out of range throws exception (high)
95 		try
96 		{
97 			Hashtable ht = new Hashtable (100, 2f, null, null);
98 			Assert.Fail ("must throw ArgumentOutOfRange exception, param: loadFactor, too high value");
99 		}
100 		catch (ArgumentOutOfRangeException e)
101 		{
102 			Assert.IsTrue (e.ParamName == "loadFactor", "ParamName is not loadFactor");
103 		}
104 
105 	}
106 
107 	// TODO - Ctors for capacity and load (how to test? any access?)
108         // TODO - Ctors with IComparer, IHashCodeProvider, Serialization
109 
110         [Test]
TestCount()111 	public void TestCount() {
112 		Hashtable h = new Hashtable();
113 		Assert.AreEqual (0, h.Count, "new table - count zero");
114 		int max = 100;
115 		for (int i = 1; i <= max; i++) {
116 			h[i] = i;
117 			Assert.AreEqual (i, h.Count, "Count wrong for " + i);
118 		}
119 		for (int i = 1; i <= max; i++) {
120 			h[i] = i * 2;
121 			Assert.AreEqual (max, h.Count, "Count shouldn't change at " + i);
122 		}
123 	}
124 
125         [Test]
TestIsFixedSize()126 	public void TestIsFixedSize() {
127 		Hashtable h = new Hashtable();
128 		Assert.AreEqual (false, h.IsFixedSize, "hashtable not fixed by default");
129 		// TODO - any way to get a fixed-size hashtable?
130 	}
131 
TestIsReadOnly()132 	public void TestIsReadOnly() {
133 		Hashtable h = new Hashtable();
134 		Assert.AreEqual (false, h.IsReadOnly, "hashtable not read-only by default");
135 		// TODO - any way to get a read-only hashtable?
136 	}
137 
138         [Test]
TestIsSynchronized()139 	public void TestIsSynchronized ()
140 	{
141 		Hashtable h = new Hashtable ();
142 		Assert.IsTrue (!h.IsSynchronized, "hashtable not synched by default");
143 
144 		Hashtable h2 = Hashtable.Synchronized (h);
145 		Assert.IsTrue (h2.IsSynchronized, "hashtable should by synched");
146 
147 		Hashtable h3 = (Hashtable) h2.Clone ();
148 		Assert.IsTrue (h3.IsSynchronized, "Cloned Hashtable should by synched");
149 	}
150 
151         [Test]
TestItem()152 	public void TestItem() {
153 		{
154 			bool errorThrown = false;
155 			try {
156 				Hashtable h = new Hashtable();
157 				Object o = h[null];
158 			} catch (ArgumentNullException e) {
159 				errorThrown = true;
160 				Assert.AreEqual ("key", e.ParamName, "ParamName is not \"key\"");
161 			}
162 			Assert.IsTrue (errorThrown, "null hashtable error not thrown");
163 		}
164 		// TODO - if read-only and/or fixed-size is possible,
165 		//        test 'NotSupportedException' here
166 
167 		{
168 			Hashtable h = new Hashtable();
169 			int max = 100;
170 			for (int i = 1; i <= max; i++) {
171 				h[i] = i;
172 				Assert.AreEqual (i, h[i], "value wrong for " + i);
173 			}
174 		}
175 	}
176 
177         [Test]
TestKeys()178 	public void TestKeys() {
179 		string[] keys = {"this", "is", "a", "test"};
180 		string[] keys2 = {"new", "keys"};
181 		char[] values1 = {'a', 'b', 'c', 'd'};
182 		char[] values2 = {'e', 'f', 'g', 'h'};
183 		ICollection keysReference, keysReference2;
184 		Hashtable h1 = new Hashtable();
185 		for (int i = 0; i < keys.Length; i++) {
186 			h1[keys[i]] = values1[i];
187 		}
188 		Assert.AreEqual (keys.Length, h1.Keys.Count, "keys wrong size");
189 		for (int i = 0; i < keys.Length; i++) {
190 			h1[keys[i]] = values2[i];
191 		}
192 		Assert.AreEqual (keys.Length, h1.Keys.Count, "keys wrong size 2");
193 
194 		// MS .NET Always returns the same reference when calling Keys property
195 		keysReference = h1.Keys;
196 	    keysReference2 = h1.Keys;
197 		Assert.AreEqual (keysReference, keysReference2, "keys references differ");
198 
199 		for (int i = 0; i < keys2.Length; i++)
200 		{
201 			h1[keys2[i]] = values2[i];
202 		}
203 		Assert.AreEqual (keys.Length+keys2.Length, h1.Keys.Count, "keys wrong size 3");
204 		Assert.AreEqual (keys.Length+keys2.Length, keysReference.Count, "keys wrong size 4");
205 	}
206 
207 	// TODO - SyncRoot
208         [Test]
TestValues()209 	public void TestValues() {
210 		string[] keys = {"this", "is", "a", "test"};
211 		char[] values1 = {'a', 'b', 'c', 'd'};
212 		char[] values2 = {'e', 'f', 'g', 'h'};
213 		Hashtable h1 = new Hashtable();
214 		for (int i = 0; i < keys.Length; i++) {
215 			h1[keys[i]] = values1[i];
216 		}
217 		Assert.AreEqual (keys.Length, h1.Values.Count, "values wrong size");
218 		for (int i = 0; i < keys.Length; i++) {
219 			h1[keys[i]] = values2[i];
220 		}
221 		Assert.AreEqual (keys.Length, h1.Values.Count, "values wrong size 2");
222 
223 		// MS .NET Always returns the same reference when calling Values property
224 		ICollection valuesReference1 = h1.Values;
225 		ICollection valuesReference2 = h1.Values;
226 		Assert.AreEqual (valuesReference1, valuesReference2, "values references differ");
227 	}
228 
229 	[Test]
TestAdd()230 	public void TestAdd() {
231 		{
232 			bool errorThrown = false;
233 			try {
234 				Hashtable h = new Hashtable();
235 				h.Add(null, "huh?");
236 			} catch (ArgumentNullException e) {
237 				errorThrown = true;
238 				Assert.AreEqual ("key", e.ParamName, "ParamName is not 'key'");
239 			}
240 			Assert.IsTrue (errorThrown, "null add error not thrown");
241 		}
242 		{
243 			bool errorThrown = false;
244 			try {
245 				Hashtable h = new Hashtable();
246 				h.Add('a', 1);
247 				h.Add('a', 2);
248 			} catch (ArgumentException) {
249 				errorThrown = true;
250 			}
251 			Assert.IsTrue (errorThrown, "re-add error not thrown");
252 		}
253 		// TODO - hit NotSupportedException
254 		{
255 			Hashtable h = new Hashtable();
256 			int max = 100;
257 			for (int i = 1; i <= max; i++) {
258 				h.Add(i, i);
259 				Assert.AreEqual (i, h[i], "value wrong for " + i);
260 			}
261 		}
262 	}
263 
264         [Test]
TestClear()265 	public void TestClear() {
266 		// TODO - hit NotSupportedException
267 		Hashtable h = new Hashtable();
268 		Assert.AreEqual (0, h.Count, "new table - count zero");
269 		int max = 100;
270 		for (int i = 1; i <= max; i++) {
271 			h[i] = i;
272 		}
273 		Assert.IsTrue (h.Count > 0, "table don't gots stuff");
274 		h.Clear();
275 		Assert.AreEqual (0, h.Count, "Table should be cleared");
276 	}
277 
278 	public class MyEqualityComparer : IEqualityComparer {
IEqualityComparer.Equals(object x, object y)279 		bool IEqualityComparer.Equals (object x, object y) { return x == y; }
GetHashCode(object obj)280 		public int GetHashCode (object obj) { return 1; }
281 	}
282 
GetEqualityComparer(Hashtable h)283 	static IEqualityComparer GetEqualityComparer (Hashtable h)
284 	{
285 		return (IEqualityComparer) typeof (Hashtable).GetField ("_keycomparer",
286 			BindingFlags.NonPublic | BindingFlags.Instance).GetValue (h);
287 	}
288 
289         [Test]
TestClone()290 	public void TestClone() {
291 		{
292 			char[] c1 = {'a', 'b', 'c'};
293 			char[] c2 = {'d', 'e', 'f'};
294 			Hashtable h1 = new Hashtable();
295 			for (int i = 0; i < c1.Length; i++) {
296 				h1[c1[i]] = c2[i];
297 			}
298 			Hashtable h2 = (Hashtable)h1.Clone();
299 			Assert.IsNotNull (h2, "got no clone!");
300 			Assert.IsNotNull (h2[c1[0]], "clone's got nothing!");
301 			for (int i = 0; i < c1.Length; i++) {
302 				Assert.AreEqual (h1[c1[i]], h2[c1[i]], "Hashtable match");
303 			}
304 		}
305 		{
306 			char[] c1 = {'a', 'b', 'c'};
307 			char[] c20 = {'1', '2'};
308 			char[] c21 = {'3', '4'};
309 			char[] c22 = {'5', '6'};
310 			char[][] c2 = {c20, c21, c22};
311 			Hashtable h1 = new Hashtable();
312 			for (int i = 0; i < c1.Length; i++) {
313 				h1[c1[i]] = c2[i];
314 			}
315 			Hashtable h2 = (Hashtable)h1.Clone();
316 			Assert.IsNotNull (h2, "got no clone!");
317 			Assert.IsNotNull (h2[c1[0]], "clone's got nothing!");
318 			for (int i = 0; i < c1.Length; i++) {
319 				Assert.AreEqual (h1[c1[i]], h2[c1[i]], "Hashtable match");
320 			}
321 
322 			((char[])h1[c1[0]])[0] = 'z';
323 			Assert.AreEqual (h1[c1[0]], h2[c1[0]], "shallow copy");
324 
325 			// NET 2.0 stuff
326 			MyEqualityComparer a = new MyEqualityComparer ();
327 			Hashtable mh1 = new Hashtable (a);
328 			Hashtable mh1clone = (Hashtable) mh1.Clone ();
329 
330 			// warning, depends on the field name.
331 			Assert.AreEqual (GetEqualityComparer (mh1), GetEqualityComparer (mh1clone), "EqualityComparer");
332 		}
333 	}
334 
335         [Test]
TestContains()336 	public void TestContains() {
337 		{
338 			bool errorThrown = false;
339 			try {
340 				Hashtable h = new Hashtable();
341 				bool result = h.Contains(null);
342 			} catch (ArgumentNullException e) {
343 				errorThrown = true;
344 				Assert.AreEqual ("key", e.ParamName, "ParamName is not 'key'");
345 			}
346 			Assert.IsTrue (errorThrown, "null add error not thrown");
347 		}
348 		{
349 			Hashtable h = new Hashtable();
350 			for (int i = 0; i < 10000; i += 2)
351 			{
352 				h[i] = i;
353 			}
354 			for (int i = 0; i < 10000; i += 2)
355 			{
356 				Assert.IsTrue (h.Contains(i), "hashtable must contain"+i.ToString());
357 				Assert.IsTrue (!h.Contains(i+1), "hashtable does not contain "+((int)(i+1)).ToString());
358 			}
359 		}
360 	}
361 
362         [Test]
TestContainsKey()363 	public void TestContainsKey() {
364 	{
365 			bool errorThrown = false;
366 			try
367 			{
368 				Hashtable h = new Hashtable();
369 				bool result = h.Contains(null);
370 			}
371 			catch (ArgumentNullException e)
372 			{
373 				errorThrown = true;
374 				Assert.AreEqual ("key", e.ParamName, "ParamName is not 'key'");
375 			}
376 			Assert.IsTrue (errorThrown, "null add error not thrown");
377 		}
378 		{
379 			Hashtable h = new Hashtable();
380 			for (int i = 0; i < 1000; i += 2)
381 			{
382 				h[i] = i;
383 			}
384 			for (int i = 0; i < 1000; i += 2)
385 			{
386 				Assert.IsTrue (h.Contains(i), "hashtable must contain"+i.ToString());
387 				Assert.IsTrue (!h.Contains(i+1), "hashtable does not contain "+((int)(i+1)).ToString());
388 			}
389 		}
390 
391 	}
392 
393         [Test]
TestContainsValue()394 	public void TestContainsValue() {
395 		{
396 			Hashtable h = new Hashtable();
397 			h['a'] = "blue";
398 			Assert.IsTrue (h.ContainsValue("blue"), "blue? it's in there!");
399 			Assert.IsTrue (!h.ContainsValue("green"), "green? no way!");
400 			Assert.IsTrue (!h.ContainsValue(null), "null? no way!");
401 			h['b'] = null;
402 			Assert.IsTrue (h.ContainsValue(null), "null? it's in there!");
403 
404 		}
405 	}
406 
407         [Test]
TestCopyTo()408 	public void TestCopyTo() {
409 		{
410 			bool errorThrown = false;
411 			try {
412 				Hashtable h = new Hashtable();
413 				h.CopyTo(null, 0);
414 			} catch (ArgumentNullException e) {
415 				errorThrown = true;
416 				Assert.AreEqual ("array", e.ParamName, "ParamName is not \"array\"");
417 			}
418 			Assert.IsTrue (errorThrown, "null hashtable error not thrown");
419 		}
420 		{
421 			bool errorThrown = false;
422 			try {
423 				Hashtable h = new Hashtable();
424 				Object[] o = new Object[1];
425 				h.CopyTo(o, -1);
426 			} catch (ArgumentOutOfRangeException e) {
427 				errorThrown = true;
428 				Assert.AreEqual ("arrayIndex", e.ParamName, "ParamName is not \"arrayIndex\"");
429 			}
430 			Assert.IsTrue (errorThrown, "out of range error not thrown");
431 		}
432 		{
433 			bool errorThrown = false;
434 			try {
435 				Hashtable h = new Hashtable();
436 				Object[,] o = new Object[1,1];
437 				h.CopyTo(o, 1);
438 			} catch (ArgumentException) {
439 				errorThrown = true;
440 			}
441 			Assert.IsTrue (errorThrown, "multi-dim array error not thrown");
442 		}
443 		{
444 			bool errorThrown = false;
445 			try {
446 				Hashtable h = new Hashtable();
447 				h['a'] = 1; // no error if table is empty
448 				Object[] o = new Object[5];
449 				h.CopyTo(o, 5);
450 			} catch (ArgumentException) {
451 				errorThrown = true;
452 			}
453 			Assert.IsTrue (errorThrown, "no room in array error not thrown");
454 		}
455 		{
456 			bool errorThrown = false;
457 			try {
458 				Hashtable h = new Hashtable();
459 				h['a'] = 1;
460 				h['b'] = 2;
461 				h['c'] = 2;
462 				Object[] o = new Object[2];
463 				h.CopyTo(o, 0);
464 			} catch (ArgumentException) {
465 				errorThrown = true;
466 			}
467 			Assert.IsTrue (errorThrown, "table too big error not thrown");
468 		}
469 		{
470 			bool errorThrown = false;
471 			try {
472 				Hashtable h = new Hashtable();
473 				h["blue"] = 1;
474 				h["green"] = 2;
475 				h["red"] = 3;
476 				Char[] o = new Char[3];
477 				h.CopyTo(o, 0);
478 			} catch (InvalidCastException) {
479 				errorThrown = true;
480 			}
481 			Assert.IsTrue (errorThrown, "invalid cast error not thrown");
482 		}
483 
484 		{
485 			Hashtable h = new Hashtable();
486 			h['a'] = 1;
487 			h['b'] = 2;
488 			DictionaryEntry[] o = new DictionaryEntry[2];
489 			h.CopyTo(o,0);
490 			Assert.AreEqual ('a', o[0].Key, "first copy fine.");
491 			Assert.AreEqual (1, o[0].Value, "first copy fine.");
492 			Assert.AreEqual ('b', o[1].Key, "second copy fine.");
493 			Assert.AreEqual (2, o[1].Value, "second copy fine.");
494 		}
495 	}
496 
497         [Test]
TestGetEnumerator()498 	public void TestGetEnumerator() {
499 		String[] s1 = {"this", "is", "a", "test"};
500 		Char[] c1 = {'a', 'b', 'c', 'd'};
501 		Hashtable h1 = new Hashtable();
502 		for (int i = 0; i < s1.Length; i++) {
503 			h1[s1[i]] = c1[i];
504 		}
505 		IDictionaryEnumerator en = h1.GetEnumerator();
506 		Assert.IsNotNull (en, "No enumerator");
507 
508 		for (int i = 0; i < s1.Length; i++) {
509 			en.MoveNext();
510 			Assert.IsTrue (Array.IndexOf(s1, en.Key) >= 0, "Not enumerating for " + en.Key);
511 			Assert.IsTrue (Array.IndexOf(c1, en.Value) >= 0, "Not enumerating for " + en.Value);
512 		}
513 	}
514 
515 	[Test]
TestSerialization()516 	public void TestSerialization () {
517 		Hashtable table1 = new Hashtable();
518 		Hashtable table2;
519 		Stream str = new MemoryStream ();
520 		BinaryFormatter formatter = new BinaryFormatter();
521 
522 		for (int i = 0; i < 100; i++)
523 			table1[i] = "TestString Key: " + i.ToString();
524 
525 		formatter.Serialize (str, table1);
526 		str.Position = 0;
527 		table2 = (Hashtable) formatter.Deserialize (str);
528 
529 		bool result;
530 		foreach (DictionaryEntry de in table1)
531 			Assert.AreEqual (table2 [de.Key], de.Value);
532 	}
533 
534 	[Test]
TestSerialization2()535 	public void TestSerialization2 () {
536 		// Test from bug #70570
537 		MemoryStream stream = new MemoryStream();
538 		BinaryFormatter formatter = new BinaryFormatter();
539 
540 		Hashtable table = new Hashtable();
541 		table.Add (new Bug(), "Hello");
542 
543 		formatter.Serialize(stream, table);
544 		stream.Position = 0;
545 		table = (Hashtable) formatter.Deserialize(stream);
546 		Assert.AreEqual (1, table.Count, "#1");
547 	}
548 
549         [Test]
TestRemove()550 	public void TestRemove() {
551 		{
552 			bool errorThrown = false;
553 			try {
554 				Hashtable h = new Hashtable();
555 				h.Remove(null);
556 			} catch (ArgumentNullException e) {
557 				errorThrown = true;
558 				Assert.AreEqual ("key", e.ParamName, "ParamName is not \"key\"");
559 			}
560 			Assert.IsTrue (errorThrown, "null hashtable error not thrown");
561 		}
562 		{
563 			string[] keys = {"this", "is", "a", "test"};
564 			char[] values = {'a', 'b', 'c', 'd'};
565 			Hashtable h = new Hashtable();
566 			for (int i = 0; i < keys.Length; i++) {
567 				h[keys[i]] = values[i];
568 			}
569 			Assert.AreEqual (4, h.Count, "not enough in table");
570 			h.Remove("huh?");
571 			Assert.AreEqual (4, h.Count, "not enough in table");
572 			h.Remove("this");
573 			Assert.AreEqual (3, h.Count, "Wrong count in table");
574 			h.Remove("this");
575 			Assert.AreEqual (3, h.Count, "Wrong count in table");
576 		}
577 	}
578 
579         [Test]
TestSynchronized()580 	public void TestSynchronized() {
581 		{
582 			bool errorThrown = false;
583 			try {
584 				Hashtable h = Hashtable.Synchronized(null);
585 			} catch (ArgumentNullException e) {
586 				errorThrown = true;
587 				Assert.AreEqual ("table", e.ParamName, "ParamName is not \"table\"");
588 			}
589 			Assert.IsTrue (errorThrown, "null hashtable error not thrown");
590 		}
591 		{
592 			Hashtable h = new Hashtable();
593 			Assert.IsTrue (!h.IsSynchronized, "hashtable not synced by default");
594 			Hashtable h2 = Hashtable.Synchronized(h);
595 			Assert.IsTrue (h2.IsSynchronized, "hashtable should by synced");
596 		}
597 	}
598 
599 
600 	protected Hashtable ht;
601 	private static Random rnd;
602 
603 	[SetUp]
SetUp()604 	public void SetUp() {
605 		ht=new Hashtable();
606 		rnd=new Random();
607 	}
608 
SetDefaultData()609 	private void SetDefaultData() {
610 		ht.Clear();
611 		ht.Add("k1","another");
612 		ht.Add("k2","yet");
613 		ht.Add("k3","hashtable");
614 	}
615 
616         [Test]
TestAddRemoveClear()617 	public void TestAddRemoveClear() {
618 		ht.Clear();
619 		Assert.IsTrue (ht.Count==0);
620 
621 		SetDefaultData();
622 		Assert.IsTrue (ht.Count==3);
623 
624 		bool thrown=false;
625 		try {
626 			ht.Add("k2","cool");
627 		} catch (ArgumentException) {thrown=true;}
628 		Assert.IsTrue (thrown, "Must throw ArgumentException!");
629 
630 		ht["k2"]="cool";
631 		Assert.IsTrue (ht.Count==3);
632 		Assert.IsTrue (ht["k2"].Equals("cool"));
633 
634 	}
635 
636         [Test]
TestCopyTo2()637 	public void TestCopyTo2() {
638 		SetDefaultData();
639 		Object[] entries=new Object[ht.Count];
640 		ht.CopyTo(entries,0);
641 		Assert.IsTrue (entries[0] is DictionaryEntry, "Not an entry.");
642 	}
643 
644 	[Test]
CopyTo_Empty()645 	public void CopyTo_Empty ()
646 	{
647 		Hashtable ht = new Hashtable ();
648 		Assert.AreEqual (0, ht.Count, "Count");
649 		object[] array = new object [ht.Count];
650 		ht.CopyTo (array, 0);
651 	}
652 
653         [Test]
TestUnderHeavyLoad()654 	public void TestUnderHeavyLoad() {
655 		ht.Clear();
656 		int max=100000;
657 		String[] cache=new String[max*2];
658 		int n=0;
659 
660 		for (int i=0;i<max;i++) {
661 			int id=rnd.Next()&0xFFFF;
662 			String key=""+id+"-key-"+id;
663 			String val="value-"+id;
664 			if (ht[key]==null) {
665 				ht[key]=val;
666 				cache[n]=key;
667 				cache[n+max]=val;
668 				n++;
669 			}
670 		}
671 
672 		Assert.IsTrue (ht.Count==n);
673 
674 		for (int i=0;i<n;i++) {
675 			String key=cache[i];
676 			String val=ht[key] as String;
677 			String err="ht[\""+key+"\"]=\""+val+
678 				"\", expected \""+cache[i+max]+"\"";
679 			Assert.IsTrue (val!=null && val.Equals(cache[i+max]), err);
680 		}
681 
682 		int r1=(n/3);
683 		int r2=r1+(n/5);
684 
685 		for (int i=r1;i<r2;i++) {
686 			ht.Remove(cache[i]);
687 		}
688 
689 
690 		for (int i=0;i<n;i++) {
691 			if (i>=r1 && i<r2) {
692 				Assert.IsTrue (ht[cache[i]]==null);
693 			} else {
694 				String key=cache[i];
695 				String val=ht[key] as String;
696 				String err="ht[\""+key+"\"]=\""+val+
697 					"\", expected \""+cache[i+max]+"\"";
698 				Assert.IsTrue (val!=null && val.Equals(cache[i+max]), err);
699 			}
700 		}
701 
702 		ICollection keys=ht.Keys;
703 		int nKeys=0;
704 		foreach (Object key in keys) {
705 			Assert.IsTrue ((key as String) != null);
706 			nKeys++;
707 		}
708 		Assert.IsTrue (nKeys==ht.Count);
709 
710 
711 		ICollection vals=ht.Values;
712 		int nVals=0;
713 		foreach (Object val in vals) {
714 			Assert.IsTrue ((val as String) != null);
715 			nVals++;
716 		}
717 		Assert.IsTrue (nVals==ht.Count);
718 
719 	}
720 
721 
722 	/// <summary>
723 	///  Test hashtable with CaseInsensitiveHashCodeProvider
724 	///  and CaseInsensitive comparer.
725 	/// </summary>
726         [Test]
TestCaseInsensitive()727 	public void TestCaseInsensitive ()
728 	{
729 		// Not very meaningfull test, just to make
730 		// sure that hcp is set properly set.
731 		Hashtable ciHashtable = new Hashtable(11,1.0f,CaseInsensitiveHashCodeProvider.Default,CaseInsensitiveComparer.Default);
732 		ciHashtable ["key1"] = "value";
733 		ciHashtable ["key2"] = "VALUE";
734 		Assert.IsTrue (ciHashtable ["key1"].Equals ("value"));
735 		Assert.IsTrue (ciHashtable ["key2"].Equals ("VALUE"));
736 
737 		ciHashtable ["KEY1"] = "new_value";
738 		Assert.IsTrue (ciHashtable ["key1"].Equals ("new_value"));
739 
740 	}
741 
742         [Test]
TestCopyConstructor()743 	public void TestCopyConstructor ()
744 	{
745 		SetDefaultData ();
746 
747 		Hashtable htCopy = new Hashtable (ht);
748 
749 		Assert.IsTrue (ht.Count == htCopy.Count);
750 	}
751 
752         [Test]
TestEnumerator()753 	public void TestEnumerator ()
754 	{
755 		SetDefaultData ();
756 
757 		IEnumerator e = ht.GetEnumerator ();
758 
759 		while (e.MoveNext ()) {}
760 
761 		Assert.IsTrue (!e.MoveNext ());
762 
763 	}
764 
765 	[Test]
766 	[ExpectedException (typeof (ArgumentNullException))]
GetObjectData_NullSerializationInfo()767 	public void GetObjectData_NullSerializationInfo ()
768 	{
769 		SetDefaultData ();
770 		ht.GetObjectData (null, new StreamingContext ());
771 	}
772 
773 	// bug #75790
774 	[Test]
775 	[Category ("NotDotNet")] // .NET raises InvalidOperationException.
SyncHashtable_ICollectionsGetEnumerator()776 	public void SyncHashtable_ICollectionsGetEnumerator ()
777 	{
778 		Hashtable hashtable = Hashtable.Synchronized (new Hashtable ());
779 		hashtable["a"] = 1;
780 		//IEnumerator e = (hashtable.Clone() as
781 		IEnumerator e = (hashtable as ICollection).GetEnumerator ();
782 		//e.Reset();
783 		e.MoveNext ();
784 		DictionaryEntry de = (DictionaryEntry) e.Current;
785 	}
786 
787 	[Test]
SerializableSubClasses()788 	public void SerializableSubClasses ()
789 	{
790 		Hashtable ht = new Hashtable ();
791 		// see bug #76300
792 		Assert.IsTrue (ht.Keys.GetType ().IsSerializable, "Keys.IsSerializable");
793 		Assert.IsTrue (ht.Values.GetType ().IsSerializable, "Values.IsSerializable");
794 		Assert.IsTrue (ht.GetEnumerator ().GetType ().IsSerializable, "GetEnumerator.IsSerializable");
795 		Assert.IsTrue (Hashtable.Synchronized (ht).GetType ().IsSerializable, "Synchronized.IsSerializable");
796 	}
797 
798 	[Test]
TestHashtableWithCustomComparer()799 	public void TestHashtableWithCustomComparer ()
800 	{
801 		// see bug #324761
802 		IDHashtable dd = new IDHashtable ();
803 		Random r = new Random (1000);
804 		for (int n = 0; n < 10000; n++) {
805 			int v = r.Next (0, 1000);
806 			dd [v] = v;
807 			v = r.Next (0, 1000);
808 			dd.Remove (v);
809 		}
810 	}
811 
812 	[Test]
HashtableCopyWithCustomComparer()813 	public void HashtableCopyWithCustomComparer ()
814 	{
815 		var ht = new Hashtable ();
816 		ht.Add ("a", "b");
817 		try {
818 			new Hashtable (ht, new IEqualityComparer_ApplicationException ());
819 			Assert.Fail ("custom comparer not used");
820 		} catch (ApplicationException) {
821 
822 		}
823 	}
824 }
825 
826 class IDHashtable : Hashtable {
827 
828 	class IDComparer : IComparer {
Compare(object x, object y)829 		public int Compare (object x, object y)
830 		{
831 			if ((int) x == (int) y)
832 				return 0;
833 			else
834 				return 1;
835 		}
836 	}
837 
838 	class IDHashCodeProvider : IHashCodeProvider {
GetHashCode(object o)839 		public int GetHashCode (object o)
840 		{
841 			return (int) o;
842 		}
843 	}
844 
IDHashtable()845 	public IDHashtable ()
846 		: base (new IDHashCodeProvider (),
847 				new IDComparer ())
848 	{
849 	}
850 }
851 
852 [Serializable]
853 public class Bug :ISerializable {
854 
855 	[Serializable]
856 	private sealed class InnerClassSerializationHelper : IObjectReference {
GetRealObject( StreamingContext context )857 		public object GetRealObject( StreamingContext context )
858 		{
859 			return new Bug();
860 		}
861 	};
862 
ISerializable.GetObjectData(SerializationInfo info, StreamingContext context )863 	void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context )
864 	{
865 		info.SetType( typeof(InnerClassSerializationHelper) );
866 	}
867 };
868 
869 	class IEqualityComparer_ApplicationException : IEqualityComparer
870 	{
Equals(object x, object y)871 		public new bool Equals (object x, object y)
872 		{
873 			return false;
874 		}
875 
GetHashCode(object obj)876 		public int GetHashCode (object obj)
877 		{
878 			throw new ApplicationException ();
879 		}
880 	}
881 
882 }
883