001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.luni.tests.java.util;
019:
020: import java.util.ArrayList;
021: import java.util.Arrays;
022: import java.util.Collection;
023: import java.util.ConcurrentModificationException;
024: import java.util.Enumeration;
025: import java.util.HashSet;
026: import java.util.Hashtable;
027: import java.util.Iterator;
028: import java.util.Map;
029: import java.util.NoSuchElementException;
030: import java.util.Set;
031: import java.util.TreeMap;
032: import java.util.Vector;
033:
034: import tests.support.Support_MapTest2;
035: import tests.support.Support_UnmodifiableCollectionTest;
036:
037: public class HashtableTest extends junit.framework.TestCase {
038:
039: private Hashtable ht10;
040:
041: private Hashtable ht100;
042:
043: private Hashtable htfull;
044:
045: private Vector keyVector;
046:
047: private Vector elmVector;
048:
049: private String h10sVal;
050:
051: /**
052: * @tests java.util.Hashtable#Hashtable()
053: */
054: public void test_Constructor() {
055: // Test for method java.util.Hashtable()
056: new Support_MapTest2(new Hashtable()).runTest();
057:
058: Hashtable h = new Hashtable();
059:
060: assertEquals("Created incorrect hashtable", 0, h.size());
061: }
062:
063: /**
064: * @tests java.util.Hashtable#Hashtable(int)
065: */
066: public void test_ConstructorI() {
067: // Test for method java.util.Hashtable(int)
068: Hashtable h = new Hashtable(9);
069:
070: assertEquals("Created incorrect hashtable", 0, h.size());
071:
072: Hashtable empty = new Hashtable(0);
073: assertNull("Empty hashtable access", empty.get("nothing"));
074: empty.put("something", "here");
075: assertTrue("cannot get element",
076: empty.get("something") == "here");
077: }
078:
079: /**
080: * @tests java.util.Hashtable#Hashtable(int, float)
081: */
082: public void test_ConstructorIF() {
083: // Test for method java.util.Hashtable(int, float)
084: Hashtable h = new java.util.Hashtable(10, 0.5f);
085: assertEquals("Created incorrect hashtable", 0, h.size());
086:
087: Hashtable empty = new Hashtable(0, 0.75f);
088: assertNull("Empty hashtable access", empty.get("nothing"));
089: empty.put("something", "here");
090: assertTrue("cannot get element",
091: empty.get("something") == "here");
092: }
093:
094: /**
095: * @tests java.util.Hashtable#Hashtable(java.util.Map)
096: */
097: public void test_ConstructorLjava_util_Map() {
098: // Test for method java.util.Hashtable(java.util.Map)
099: Map map = new TreeMap();
100: Object firstVal = "Gabba";
101: Object secondVal = new Integer(5);
102: map.put("Gah", firstVal);
103: map.put("Ooga", secondVal);
104: Hashtable ht = new Hashtable(map);
105: assertTrue("a) Incorrect Hashtable constructed",
106: ht.get("Gah") == firstVal);
107: assertTrue("b) Incorrect Hashtable constructed",
108: ht.get("Ooga") == secondVal);
109: }
110:
111: /**
112: * @tests java.util.Hashtable#clear()
113: */
114: public void test_clear() {
115: // Test for method void java.util.Hashtable.clear()
116: Hashtable h = hashtableClone(htfull);
117: h.clear();
118: assertEquals("Hashtable was not cleared", 0, h.size());
119: Enumeration el = h.elements();
120: Enumeration keys = h.keys();
121: assertTrue("Hashtable improperly cleared", !el
122: .hasMoreElements()
123: && !(keys.hasMoreElements()));
124: }
125:
126: /**
127: * @tests java.util.Hashtable#clone()
128: */
129: public void test_clone() {
130: // Test for method java.lang.Object java.util.Hashtable.clone()
131:
132: Hashtable h = (Hashtable) htfull.clone();
133: assertTrue("Clone different size than original",
134: h.size() == htfull.size());
135:
136: Enumeration org = htfull.keys();
137: Enumeration cpy = h.keys();
138:
139: String okey, ckey;
140: while (org.hasMoreElements()) {
141: assertTrue("Key comparison failed", (okey = (String) org
142: .nextElement()).equals(ckey = (String) cpy
143: .nextElement()));
144: assertTrue("Value comparison failed", ((String) htfull
145: .get(okey)).equals((String) h.get(ckey)));
146: }
147: assertTrue("Copy has more keys than original", !cpy
148: .hasMoreElements());
149: }
150:
151: /**
152: * @tests java.util.Hashtable#contains(java.lang.Object)
153: */
154: public void test_containsLjava_lang_Object() {
155: // Test for method boolean
156: // java.util.Hashtable.contains(java.lang.Object)
157: assertTrue("Element not found", ht10.contains("Val 7"));
158: assertTrue("Invalid element found", !ht10
159: .contains("ZZZZZZZZZZZZZZZZ"));
160: }
161:
162: /**
163: * @tests java.util.Hashtable#containsKey(java.lang.Object)
164: */
165: public void test_containsKeyLjava_lang_Object() {
166: // Test for method boolean
167: // java.util.Hashtable.containsKey(java.lang.Object)
168:
169: assertTrue("Failed to find key", htfull.containsKey("FKey 4"));
170: assertTrue("Failed to find key", !htfull.containsKey("FKey 99"));
171: }
172:
173: /**
174: * @tests java.util.Hashtable#containsValue(java.lang.Object)
175: */
176: public void test_containsValueLjava_lang_Object() {
177: // Test for method boolean
178: // java.util.Hashtable.containsValue(java.lang.Object)
179: Enumeration e = elmVector.elements();
180: while (e.hasMoreElements())
181: assertTrue("Returned false for valid value", ht10
182: .containsValue(e.nextElement()));
183: assertTrue("Returned true for invalid value", !ht10
184: .containsValue(new Object()));
185: }
186:
187: /**
188: * @tests java.util.Hashtable#elements()
189: */
190: public void test_elements() {
191: // Test for method java.util.Enumeration java.util.Hashtable.elements()
192: Enumeration elms = ht10.elements();
193: int i = 0;
194: while (elms.hasMoreElements()) {
195: String s = (String) elms.nextElement();
196: assertTrue("Missing key from enumeration", elmVector
197: .contains(s));
198: ++i;
199: }
200:
201: assertEquals("All keys not retrieved", 10, ht10.size());
202: }
203:
204: /**
205: * @tests java.util.Hashtable#elements()
206: */
207: public void test_elements_subtest0() {
208: // this is the reference implementation behavior
209: final Hashtable ht = new Hashtable(7);
210: ht.put("1", "a");
211: // these three elements hash to the same bucket in a 7 element Hashtable
212: ht.put("2", "b");
213: ht.put("9", "c");
214: ht.put("12", "d");
215: // Hashtable looks like:
216: // 0: "1"
217: // 1: "12" -> "9" -> "2"
218: Enumeration en = ht.elements();
219: // cache the first entry
220: en.hasMoreElements();
221: ht.remove("12");
222: ht.remove("9");
223: boolean exception = false;
224: try {
225: // cached "12"
226: Object result = en.nextElement();
227: assertNull("unexpected: " + result, result);
228: // next is removed "9"
229: result = en.nextElement();
230: assertNull("unexpected: " + result, result);
231: result = en.nextElement();
232: assertTrue("unexpected: " + result, "b".equals(result));
233: } catch (NoSuchElementException e) {
234: exception = true;
235: }
236: assertTrue("unexpected NoSuchElementException", !exception);
237: }
238:
239: /**
240: * @tests java.util.Hashtable#entrySet()
241: */
242: public void test_entrySet() {
243: // Test for method java.util.Set java.util.Hashtable.entrySet()
244: Set s = ht10.entrySet();
245: Set s2 = new HashSet();
246: Iterator i = s.iterator();
247: while (i.hasNext())
248: s2.add(((Map.Entry) i.next()).getValue());
249: Enumeration e = elmVector.elements();
250: while (e.hasMoreElements())
251: assertTrue("Returned incorrect entry set", s2.contains(e
252: .nextElement()));
253:
254: assertEquals("Not synchronized",
255: "java.util.Collections$SynchronizedSet", s.getClass()
256: .getName());
257:
258: boolean exception = false;
259: try {
260: ((Map.Entry) ht10.entrySet().iterator().next())
261: .setValue(null);
262: } catch (NullPointerException e1) {
263: exception = true;
264: }
265: assertTrue(
266: "Should not be able to assign null to a Hashtable entrySet() Map.Entry",
267: exception);
268: }
269:
270: /**
271: * @tests java.util.Hashtable#equals(java.lang.Object)
272: */
273: public void test_equalsLjava_lang_Object() {
274: // Test for method boolean java.util.Hashtable.equals(java.lang.Object)
275: Hashtable h = hashtableClone(ht10);
276: assertTrue("Returned false for equal tables", ht10.equals(h));
277: assertTrue("Returned true for unequal tables", !ht10
278: .equals(htfull));
279: }
280:
281: /**
282: * @tests java.util.Hashtable#get(java.lang.Object)
283: */
284: public void test_getLjava_lang_Object() {
285: // Test for method java.lang.Object
286: // java.util.Hashtable.get(java.lang.Object)
287: Hashtable h = hashtableClone(htfull);
288: assertEquals("Could not retrieve element", "FVal 2",
289: ((String) h.get("FKey 2")));
290:
291: // Regression for HARMONY-262
292: ReusableKey k = new ReusableKey();
293: Hashtable h2 = new Hashtable();
294: k.setKey(1);
295: h2.put(k, "value1");
296:
297: k.setKey(13);
298: assertNull(h2.get(k));
299:
300: k.setKey(12);
301: assertNull(h2.get(k));
302: }
303:
304: /**
305: * @tests java.util.Hashtable#hashCode()
306: */
307: public void test_hashCode() {
308: // Test for method int java.util.Hashtable.hashCode()
309: Set entrySet = ht10.entrySet();
310: Iterator iterator = entrySet.iterator();
311: int expectedHash;
312: for (expectedHash = 0; iterator.hasNext(); expectedHash += iterator
313: .next().hashCode())
314: ;
315: assertTrue("Incorrect hashCode returned. Wanted: "
316: + expectedHash + " got: " + ht10.hashCode(),
317: expectedHash == ht10.hashCode());
318: }
319:
320: /**
321: * @tests java.util.Hashtable#isEmpty()
322: */
323: public void test_isEmpty() {
324: // Test for method boolean java.util.Hashtable.isEmpty()
325:
326: assertTrue("isEmpty returned incorrect value", !ht10.isEmpty());
327: assertTrue("isEmpty returned incorrect value",
328: new java.util.Hashtable().isEmpty());
329:
330: final Hashtable ht = new Hashtable();
331: ht.put("0", "");
332: Thread t1 = new Thread() {
333: public void run() {
334: while (!ht.isEmpty())
335: ;
336: ht.put("final", "");
337: }
338: };
339: t1.start();
340: for (int i = 1; i < 10000; i++) {
341: synchronized (ht) {
342: ht.remove(String.valueOf(i - 1));
343: ht.put(String.valueOf(i), "");
344: }
345: int size;
346: if ((size = ht.size()) != 1) {
347: String result = "Size is not 1: " + size + " " + ht;
348: // terminate the thread
349: ht.clear();
350: fail(result);
351: }
352: }
353: // terminate the thread
354: ht.clear();
355: }
356:
357: /**
358: * @tests java.util.Hashtable#keys()
359: */
360: public void test_keys() {
361: // Test for method java.util.Enumeration java.util.Hashtable.keys()
362:
363: Enumeration keys = ht10.keys();
364: int i = 0;
365: while (keys.hasMoreElements()) {
366: String s = (String) keys.nextElement();
367: assertTrue("Missing key from enumeration", keyVector
368: .contains(s));
369: ++i;
370: }
371:
372: assertEquals("All keys not retrieved", 10, ht10.size());
373: }
374:
375: /**
376: * @tests java.util.Hashtable#keys()
377: */
378: public void test_keys_subtest0() {
379: // this is the reference implementation behavior
380: final Hashtable ht = new Hashtable(3);
381: ht.put("initial", "");
382: Enumeration en = ht.keys();
383: en.hasMoreElements();
384: ht.remove("initial");
385: boolean exception = false;
386: try {
387: Object result = en.nextElement();
388: assertTrue("unexpected: " + result, "initial"
389: .equals(result));
390: } catch (NoSuchElementException e) {
391: exception = true;
392: }
393: assertTrue("unexpected NoSuchElementException", !exception);
394: }
395:
396: /**
397: * @tests java.util.Hashtable#keySet()
398: */
399: public void test_keySet() {
400: // Test for method java.util.Set java.util.Hashtable.keySet()
401: Set s = ht10.keySet();
402: Enumeration e = keyVector.elements();
403: while (e.hasMoreElements())
404: assertTrue("Returned incorrect key set", s.contains(e
405: .nextElement()));
406:
407: assertEquals("Not synchronized",
408: "java.util.Collections$SynchronizedSet", s.getClass()
409: .getName());
410:
411: Map map = new Hashtable(101);
412: map.put(new Integer(1), "1");
413: map.put(new Integer(102), "102");
414: map.put(new Integer(203), "203");
415: Iterator it = map.keySet().iterator();
416: Integer remove1 = (Integer) it.next();
417: it.remove();
418: Integer remove2 = (Integer) it.next();
419: it.remove();
420: ArrayList list = new ArrayList(Arrays.asList(new Integer[] {
421: new Integer(1), new Integer(102), new Integer(203) }));
422: list.remove(remove1);
423: list.remove(remove2);
424: assertTrue("Wrong result", it.next().equals(list.get(0)));
425: assertEquals("Wrong size", 1, map.size());
426: assertTrue("Wrong contents", map.keySet().iterator().next()
427: .equals(list.get(0)));
428:
429: Map map2 = new Hashtable(101);
430: map2.put(new Integer(1), "1");
431: map2.put(new Integer(4), "4");
432: Iterator it2 = map2.keySet().iterator();
433: Integer remove3 = (Integer) it2.next();
434: Integer next;
435: if (remove3.intValue() == 1)
436: next = new Integer(4);
437: else
438: next = new Integer(1);
439: it2.hasNext();
440: it2.remove();
441: assertTrue("Wrong result 2", it2.next().equals(next));
442: assertEquals("Wrong size 2", 1, map2.size());
443: assertTrue("Wrong contents 2", map2.keySet().iterator().next()
444: .equals(next));
445: }
446:
447: /**
448: * @tests java.util.Hashtable#keySet()
449: */
450: public void test_keySet_subtest0() {
451: Set s1 = ht10.keySet();
452: assertTrue("should contain key", s1.remove("Key 0"));
453: assertTrue("should not contain key", !s1.remove("Key 0"));
454:
455: final int iterations = 10000;
456: final Hashtable ht = new Hashtable();
457: Thread t1 = new Thread() {
458: public void run() {
459: for (int i = 0; i < iterations; i++) {
460: ht.put(String.valueOf(i), "");
461: ht.remove(String.valueOf(i));
462: }
463: }
464: };
465: t1.start();
466: Set set = ht.keySet();
467: for (int i = 0; i < iterations; i++) {
468: Iterator it = set.iterator();
469: try {
470: it.next();
471: it.remove();
472: int size;
473: // ensure removing with the iterator doesn't corrupt the
474: // Hashtable
475: if ((size = ht.size()) < 0) {
476: fail("invalid size: " + size);
477: }
478: } catch (NoSuchElementException e) {
479: } catch (ConcurrentModificationException e) {
480: }
481: }
482: }
483:
484: /**
485: * @tests java.util.Hashtable#keySet()
486: */
487: public void test_keySet_subtest1() {
488: // this is the reference implementation behavior
489: final Hashtable ht = new Hashtable(7);
490: ht.put("1", "a");
491: // these three elements hash to the same bucket in a 7 element Hashtable
492: ht.put("2", "b");
493: ht.put("9", "c");
494: ht.put("12", "d");
495: // Hashtable looks like:
496: // 0: "1"
497: // 1: "12" -> "9" -> "2"
498: Enumeration en = ht.elements();
499: // cache the first entry
500: en.hasMoreElements();
501: Iterator it = ht.keySet().iterator();
502: // this is mostly a copy of the test in test_elements_subtest0()
503: // test removing with the iterator does not null the values
504: while (it.hasNext()) {
505: String key = (String) it.next();
506: if ("12".equals(key) || "9".equals(key)) {
507: it.remove();
508: }
509: }
510: it.remove();
511: boolean exception = false;
512: try {
513: // cached "12"
514: Object result = en.nextElement();
515: assertTrue("unexpected: " + result, "d".equals(result));
516: // next is removed "9"
517: result = en.nextElement();
518: assertTrue("unexpected: " + result, "c".equals(result));
519: result = en.nextElement();
520: assertTrue("unexpected: " + result, "b".equals(result));
521: } catch (NoSuchElementException e) {
522: exception = true;
523: }
524: assertTrue("unexpected NoSuchElementException", !exception);
525: }
526:
527: /**
528: * @tests java.util.Hashtable#put(java.lang.Object, java.lang.Object)
529: */
530: public void test_putLjava_lang_ObjectLjava_lang_Object() {
531: // Test for method java.lang.Object
532: // java.util.Hashtable.put(java.lang.Object, java.lang.Object)
533: Hashtable h = hashtableClone(ht100);
534: Integer key = new Integer(100);
535: h.put("Value 100", key);
536: assertTrue("Key/Value not inserted", h.size() == 1
537: && (h.contains(key)));
538:
539: // Put into "full" table
540: h = hashtableClone(htfull);
541: h.put("Value 100", key);
542: assertTrue("Key/Value not inserted into full table",
543: h.size() == 8 && (h.contains(key)));
544: }
545:
546: /**
547: * @tests java.util.Hashtable#putAll(java.util.Map)
548: */
549: public void test_putAllLjava_util_Map() {
550: // Test for method void java.util.Hashtable.putAll(java.util.Map)
551: Hashtable h = new Hashtable();
552: h.putAll(ht10);
553: Enumeration e = keyVector.elements();
554: while (e.hasMoreElements()) {
555: Object x = e.nextElement();
556: assertTrue("Failed to put all elements", h.get(x).equals(
557: ht10.get(x)));
558: }
559: }
560:
561: /**
562: * @tests java.util.Hashtable#remove(java.lang.Object)
563: */
564: public void test_removeLjava_lang_Object() {
565: // Test for method java.lang.Object
566: // java.util.Hashtable.remove(java.lang.Object)
567: Hashtable h = hashtableClone(htfull);
568: Object k = h.remove("FKey 0");
569: assertTrue("Remove failed", !h.containsKey("FKey 0")
570: || k == null);
571: }
572:
573: /**
574: * @tests java.util.Hashtable#size()
575: */
576: public void test_size() {
577: // Test for method int java.util.Hashtable.size()
578: assertTrue("Returned invalid size", ht10.size() == 10
579: && (ht100.size() == 0));
580:
581: final Hashtable ht = new Hashtable();
582: ht.put("0", "");
583: Thread t1 = new Thread() {
584: public void run() {
585: while (ht.size() > 0)
586: ;
587: ht.put("final", "");
588: }
589: };
590: t1.start();
591: for (int i = 1; i < 10000; i++) {
592: synchronized (ht) {
593: ht.remove(String.valueOf(i - 1));
594: ht.put(String.valueOf(i), "");
595: }
596: int size;
597: if ((size = ht.size()) != 1) {
598: String result = "Size is not 1: " + size + " " + ht;
599: // terminate the thread
600: ht.clear();
601: fail(result);
602: }
603: }
604: // terminate the thread
605: ht.clear();
606: }
607:
608: /**
609: * @tests java.util.Hashtable#toString()
610: */
611: public void test_toString() {
612: // Test for method java.lang.String java.util.Hashtable.toString()
613: Hashtable h = new Hashtable();
614: assertEquals("Incorrect toString for Empty table", "{}", h
615: .toString());
616:
617: h.put("one", "1");
618: h.put("two", h);
619: h.put(h, "3");
620: h.put(h, h);
621: String result = h.toString();
622: assertTrue("should contain self ref",
623: result.indexOf("(this") > -1);
624: }
625:
626: /**
627: * @tests java.util.Hashtable#values()
628: */
629: public void test_values() {
630: // Test for method java.util.Collection java.util.Hashtable.values()
631: Collection c = ht10.values();
632: Enumeration e = elmVector.elements();
633: while (e.hasMoreElements())
634: assertTrue("Returned incorrect values", c.contains(e
635: .nextElement()));
636:
637: assertEquals("Not synchronized",
638: "java.util.Collections$SynchronizedCollection", c
639: .getClass().getName());
640:
641: Hashtable myHashtable = new Hashtable();
642: for (int i = 0; i < 100; i++)
643: myHashtable.put(new Integer(i), new Integer(i));
644: Collection values = myHashtable.values();
645: new Support_UnmodifiableCollectionTest(
646: "Test Returned Collection From Hashtable.values()",
647: values).runTest();
648: values.remove(new Integer(0));
649: assertTrue(
650: "Removing from the values collection should remove from the original map",
651: !myHashtable.containsValue(new Integer(0)));
652: }
653:
654: /**
655: * Regression Test for JIRA 2181
656: */
657: public void test_entrySet_remove() {
658: Hashtable<String, String> hashtable = new Hashtable<String, String>();
659: hashtable.put("my.nonexistent.prop", "AAA");
660: hashtable.put("parse.error", "BBB");
661: Iterator<Map.Entry<String, String>> iterator = hashtable
662: .entrySet().iterator();
663: while (iterator.hasNext()) {
664: Map.Entry entry = iterator.next();
665: final Object value = entry.getValue();
666: if (value.equals("AAA")) {
667: iterator.remove();
668: }
669: }
670: assertFalse(hashtable.containsKey("my.nonexistent.prop"));
671: }
672:
673: protected Hashtable hashtableClone(Hashtable s) {
674: return (Hashtable) s.clone();
675: }
676:
677: /**
678: * Sets up the fixture, for example, open a network connection. This method
679: * is called before a test is executed.
680: */
681: protected void setUp() {
682:
683: ht10 = new Hashtable(10);
684: ht100 = new Hashtable(100);
685: htfull = new Hashtable(10);
686: keyVector = new Vector(10);
687: elmVector = new Vector(10);
688:
689: for (int i = 0; i < 10; i++) {
690: ht10.put("Key " + i, "Val " + i);
691: keyVector.addElement("Key " + i);
692: elmVector.addElement("Val " + i);
693: }
694:
695: for (int i = 0; i < 7; i++)
696: htfull.put("FKey " + i, "FVal " + i);
697: }
698:
699: static class ReusableKey {
700: private int key = 0;
701:
702: public void setKey(int key) {
703: this .key = key;
704: }
705:
706: public int hashCode() {
707: return key;
708: }
709:
710: public boolean equals(Object o) {
711: if (o == this ) {
712: return true;
713: }
714: if (!(o instanceof ReusableKey)) {
715: return false;
716: }
717: return key == ((ReusableKey) o).key;
718: }
719: }
720: }
|