HashMapTest.java revision cc05ad238516f1303687aba4a978e24e57c0c07a
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
18package tests.api.java.util;
19
20import dalvik.annotation.TestTargetNew;
21import dalvik.annotation.TestTargets;
22import dalvik.annotation.TestLevel;
23import dalvik.annotation.TestTargetClass;
24
25import java.util.AbstractMap;
26import java.util.ArrayList;
27import java.util.Arrays;
28import java.util.Collection;
29import java.util.HashMap;
30import java.util.Iterator;
31import java.util.Map;
32import java.util.Set;
33import java.util.TreeMap;
34
35import tests.support.Support_MapTest2;
36import tests.support.Support_UnmodifiableCollectionTest;
37
38@TestTargetClass(HashMap.class)
39public class HashMapTest extends junit.framework.TestCase {
40    class MockMap extends AbstractMap {
41        public Set entrySet() {
42            return null;
43        }
44        public int size(){
45            return 0;
46        }
47    }
48
49    private static class MockMapNull extends AbstractMap {
50        public Set entrySet() {
51            return null;
52        }
53
54        public int size() {
55            return 10;
56        }
57    }
58
59    HashMap hm;
60
61    final static int hmSize = 1000;
62
63    static Object[] objArray;
64
65    static Object[] objArray2;
66    {
67        objArray = new Object[hmSize];
68        objArray2 = new Object[hmSize];
69        for (int i = 0; i < objArray.length; i++) {
70            objArray[i] = new Integer(i);
71            objArray2[i] = objArray[i].toString();
72        }
73    }
74
75    /**
76     * @tests java.util.HashMap#HashMap()
77     */
78    @TestTargetNew(
79        level = TestLevel.COMPLETE,
80        notes = "",
81        method = "HashMap",
82        args = {}
83    )
84    public void test_Constructor() {
85        // Test for method java.util.HashMap()
86        new Support_MapTest2(new HashMap()).runTest();
87
88        HashMap hm2 = new HashMap();
89        assertEquals("Created incorrect HashMap", 0, hm2.size());
90    }
91
92    /**
93     * @tests java.util.HashMap#HashMap(int)
94     */
95    @TestTargetNew(
96        level = TestLevel.COMPLETE,
97        notes = "",
98        method = "HashMap",
99        args = {int.class}
100    )
101    public void test_ConstructorI() {
102        // Test for method java.util.HashMap(int)
103        HashMap hm2 = new HashMap(5);
104        assertEquals("Created incorrect HashMap", 0, hm2.size());
105        try {
106            new HashMap(-1);
107            fail("IllegalArgumentException expected");
108        } catch (IllegalArgumentException e) {
109            //expected
110        }
111
112        HashMap empty = new HashMap(0);
113        assertNull("Empty hashmap access", empty.get("nothing"));
114        empty.put("something", "here");
115        assertTrue("cannot get element", empty.get("something") == "here");
116    }
117
118    /**
119     * @tests java.util.HashMap#HashMap(int, float)
120     */
121    @TestTargetNew(
122        level = TestLevel.COMPLETE,
123        notes = "",
124        method = "HashMap",
125        args = {int.class, float.class}
126    )
127    public void test_ConstructorIF() {
128        // Test for method java.util.HashMap(int, float)
129        HashMap hm2 = new HashMap(5, (float) 0.5);
130        assertEquals("Created incorrect HashMap", 0, hm2.size());
131        try {
132            new HashMap(0, 0);
133            fail("IllegalArgumentException expected");
134        } catch (IllegalArgumentException e) {
135            //expected
136        }
137
138        HashMap empty = new HashMap(0, 0.75f);
139        assertNull("Empty hashtable access", empty.get("nothing"));
140        empty.put("something", "here");
141        assertTrue("cannot get element", empty.get("something") == "here");
142    }
143
144    /**
145     * @tests java.util.HashMap#HashMap(java.util.Map)
146     */
147    @TestTargetNew(
148        level = TestLevel.COMPLETE,
149        notes = "",
150        method = "HashMap",
151        args = {java.util.Map.class}
152    )
153    public void test_ConstructorLjava_util_Map() {
154        // Test for method java.util.HashMap(java.util.Map)
155        Map myMap = new TreeMap();
156        for (int counter = 0; counter < hmSize; counter++)
157            myMap.put(objArray2[counter], objArray[counter]);
158        HashMap hm2 = new HashMap(myMap);
159        for (int counter = 0; counter < hmSize; counter++)
160            assertTrue("Failed to construct correct HashMap", hm
161                    .get(objArray2[counter]) == hm2.get(objArray2[counter]));
162
163        try {
164            Map mockMap = new MockMap();
165            hm = new HashMap(mockMap);
166            fail("Should throw NullPointerException");
167        } catch (NullPointerException e) {
168            //empty
169        }
170    }
171
172    /**
173     * @tests java.util.HashMap#clear()
174     */
175    @TestTargetNew(
176        level = TestLevel.COMPLETE,
177        notes = "",
178        method = "clear",
179        args = {}
180    )
181    public void test_clear() {
182        // Test for method void java.util.HashMap.clear()
183        hm.clear();
184        assertEquals("Clear failed to reset size", 0, hm.size());
185        for (int i = 0; i < hmSize; i++)
186            assertNull("Failed to clear all elements",
187                    hm.get(objArray2[i]));
188
189    }
190
191    /**
192     * @tests java.util.HashMap#clone()
193     */
194    @TestTargetNew(
195        level = TestLevel.COMPLETE,
196        notes = "",
197        method = "clone",
198        args = {}
199    )
200    public void test_clone() {
201        // Test for method java.lang.Object java.util.HashMap.clone()
202        HashMap hm2 = (HashMap) hm.clone();
203        assertTrue("Clone answered equivalent HashMap", hm2 != hm);
204        for (int counter = 0; counter < hmSize; counter++)
205            assertTrue("Clone answered unequal HashMap", hm
206                    .get(objArray2[counter]) == hm2.get(objArray2[counter]));
207
208        HashMap map = new HashMap();
209        map.put("key", "value");
210        // get the keySet() and values() on the original Map
211        Set keys = map.keySet();
212        Collection values = map.values();
213        assertEquals("values() does not work",
214                "value", values.iterator().next());
215        assertEquals("keySet() does not work",
216                "key", keys.iterator().next());
217        AbstractMap map2 = (AbstractMap) map.clone();
218        map2.put("key", "value2");
219        Collection values2 = map2.values();
220        assertTrue("values() is identical", values2 != values);
221        // values() and keySet() on the cloned() map should be different
222        assertEquals("values() was not cloned",
223                "value2", values2.iterator().next());
224        map2.clear();
225        map2.put("key2", "value3");
226        Set key2 = map2.keySet();
227        assertTrue("keySet() is identical", key2 != keys);
228        assertEquals("keySet() was not cloned",
229                "key2", key2.iterator().next());
230
231        // regresion test for HARMONY-4603
232        HashMap hashmap = new HashMap();
233        MockClonable mock = new MockClonable(1);
234        hashmap.put(1, mock);
235        assertEquals(1, ((MockClonable) hashmap.get(1)).i);
236        HashMap hm3 = (HashMap)hashmap.clone();
237        assertEquals(1, ((MockClonable) hm3.get(1)).i);
238        mock.i = 0;
239        assertEquals(0, ((MockClonable) hashmap.get(1)).i);
240        assertEquals(0, ((MockClonable) hm3.get(1)).i);
241    }
242
243    /**
244     * @tests java.util.HashMap#containsKey(java.lang.Object)
245     */
246    @TestTargetNew(
247        level = TestLevel.COMPLETE,
248        notes = "",
249        method = "containsKey",
250        args = {java.lang.Object.class}
251    )
252    public void test_containsKeyLjava_lang_Object() {
253        // Test for method boolean
254        // java.util.HashMap.containsKey(java.lang.Object)
255        assertTrue("Returned false for valid key", hm.containsKey(new Integer(
256                876).toString()));
257        assertTrue("Returned true for invalid key", !hm.containsKey("KKDKDKD"));
258
259        HashMap m = new HashMap();
260        m.put(null, "test");
261        assertTrue("Failed with null key", m.containsKey(null));
262        assertTrue("Failed with missing key matching null hash", !m
263                .containsKey(new Integer(0)));
264    }
265
266    /**
267     * @tests java.util.HashMap#containsValue(java.lang.Object)
268     */
269    @TestTargetNew(
270        level = TestLevel.COMPLETE,
271        notes = "",
272        method = "containsValue",
273        args = {java.lang.Object.class}
274    )
275    public void test_containsValueLjava_lang_Object() {
276        // Test for method boolean
277        // java.util.HashMap.containsValue(java.lang.Object)
278        assertTrue("Returned false for valid value", hm
279                .containsValue(new Integer(875)));
280        assertTrue("Returned true for invalid valie", !hm
281                .containsValue(new Integer(-9)));
282    }
283
284    /**
285     * @tests java.util.HashMap#entrySet()
286     */
287    @TestTargetNew(
288        level = TestLevel.COMPLETE,
289        notes = "",
290        method = "entrySet",
291        args = {}
292    )
293    public void test_entrySet() {
294        // Test for method java.util.Set java.util.HashMap.entrySet()
295        Set s = hm.entrySet();
296        Iterator i = s.iterator();
297        assertTrue("Returned set of incorrect size", hm.size() == s.size());
298        while (i.hasNext()) {
299            Map.Entry m = (Map.Entry) i.next();
300            assertTrue("Returned incorrect entry set", hm.containsKey(m
301                    .getKey())
302                    && hm.containsValue(m.getValue()));
303        }
304    }
305
306    /**
307     * @tests java.util.HashMap#get(java.lang.Object)
308     */
309    @TestTargetNew(
310        level = TestLevel.COMPLETE,
311        notes = "",
312        method = "get",
313        args = {java.lang.Object.class}
314    )
315    public void test_getLjava_lang_Object() {
316        // Test for method java.lang.Object
317        // java.util.HashMap.get(java.lang.Object)
318        assertNull("Get returned non-null for non existent key",
319                hm.get("T"));
320        hm.put("T", "HELLO");
321        assertEquals("Get returned incorrect value for existing key", "HELLO", hm.get("T")
322                );
323
324        HashMap m = new HashMap();
325        m.put(null, "test");
326        assertEquals("Failed with null key", "test", m.get(null));
327        assertNull("Failed with missing key matching null hash", m
328                .get(new Integer(0)));
329
330        // Regression for HARMONY-206
331        ReusableKey k = new ReusableKey();
332        HashMap map = new HashMap();
333        k.setKey(1);
334        map.put(k, "value1");
335
336        k.setKey(18);
337        assertNull(map.get(k));
338
339        k.setKey(17);
340        assertNull(map.get(k));
341    }
342
343    /**
344     * @tests java.util.HashMap#isEmpty()
345     */
346    @TestTargetNew(
347        level = TestLevel.COMPLETE,
348        notes = "",
349        method = "isEmpty",
350        args = {}
351    )
352    public void test_isEmpty() {
353        // Test for method boolean java.util.HashMap.isEmpty()
354        assertTrue("Returned false for new map", new HashMap().isEmpty());
355        assertTrue("Returned true for non-empty", !hm.isEmpty());
356    }
357
358    /**
359     * @tests java.util.HashMap#keySet()
360     */
361    @TestTargetNew(
362        level = TestLevel.COMPLETE,
363        notes = "",
364        method = "keySet",
365        args = {}
366    )
367    public void test_keySet() {
368        // Test for method java.util.Set java.util.HashMap.keySet()
369        Set s = hm.keySet();
370        assertTrue("Returned set of incorrect size()", s.size() == hm.size());
371        for (int i = 0; i < objArray.length; i++)
372            assertTrue("Returned set does not contain all keys", s
373                    .contains(objArray[i].toString()));
374
375        HashMap m = new HashMap();
376        m.put(null, "test");
377        assertTrue("Failed with null key", m.keySet().contains(null));
378        assertNull("Failed with null key", m.keySet().iterator().next());
379
380        Map map = new HashMap(101);
381        map.put(new Integer(1), "1");
382        map.put(new Integer(102), "102");
383        map.put(new Integer(203), "203");
384        Iterator it = map.keySet().iterator();
385        Integer remove1 = (Integer) it.next();
386        it.hasNext();
387        it.remove();
388        Integer remove2 = (Integer) it.next();
389        it.remove();
390        ArrayList list = new ArrayList(Arrays.asList(new Integer[] {
391                new Integer(1), new Integer(102), new Integer(203) }));
392        list.remove(remove1);
393        list.remove(remove2);
394        assertTrue("Wrong result", it.next().equals(list.get(0)));
395        assertEquals("Wrong size", 1, map.size());
396        assertTrue("Wrong contents", map.keySet().iterator().next().equals(
397                list.get(0)));
398
399        Map map2 = new HashMap(101);
400        map2.put(new Integer(1), "1");
401        map2.put(new Integer(4), "4");
402        Iterator it2 = map2.keySet().iterator();
403        Integer remove3 = (Integer) it2.next();
404        Integer next;
405        if (remove3.intValue() == 1)
406            next = new Integer(4);
407        else
408            next = new Integer(1);
409        it2.hasNext();
410        it2.remove();
411        assertTrue("Wrong result 2", it2.next().equals(next));
412        assertEquals("Wrong size 2", 1, map2.size());
413        assertTrue("Wrong contents 2", map2.keySet().iterator().next().equals(
414                next));
415    }
416
417    /**
418     * @tests java.util.HashMap#put(java.lang.Object, java.lang.Object)
419     */
420    @TestTargetNew(
421        level = TestLevel.COMPLETE,
422        notes = "",
423        method = "put",
424        args = {java.lang.Object.class, java.lang.Object.class}
425    )
426    public void test_putLjava_lang_ObjectLjava_lang_Object() {
427        // Test for method java.lang.Object
428        // java.util.HashMap.put(java.lang.Object, java.lang.Object)
429        hm.put("KEY", "VALUE");
430        assertEquals("Failed to install key/value pair",
431                "VALUE", hm.get("KEY"));
432
433        HashMap m = new HashMap();
434        m.put(new Short((short) 0), "short");
435        m.put(null, "test");
436        m.put(new Integer(0), "int");
437        assertEquals("Failed adding to bucket containing null", "short", m.get(
438                new Short((short) 0)));
439        assertEquals("Failed adding to bucket containing null2", "int", m.get(
440                new Integer(0)));
441    }
442
443    /**
444     * @tests java.util.HashMap#putAll(java.util.Map)
445     */
446    @TestTargetNew(
447        level = TestLevel.PARTIAL_COMPLETE,
448        notes = "Doesn't verify NullPointerException.",
449        method = "putAll",
450        args = {java.util.Map.class}
451    )
452    public void test_putAllLjava_util_Map() {
453        // Test for method void java.util.HashMap.putAll(java.util.Map)
454        HashMap hm2 = new HashMap();
455        hm2.putAll(hm);
456        for (int i = 0; i < 1000; i++)
457            assertTrue("Failed to clear all elements", hm2.get(
458                    new Integer(i).toString()).equals((new Integer(i))));
459
460        Map mockMap = new MockMap();
461        hm2 = new HashMap();
462        hm2.putAll(mockMap);
463        assertEquals("Size should be 0", 0, hm2.size());
464    }
465
466    /**
467     * @tests java.util.HashMap#putAll(java.util.Map)
468     */
469    @TestTargetNew(
470        level = TestLevel.PARTIAL_COMPLETE,
471        notes = "Verifies NullPointerException.",
472        method = "putAll",
473        args = {java.util.Map.class}
474    )
475    public void test_putAllLjava_util_Map_Null() {
476        HashMap hashMap = new HashMap();
477        try {
478            hashMap.putAll(new MockMapNull());
479            fail("Should throw NullPointerException");
480        } catch (NullPointerException e) {
481            // expected.
482        }
483
484        try {
485            hashMap = new HashMap(new MockMapNull());
486            fail("Should throw NullPointerException");
487        } catch (NullPointerException e) {
488            // expected.
489        }
490    }
491
492    /**
493     * @tests java.util.HashMap#remove(java.lang.Object)
494     */
495    @TestTargetNew(
496        level = TestLevel.COMPLETE,
497        notes = "",
498        method = "remove",
499        args = {java.lang.Object.class}
500    )
501    public void test_removeLjava_lang_Object() {
502        // Test for method java.lang.Object
503        // java.util.HashMap.remove(java.lang.Object)
504        int size = hm.size();
505        Integer y = new Integer(9);
506        Integer x = ((Integer) hm.remove(y.toString()));
507        assertTrue("Remove returned incorrect value", x.equals(new Integer(9)));
508        assertNull("Failed to remove given key", hm.get(new Integer(9)));
509        assertTrue("Failed to decrement size", hm.size() == (size - 1));
510        assertNull("Remove of non-existent key returned non-null", hm
511                .remove("LCLCLC"));
512
513        HashMap m = new HashMap();
514        m.put(null, "test");
515        assertNull("Failed with same hash as null",
516                m.remove(new Integer(0)));
517        assertEquals("Failed with null key", "test", m.remove(null));
518    }
519
520    /**
521     * @tests java.util.HashMap#size()
522     */
523    @TestTargetNew(
524        level = TestLevel.COMPLETE,
525        notes = "",
526        method = "size",
527        args = {}
528    )
529    public void test_size() {
530        // Test for method int java.util.HashMap.size()
531        assertTrue("Returned incorrect size",
532                hm.size() == (objArray.length + 2));
533    }
534
535    /**
536     * @tests java.util.HashMap#values()
537     */
538    @TestTargetNew(
539        level = TestLevel.COMPLETE,
540        notes = "",
541        method = "values",
542        args = {}
543    )
544    public void test_values() {
545        // Test for method java.util.Collection java.util.HashMap.values()
546        Collection c = hm.values();
547        assertTrue("Returned collection of incorrect size()", c.size() == hm
548                .size());
549        for (int i = 0; i < objArray.length; i++)
550            assertTrue("Returned collection does not contain all keys", c
551                    .contains(objArray[i]));
552
553        HashMap myHashMap = new HashMap();
554        for (int i = 0; i < 100; i++)
555            myHashMap.put(objArray2[i], objArray[i]);
556        Collection values = myHashMap.values();
557        new Support_UnmodifiableCollectionTest(
558                "Test Returned Collection From HashMap.values()", values)
559                .runTest();
560        values.remove(new Integer(0));
561        assertTrue(
562                "Removing from the values collection should remove from the original map",
563                !myHashMap.containsValue(new Integer(0)));
564
565    }
566
567    static class ReusableKey {
568        private int key = 0;
569
570        public void setKey(int key) {
571            this.key = key;
572        }
573
574        public int hashCode() {
575            return key;
576        }
577
578        public boolean equals(Object o) {
579            if (o == this) {
580                return true;
581            }
582            if (!(o instanceof ReusableKey)) {
583                return false;
584            }
585            return key == ((ReusableKey) o).key;
586        }
587    }
588    @TestTargetNew(
589        level = TestLevel.COMPLETE,
590        notes = "",
591        method = "hashCode",
592        args = {}
593    )
594    public void test_Map_Entry_hashCode() {
595        //Related to HARMONY-403
596        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>(10);
597        Integer key = new Integer(1);
598        Integer val = new Integer(2);
599        map.put(key, val);
600        int expected = key.hashCode() ^ val.hashCode();
601        assertEquals(expected, map.hashCode());
602        key = new Integer(4);
603        val = new Integer(8);
604        map.put(key, val);
605        expected += key.hashCode() ^ val.hashCode();
606        assertEquals(expected, map.hashCode());
607    }
608
609    class MockClonable implements Cloneable{
610        public int i;
611
612        public MockClonable(int i) {
613            this.i = i;
614        }
615
616        @Override
617        protected Object clone() throws CloneNotSupportedException {
618            return new MockClonable(i);
619        }
620    }
621
622    /**
623     * Sets up the fixture, for example, open a network connection. This method
624     * is called before a test is executed.
625     */
626    protected void setUp() {
627        hm = new HashMap();
628        for (int i = 0; i < objArray.length; i++)
629            hm.put(objArray2[i], objArray[i]);
630        hm.put("test", null);
631        hm.put(null, "test");
632    }
633
634    /**
635     * Tears down the fixture, for example, close a network connection. This
636     * method is called after a test is executed.
637     */
638    protected void tearDown() {
639    }
640}
641