1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *   http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package org.apache.harmony.tests.java.util;
19 
20 import tests.support.Support_MapTest2;
21 import tests.support.Support_UnmodifiableCollectionTest;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collection;
25 import java.util.ConcurrentModificationException;
26 import java.util.Enumeration;
27 import java.util.HashSet;
28 import java.util.Hashtable;
29 import java.util.Iterator;
30 import java.util.Map;
31 import java.util.NoSuchElementException;
32 import java.util.Set;
33 import java.util.TreeMap;
34 import java.util.Vector;
35 
36 public class HashtableTest extends junit.framework.TestCase {
37 
38     private Hashtable ht10;
39 
40     private Hashtable ht100;
41 
42     private Hashtable htfull;
43 
44     private Vector keyVector;
45 
46     private Vector elmVector;
47 
48     private String h10sVal;
49 
50     /**
51      * java.util.Hashtable#Hashtable()
52      */
test_Constructor()53     public void test_Constructor() {
54         // Test for method java.util.Hashtable()
55         new Support_MapTest2(new Hashtable()).runTest();
56 
57         Hashtable h = new Hashtable();
58 
59         assertEquals("Created incorrect hashtable", 0, h.size());
60     }
61 
62     /**
63      * java.util.Hashtable#Hashtable(int)
64      */
test_ConstructorI()65     public void test_ConstructorI() {
66         // Test for method java.util.Hashtable(int)
67         Hashtable h = new Hashtable(9);
68 
69         assertEquals("Created incorrect hashtable", 0, h.size());
70 
71         Hashtable empty = new Hashtable(0);
72         assertNull("Empty hashtable access", empty.get("nothing"));
73         empty.put("something", "here");
74         assertTrue("cannot get element", empty.get("something") == "here");
75     }
76 
77     /**
78      * java.util.Hashtable#Hashtable(int, float)
79      */
test_ConstructorIF()80     public void test_ConstructorIF() {
81         // Test for method java.util.Hashtable(int, float)
82         Hashtable h = new java.util.Hashtable(10, 0.5f);
83         assertEquals("Created incorrect hashtable", 0, h.size());
84 
85         Hashtable empty = new Hashtable(0, 0.75f);
86         assertNull("Empty hashtable access", empty.get("nothing"));
87         empty.put("something", "here");
88         assertTrue("cannot get element", empty.get("something") == "here");
89 
90         try {
91             new Hashtable(-1, 0.75f);
92             fail("IllegalArgumentException expected");
93         } catch (IllegalArgumentException e) {
94             //expected
95         }
96 
97         try {
98             new Hashtable(0, -0.75f);
99             fail("IllegalArgumentException expected");
100         } catch (IllegalArgumentException e) {
101             //expected
102         }
103     }
104 
105     /**
106      * java.util.Hashtable#Hashtable(java.util.Map)
107      */
test_ConstructorLjava_util_Map()108     public void test_ConstructorLjava_util_Map() {
109         // Test for method java.util.Hashtable(java.util.Map)
110         Map map = new TreeMap();
111         Object firstVal = "Gabba";
112         Object secondVal = Integer.valueOf(5);
113         map.put("Gah", firstVal);
114         map.put("Ooga", secondVal);
115         Hashtable ht = new Hashtable(map);
116         assertTrue("a) Incorrect Hashtable constructed",
117                 ht.get("Gah") == firstVal);
118         assertTrue("b) Incorrect Hashtable constructed",
119                 ht.get("Ooga") == secondVal);
120 
121         try {
122             new Hashtable(null);
123             fail("NullPointerException expected");
124         } catch (NullPointerException e) {
125             //expected
126         }
127     }
128 
test_HashTable_Constructor()129     public void test_HashTable_Constructor() {
130         Hashtable hashTable = new Hashtable();
131         hashTable.put(hashTable, hashTable.keySet());
132         new Hashtable(hashTable);
133     }
134 
135     /**
136      * java.util.Hashtable#clear()
137      */
test_clear()138     public void test_clear() {
139         // Test for method void java.util.Hashtable.clear()
140         Hashtable h = hashtableClone(htfull);
141         h.clear();
142         assertEquals("Hashtable was not cleared", 0, h.size());
143         Enumeration el = h.elements();
144         Enumeration keys = h.keys();
145         assertTrue("Hashtable improperly cleared", !el.hasMoreElements()
146                 && !(keys.hasMoreElements()));
147     }
148 
149     /**
150      * java.util.Hashtable#clone()
151      */
test_clone()152     public void test_clone() {
153         // Test for method java.lang.Object java.util.Hashtable.clone()
154 
155         Hashtable h = (Hashtable) htfull.clone();
156         assertTrue("Clone different size than original", h.size() == htfull
157                 .size());
158 
159         Enumeration org = htfull.keys();
160         Enumeration cpy = h.keys();
161 
162         String okey, ckey;
163         while (org.hasMoreElements()) {
164             assertTrue("Key comparison failed", (okey = (String) org
165                     .nextElement()).equals(ckey = (String) cpy.nextElement()));
166             assertTrue("Value comparison failed", ((String) htfull.get(okey))
167                     .equals((String) h.get(ckey)));
168         }
169         assertTrue("Copy has more keys than original", !cpy.hasMoreElements());
170     }
171 
172     /**
173      * java.util.Hashtable#contains(java.lang.Object)
174      */
test_containsLjava_lang_Object()175     public void test_containsLjava_lang_Object() {
176         // Test for method boolean
177         // java.util.Hashtable.contains(java.lang.Object)
178         assertTrue("Element not found", ht10.contains("Val 7"));
179         assertTrue("Invalid element found", !ht10.contains("ZZZZZZZZZZZZZZZZ"));
180 
181         try {
182             ht10.contains(null);
183             fail("NullPointerException expected");
184         } catch (NullPointerException e) {
185             //expected
186         }
187     }
188 
189     /**
190      * java.util.Hashtable#containsKey(java.lang.Object)
191      */
test_containsKeyLjava_lang_Object()192     public void test_containsKeyLjava_lang_Object() {
193         // Test for method boolean
194         // java.util.Hashtable.containsKey(java.lang.Object)
195 
196         assertTrue("Failed to find key", htfull.containsKey("FKey 4"));
197         assertTrue("Failed to find key", !htfull.containsKey("FKey 99"));
198 
199         try {
200             htfull.containsKey(null);
201             fail("NullPointerException expected");
202         } catch (NullPointerException e) {
203             //expected
204         }
205     }
206 
207     /**
208      * java.util.Hashtable#containsValue(java.lang.Object)
209      */
test_containsValueLjava_lang_Object()210     public void test_containsValueLjava_lang_Object() {
211         // Test for method boolean
212         // java.util.Hashtable.containsValue(java.lang.Object)
213         Enumeration e = elmVector.elements();
214         while (e.hasMoreElements())
215             assertTrue("Returned false for valid value", ht10.containsValue(e
216                     .nextElement()));
217         assertTrue("Returned true for invalid value", !ht10
218                 .containsValue(new Object()));
219 
220         try {
221             ht10.containsValue(null);
222             fail("NullPointerException expected");
223         } catch (NullPointerException ee) {
224             //expected
225         }
226     }
227 
228     /**
229      * java.util.Hashtable#elements()
230      */
test_elements()231     public void test_elements() {
232         // Test for method java.util.Enumeration java.util.Hashtable.elements()
233         Enumeration elms = ht10.elements();
234         int i = 0;
235         while (elms.hasMoreElements()) {
236             String s = (String) elms.nextElement();
237             assertTrue("Missing key from enumeration", elmVector.contains(s));
238             ++i;
239         }
240 
241         assertEquals("All keys not retrieved", 10, ht10.size());
242 
243         assertFalse(elms.hasMoreElements());
244         try {
245             elms.nextElement();
246             fail("should throw NoSuchElementException");
247         } catch (NoSuchElementException e) {
248             // Expected
249         }
250     }
251 
252 // BEGIN Android-removed
253 // implementation dependent
254 //    /**
255 //     * java.util.Hashtable#elements()
256 //     */
257 //    public void test_elements_subtest0() {
258 //        // this is the reference implementation behavior
259 //        final Hashtable ht = new Hashtable(7);
260 //        ht.put("1", "a");
261 //        // these three elements hash to the same bucket in a 7 element Hashtable
262 //        ht.put("2", "b");
263 //        ht.put("9", "c");
264 //        ht.put("12", "d");
265 //        // Hashtable looks like:
266 //        // 0: "1"
267 //        // 1: "12" -> "9" -> "2"
268 //        Enumeration en = ht.elements();
269 //        // cache the first entry
270 //        en.hasMoreElements();
271 //        ht.remove("12");
272 //        ht.remove("9");
273 //        boolean exception = false;
274 //        try {
275 //            // cached "12"
276 //            Object result = en.nextElement();
277 //            assertNull("unexpected: " + result, result);
278 //            // next is removed "9"
279 //            result = en.nextElement();
280 //            assertNull("unexpected: " + result, result);
281 //            result = en.nextElement();
282 //            assertTrue("unexpected: " + result, "b".equals(result));
283 //        } catch (NoSuchElementException e) {
284 //            exception = true;
285 //        }
286 //        assertTrue("unexpected NoSuchElementException", !exception);
287 //    }
288 // END Android-removed
289 
290     /**
291      * java.util.Hashtable#entrySet()
292      */
test_entrySet()293     public void test_entrySet() {
294         // Test for method java.util.Set java.util.Hashtable.entrySet()
295         Set s = ht10.entrySet();
296         Set s2 = new HashSet();
297         Iterator i = s.iterator();
298         while (i.hasNext())
299             s2.add(((Map.Entry) i.next()).getValue());
300         Enumeration e = elmVector.elements();
301         while (e.hasMoreElements())
302             assertTrue("Returned incorrect entry set", s2.contains(e
303                     .nextElement()));
304 // BEGIN Android-removed
305 // implementation dependent
306 //        assertEquals("Not synchronized",
307 //                "java.util.Collections$SynchronizedSet", s.getClass().getName());
308 // END Android-removed
309 
310         boolean exception = false;
311         try {
312             ((Map.Entry) ht10.entrySet().iterator().next()).setValue(null);
313         } catch (NullPointerException e1) {
314             exception = true;
315         }
316         assertTrue(
317                 "Should not be able to assign null to a Hashtable entrySet() Map.Entry",
318                 exception);
319     }
320 
321     /**
322      * java.util.Hashtable#equals(java.lang.Object)
323      */
test_equalsLjava_lang_Object()324     public void test_equalsLjava_lang_Object() {
325         // Test for method boolean java.util.Hashtable.equals(java.lang.Object)
326         Hashtable h = hashtableClone(ht10);
327         assertTrue("Returned false for equal tables", ht10.equals(h));
328         assertTrue("Returned true for unequal tables", !ht10.equals(htfull));
329     }
330 
331     /**
332      * java.util.Hashtable#get(java.lang.Object)
333      */
test_getLjava_lang_Object()334     public void test_getLjava_lang_Object() {
335         // Test for method java.lang.Object
336         // java.util.Hashtable.get(java.lang.Object)
337         Hashtable h = hashtableClone(htfull);
338         assertEquals("Could not retrieve element", "FVal 2", ((String) h.get("FKey 2"))
339                 );
340 
341 // BEGIN Android-removed
342 // implementation dependent
343 //        // Regression for HARMONY-262
344 //        ReusableKey k = new ReusableKey();
345 //        Hashtable h2 = new Hashtable();
346 //        k.setKey(1);
347 //        h2.put(k, "value1");
348 //
349 //        k.setKey(13);
350 //        assertNull(h2.get(k));
351 //
352 //        k.setKey(12);
353 //        assertNull(h2.get(k));
354 //
355 //        try {
356 //            h2.get(null);
357 //            fail("NullPointerException expected");
358 //        } catch (NullPointerException e) {
359 //            //expected
360 //        }
361 // END Android-removed
362     }
363 
364     /**
365      * java.util.Hashtable#hashCode()
366      */
test_hashCode()367     public void test_hashCode() {
368         // Test for method int java.util.Hashtable.hashCode()
369         Set entrySet = ht10.entrySet();
370         Iterator iterator = entrySet.iterator();
371         int expectedHash;
372         for (expectedHash = 0; iterator.hasNext(); expectedHash += iterator
373                 .next().hashCode())
374             ;
375         assertTrue("Incorrect hashCode returned.  Wanted: " + expectedHash
376                 + " got: " + ht10.hashCode(), expectedHash == ht10.hashCode());
377     }
378 
379     /**
380      * java.util.Hashtable#isEmpty()
381      */
test_isEmpty()382     public void test_isEmpty() {
383         // Test for method boolean java.util.Hashtable.isEmpty()
384 
385         assertTrue("isEmpty returned incorrect value", !ht10.isEmpty());
386         assertTrue("isEmpty returned incorrect value",
387                 new java.util.Hashtable().isEmpty());
388 
389         final Hashtable ht = new Hashtable();
390         ht.put("0", "");
391         Thread t1 = new Thread() {
392             public void run() {
393                 while (!ht.isEmpty())
394                     ;
395                 ht.put("final", "");
396             }
397         };
398         t1.start();
399         for (int i = 1; i < 10000; i++) {
400             synchronized (ht) {
401                 ht.remove(String.valueOf(i - 1));
402                 ht.put(String.valueOf(i), "");
403             }
404             int size;
405             if ((size = ht.size()) != 1) {
406                 String result = "Size is not 1: " + size + " " + ht;
407                 // terminate the thread
408                 ht.clear();
409                 fail(result);
410             }
411         }
412         // terminate the thread
413         ht.clear();
414     }
415 
416     /**
417      * java.util.Hashtable#keys()
418      */
test_keys()419     public void test_keys() {
420         // Test for method java.util.Enumeration java.util.Hashtable.keys()
421 
422         Enumeration keys = ht10.keys();
423         int i = 0;
424         while (keys.hasMoreElements()) {
425             String s = (String) keys.nextElement();
426             assertTrue("Missing key from enumeration", keyVector.contains(s));
427             ++i;
428         }
429 
430         assertEquals("All keys not retrieved", 10, ht10.size());
431 
432         assertFalse(keys.hasMoreElements());
433         try {
434             keys.nextElement();
435             fail("should throw NoSuchElementException");
436         } catch (NoSuchElementException e) {
437             // Expected
438         }
439     }
440 
441     /**
442      * java.util.Hashtable#keys()
443      */
test_keys_subtest0()444     public void test_keys_subtest0() {
445         // this is the reference implementation behavior
446         final Hashtable ht = new Hashtable(3);
447         ht.put("initial", "");
448         Enumeration en = ht.keys();
449         en.hasMoreElements();
450         ht.remove("initial");
451         boolean exception = false;
452         try {
453             Object result = en.nextElement();
454             assertTrue("unexpected: " + result, "initial".equals(result));
455         } catch (NoSuchElementException e) {
456             exception = true;
457         }
458         assertTrue("unexpected NoSuchElementException", !exception);
459     }
460 
461     /**
462      * java.util.Hashtable#keySet()
463      */
test_keySet()464     public void test_keySet() {
465         // Test for method java.util.Set java.util.Hashtable.keySet()
466         Set s = ht10.keySet();
467         Enumeration e = keyVector.elements();
468         while (e.hasMoreElements())
469             assertTrue("Returned incorrect key set", s
470                     .contains(e.nextElement()));
471 
472 // BEGIN Android-removed
473 // implementation dependent
474 //        assertEquals("Not synchronized",
475 //                "java.util.Collections$SynchronizedSet", s.getClass().getName());
476 // END Android-removed
477 
478         Map map = new Hashtable(101);
479         map.put(Integer.valueOf(1), "1");
480         map.put(Integer.valueOf(102), "102");
481         map.put(Integer.valueOf(203), "203");
482         Iterator it = map.keySet().iterator();
483         Integer remove1 = (Integer) it.next();
484         it.remove();
485         Integer remove2 = (Integer) it.next();
486         it.remove();
487         ArrayList list = new ArrayList(Arrays.asList(new Integer[] {
488                 Integer.valueOf(1), Integer.valueOf(102), Integer.valueOf(203) }));
489         list.remove(remove1);
490         list.remove(remove2);
491         assertTrue("Wrong result", it.next().equals(list.get(0)));
492         assertEquals("Wrong size", 1, map.size());
493         assertTrue("Wrong contents", map.keySet().iterator().next().equals(
494                 list.get(0)));
495 
496         Map map2 = new Hashtable(101);
497         map2.put(Integer.valueOf(1), "1");
498         map2.put(Integer.valueOf(4), "4");
499         Iterator it2 = map2.keySet().iterator();
500         Integer remove3 = (Integer) it2.next();
501         Integer next;
502         if (remove3.intValue() == 1)
503             next = Integer.valueOf(4);
504         else
505             next = Integer.valueOf(1);
506         it2.hasNext();
507         it2.remove();
508         assertTrue("Wrong result 2", it2.next().equals(next));
509         assertEquals("Wrong size 2", 1, map2.size());
510         assertTrue("Wrong contents 2", map2.keySet().iterator().next().equals(
511                 next));
512     }
513 
514     /**
515      * java.util.Hashtable#keySet()
516      */
test_keySet_subtest0()517     public void test_keySet_subtest0() {
518         Set s1 = ht10.keySet();
519         assertTrue("should contain key", s1.remove("Key 0"));
520         assertTrue("should not contain key", !s1.remove("Key 0"));
521 
522         final int iterations = 10000;
523         final Hashtable ht = new Hashtable();
524         Thread t1 = new Thread() {
525             public void run() {
526                 for (int i = 0; i < iterations; i++) {
527                     ht.put(String.valueOf(i), "");
528                     ht.remove(String.valueOf(i));
529                 }
530             }
531         };
532         t1.start();
533         Set set = ht.keySet();
534         for (int i = 0; i < iterations; i++) {
535             Iterator it = set.iterator();
536             try {
537                 it.next();
538                 it.remove();
539                 int size;
540                 // ensure removing with the iterator doesn't corrupt the
541                 // Hashtable
542                 if ((size = ht.size()) < 0) {
543                     fail("invalid size: " + size);
544                 }
545             } catch (NoSuchElementException e) {
546             } catch (ConcurrentModificationException e) {
547             }
548         }
549     }
550 
551 // BEGIN Android-removed
552 // implementation dependent
553 //    /**
554 //     * java.util.Hashtable#keySet()
555 //     */
556 //    public void test_keySet_subtest1() {
557 //        // this is the reference implementation behavior
558 //        final Hashtable ht = new Hashtable(7);
559 //        ht.put("1", "a");
560 //        // these three elements hash to the same bucket in a 7 element Hashtable
561 //        ht.put("2", "b");
562 //        ht.put("9", "c");
563 //        ht.put("12", "d");
564 //        // Hashtable looks like:
565 //        // 0: "1"
566 //        // 1: "12" -> "9" -> "2"
567 //        Enumeration en = ht.elements();
568 //        // cache the first entry
569 //        en.hasMoreElements();
570 //        Iterator it = ht.keySet().iterator();
571 //        // this is mostly a copy of the test in test_elements_subtest0()
572 //        // test removing with the iterator does not null the values
573 //        while (it.hasNext()) {
574 //            String key = (String) it.next();
575 //            if ("12".equals(key) || "9".equals(key)) {
576 //                it.remove();
577 //            }
578 //        }
579 //        it.remove();
580 //        boolean exception = false;
581 //        try {
582 //            // cached "12"
583 //            Object result = en.nextElement();
584 //            assertTrue("unexpected: " + result, "d".equals(result));
585 //            // next is removed "9"
586 //            result = en.nextElement();
587 //            assertTrue("unexpected: " + result, "c".equals(result));
588 //            result = en.nextElement();
589 //            assertTrue("unexpected: " + result, "b".equals(result));
590 //        } catch (NoSuchElementException e) {
591 //            exception = true;
592 //        }
593 //        assertTrue("unexpected NoSuchElementException", !exception);
594 //    }
595 // END Android-removed
596 
597     /**
598      * java.util.Hashtable#put(java.lang.Object, java.lang.Object)
599      */
test_putLjava_lang_ObjectLjava_lang_Object()600     public void test_putLjava_lang_ObjectLjava_lang_Object() {
601         // Test for method java.lang.Object
602         // java.util.Hashtable.put(java.lang.Object, java.lang.Object)
603         Hashtable h = hashtableClone(ht100);
604         Integer key = Integer.valueOf(100);
605         h.put("Value 100", key);
606         assertTrue("Key/Value not inserted", h.size() == 1 && (h.contains(key)));
607 
608         // Put into "full" table
609         h = hashtableClone(htfull);
610         h.put("Value 100", key);
611         assertTrue("Key/Value not inserted into full table", h.size() == 8
612                 && (h.contains(key)));
613 
614         try {
615             h.put(null, key);
616             fail("NullPointerException expected");
617         } catch (NullPointerException e) {
618             //expected
619         }
620 
621         try {
622             h.put("Value 100", null);
623             fail("NullPointerException expected");
624         } catch (NullPointerException e) {
625             //expected
626         }
627     }
628 
629     /**
630      * java.util.Hashtable#putAll(java.util.Map)
631      */
test_putAllLjava_util_Map()632     public void test_putAllLjava_util_Map() {
633         // Test for method void java.util.Hashtable.putAll(java.util.Map)
634         Hashtable h = new Hashtable();
635         h.putAll(ht10);
636         Enumeration e = keyVector.elements();
637         while (e.hasMoreElements()) {
638             Object x = e.nextElement();
639             assertTrue("Failed to put all elements", h.get(x).equals(
640                     ht10.get(x)));
641         }
642 
643         try {
644             h.putAll(null);
645             fail("NullPointerException expected");
646         } catch (NullPointerException ee) {
647             //expected
648         }
649     }
650 
651     /**
652      * java.util.Hashtable#remove(java.lang.Object)
653      */
test_removeLjava_lang_Object()654     public void test_removeLjava_lang_Object() {
655         // Test for method java.lang.Object
656         // java.util.Hashtable.remove(java.lang.Object)
657         Hashtable h = hashtableClone(htfull);
658         Object k = h.remove("FKey 0");
659         assertTrue("Remove failed", !h.containsKey("FKey 0") || k == null);
660         assertNull(h.remove("FKey 0"));
661 
662         try {
663             h.remove(null);
664             fail("NullPointerException expected");
665         } catch (NullPointerException e) {
666             //expected
667         }
668     }
669 
test_HashTable_remove_scenario1()670     public void test_HashTable_remove_scenario1() {
671         Hashtable hashTable = new Hashtable();
672         Set keySet = hashTable.keySet();
673         hashTable.put(hashTable, keySet);
674         hashTable.remove(hashTable);
675     }
676 
test_HashTable_remove_scenario2()677     public void test_HashTable_remove_scenario2() {
678         Hashtable hashTable = new Hashtable();
679         Set keySet = hashTable.keySet();
680         hashTable.put(hashTable, hashTable);
681         hashTable.remove(hashTable);
682     }
683 
test_HashTable_remove_scenario3()684     public void test_HashTable_remove_scenario3() {
685         Hashtable hashTable = new Hashtable();
686         Hashtable keyHashTable = new Hashtable();
687         keyHashTable.put(hashTable, keyHashTable);
688         hashTable.put(keyHashTable, hashTable);
689         hashTable.remove(keyHashTable);
690     }
691 
692     /**
693      * java.util.Hashtable#size()
694      */
test_size()695     public void test_size() {
696         // Test for method int java.util.Hashtable.size()
697         assertTrue("Returned invalid size", ht10.size() == 10
698                 && (ht100.size() == 0));
699 
700         final Hashtable ht = new Hashtable();
701         ht.put("0", "");
702         Thread t1 = new Thread() {
703             public void run() {
704                 while (ht.size() > 0)
705                     ;
706                 ht.put("final", "");
707             }
708         };
709         t1.start();
710         for (int i = 1; i < 10000; i++) {
711             synchronized (ht) {
712                 ht.remove(String.valueOf(i - 1));
713                 ht.put(String.valueOf(i), "");
714             }
715             int size;
716             if ((size = ht.size()) != 1) {
717                 String result = "Size is not 1: " + size + " " + ht;
718                 // terminate the thread
719                 ht.clear();
720                 fail(result);
721             }
722         }
723         // terminate the thread
724         ht.clear();
725     }
726 
727     /**
728      * java.util.Hashtable#toString()
729      */
test_toString()730     public void test_toString() {
731         // Test for method java.lang.String java.util.Hashtable.toString()
732         Hashtable h = new Hashtable();
733         assertEquals("Incorrect toString for Empty table",
734                 "{}", h.toString());
735 
736         h.put("one", "1");
737         h.put("two", h);
738         h.put(h, "3");
739         h.put(h, h);
740         String result = h.toString();
741         assertTrue("should contain self ref", result.indexOf("(this") > -1);
742     }
743 
744     /**
745      * java.util.Hashtable#values()
746      */
test_values()747     public void test_values() {
748         // Test for method java.util.Collection java.util.Hashtable.values()
749         Collection c = ht10.values();
750         Enumeration e = elmVector.elements();
751         while (e.hasMoreElements())
752             assertTrue("Returned incorrect values", c.contains(e.nextElement()));
753 
754 // BEGIN Android-removed
755 // implementation dependent
756 //        assertEquals("Not synchronized",
757 //                "java.util.Collections$SynchronizedCollection", c.getClass().getName());
758 // END Android-removed
759 
760         Hashtable myHashtable = new Hashtable();
761         for (int i = 0; i < 100; i++)
762             myHashtable.put(Integer.valueOf(i), Integer.valueOf(i));
763         Collection values = myHashtable.values();
764         new Support_UnmodifiableCollectionTest(
765                 "Test Returned Collection From Hashtable.values()", values)
766                 .runTest();
767         values.remove(Integer.valueOf(0));
768         assertTrue(
769                 "Removing from the values collection should remove from the original map",
770                 !myHashtable.containsValue(Integer.valueOf(0)));
771     }
772 
773     /**
774      * Regression Test for JIRA 2181
775      */
test_entrySet_remove()776     public void test_entrySet_remove() {
777         Hashtable<String, String> hashtable = new Hashtable<String, String>();
778         hashtable.put("my.nonexistent.prop", "AAA");
779         hashtable.put("parse.error", "BBB");
780         Iterator<Map.Entry<String, String>> iterator =
781                 hashtable.entrySet().iterator();
782         while (iterator.hasNext()) {
783             Map.Entry entry = iterator.next();
784             final Object value = entry.getValue();
785             if (value.equals("AAA")) {
786                 iterator.remove();
787             }
788         }
789         assertFalse(hashtable.containsKey("my.nonexistent.prop"));
790     }
791 
792     class Mock_Hashtable extends Hashtable {
793         boolean flag = false;
794 
Mock_Hashtable(int i)795         public Mock_Hashtable(int i) {
796             super(i);
797         }
798 
799         @Override
rehash()800         protected void rehash() {
801             flag = true;
802             super.rehash();
803         }
804 
isRehashed()805         public boolean isRehashed() {
806             return flag;
807         }
808     }
809 
test_rehash()810     public void test_rehash() {
811         Mock_Hashtable mht = new Mock_Hashtable(5);
812 
813         assertFalse(mht.isRehashed());
814         for(int i = 0; i < 10; i++) {
815             mht.put(i, "New value");
816         }
817         assertTrue(mht.isRehashed());
818     }
819 
820     /**
821      * java.util.Hashtable#elements()
822      * java.util.Hashtable#keys()
823      * java.util.Hashtable#keySet()
824      */
test_keys_elements_keySet_Exceptions()825     public void test_keys_elements_keySet_Exceptions() {
826         Hashtable hashTable = new Hashtable();
827         String key = "key";
828         String value = "value";
829         hashTable.put(key, value);
830 
831         Enumeration enumeration = hashTable.keys();
832         assertTrue(enumeration.hasMoreElements());
833         enumeration.nextElement();
834         assertFalse(enumeration.hasMoreElements());
835 
836         enumeration = hashTable.elements();
837         assertTrue(enumeration.hasMoreElements());
838         enumeration.nextElement();
839         assertFalse(enumeration.hasMoreElements());
840 
841         Iterator iterator = hashTable.keySet().iterator();
842         assertTrue(iterator.hasNext());
843         try {
844             iterator.remove();
845             fail("should throw IllegalStateException");
846         } catch (IllegalStateException e) {
847             // Expected
848         }
849         iterator.next();
850         iterator.remove();
851         assertFalse(iterator.hasNext());
852 
853         hashTable.clear();
854         for (int i = 0; i < 10; i++) {
855             hashTable.put(key + i, value + i);
856         }
857 
858         enumeration = hashTable.keys();
859         assertTrue(enumeration.hasMoreElements());
860         for (int i = 0; i < 10; i++) {
861             enumeration.nextElement();
862         }
863         assertFalse(enumeration.hasMoreElements());
864         try {
865             enumeration.nextElement();
866             fail("should throw NoSuchElementException");
867         } catch (NoSuchElementException e) {
868             // Expected
869         }
870 
871         enumeration = hashTable.elements();
872         assertTrue(enumeration.hasMoreElements());
873         for (int i = 0; i < 10; i++) {
874             enumeration.nextElement();
875         }
876         assertFalse(enumeration.hasMoreElements());
877         try {
878             enumeration.nextElement();
879             fail("should throw NoSuchElementException");
880         } catch (NoSuchElementException e) {
881             // Expected
882         }
883 
884         iterator = hashTable.keySet().iterator();
885         assertTrue(iterator.hasNext());
886         for (int i = 0; i < 10; i++) {
887             iterator.next();
888         }
889         assertFalse(iterator.hasNext());
890         try {
891             iterator.next();
892             fail("should throw NoSuchElementException");
893         } catch (NoSuchElementException e) {
894             // Expected
895         }
896     }
897 
test_forEach()898     public void test_forEach() throws Exception {
899         Hashtable<String, String> ht = new Hashtable<>();
900         ht.put("1", "one");
901         ht.put("2", "two");
902         ht.put("3", "three");
903         Hashtable<String, String> output = new Hashtable<>();
904 
905         ht.forEach((k,v) -> output.put(k,v));
906         assertEquals(ht, output);
907     }
908 
test_forEach_NPE()909     public void test_forEach_NPE() throws Exception {
910         Hashtable<String, String> ht = new Hashtable<>();
911         try {
912             ht.forEach(null);
913             fail();
914         } catch(NullPointerException expected) {}
915     }
916 
test_forEach_CME()917     public void test_forEach_CME() throws Exception {
918         Hashtable<String, String> ht = new Hashtable<>();
919         ht.put("one", "1");
920         ht.put("two", "2");
921         ht.put("three", "3");
922 
923         Hashtable<String, String> outputHt = new Hashtable<>();
924         try {
925             ht.forEach(new java.util.function.BiConsumer<String, String>() {
926                     @Override
927                     public void accept(String k, String v) {
928                         outputHt.put(k, v);
929                         ht.put("foo", v);
930                     }
931                 });
932             fail();
933         } catch(ConcurrentModificationException expected) {}
934         // We should get a CME and DO NOT continue forEach evaluation
935         assertEquals(1, outputHt.size());
936     }
937 
hashtableClone(Hashtable s)938     protected Hashtable hashtableClone(Hashtable s) {
939         return (Hashtable) s.clone();
940     }
941 
942     /**
943      * Sets up the fixture, for example, open a network connection. This method
944      * is called before a test is executed.
945      */
setUp()946     protected void setUp() {
947 
948         ht10 = new Hashtable(10);
949         ht100 = new Hashtable(100);
950         htfull = new Hashtable(10);
951         keyVector = new Vector(10);
952         elmVector = new Vector(10);
953 
954         for (int i = 0; i < 10; i++) {
955             ht10.put("Key " + i, "Val " + i);
956             keyVector.addElement("Key " + i);
957             elmVector.addElement("Val " + i);
958         }
959 
960         for (int i = 0; i < 7; i++)
961             htfull.put("FKey " + i, "FVal " + i);
962     }
963 
964     /**
965      * Tears down the fixture, for example, close a network connection. This
966      * method is called after a test is executed.
967      */
tearDown()968     protected void tearDown() {
969         ht10 = null;
970         ht100 = null;
971         htfull = null;
972         keyVector = null;
973         elmVector = null;
974     }
975 }
976