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 java.io.Serializable;
21import java.util.AbstractMap;
22import java.util.ArrayList;
23import java.util.Arrays;
24import java.util.Collection;
25import java.util.HashMap;
26import java.util.IdentityHashMap;
27import java.util.Iterator;
28import java.util.Map;
29import java.util.Set;
30import java.util.TreeMap;
31
32import tests.support.Support_MapTest2;
33
34import org.apache.harmony.testframework.serialization.SerializationTest;
35
36public class IdentityHashMapTest extends junit.framework.TestCase {
37    private static final String ID = "hello";
38
39    class MockMap extends AbstractMap {
40        public Set entrySet() {
41            return null;
42        }
43        public int size(){
44            return 0;
45        }
46    }
47    /*
48     * TODO: change all the statements testing the keys and values with equals()
49     * method to check for reference equality instead
50     */
51
52    IdentityHashMap hm;
53
54    final static int hmSize = 1000;
55
56    Object[] objArray;
57
58    Object[] objArray2;
59
60    /**
61     * java.util.IdentityHashMap#IdentityHashMap()
62     */
63    public void test_Constructor() {
64        // Test for method java.util.IdentityHashMap()
65        new Support_MapTest2(new IdentityHashMap()).runTest();
66
67        IdentityHashMap hm2 = new IdentityHashMap();
68        assertEquals("Created incorrect IdentityHashMap", 0, hm2.size());
69    }
70
71    /**
72     * java.util.IdentityHashMap#IdentityHashMap(int)
73     */
74    public void test_ConstructorI() {
75        // Test for method java.util.IdentityHashMap(int)
76        IdentityHashMap hm2 = new IdentityHashMap(5);
77        assertEquals("Created incorrect IdentityHashMap", 0, hm2.size());
78        try {
79            new IdentityHashMap(-1);
80            fail("Failed to throw IllegalArgumentException for initial capacity < 0");
81        } catch (IllegalArgumentException e) {
82            //expected
83        }
84
85        IdentityHashMap empty = new IdentityHashMap(0);
86        assertNull("Empty IdentityHashMap access", empty.get("nothing"));
87        empty.put("something", "here");
88        assertTrue("cannot get element", empty.get("something") == "here");
89    }
90
91    /**
92     * java.util.IdentityHashMap#IdentityHashMap(java.util.Map)
93     */
94    public void test_ConstructorLjava_util_Map() {
95        // Test for method java.util.IdentityHashMap(java.util.Map)
96        Map myMap = new TreeMap();
97        for (int counter = 0; counter < hmSize; counter++)
98            myMap.put(objArray2[counter], objArray[counter]);
99        IdentityHashMap hm2 = new IdentityHashMap(myMap);
100        for (int counter = 0; counter < hmSize; counter++)
101            assertTrue("Failed to construct correct IdentityHashMap", hm
102                    .get(objArray2[counter]) == hm2.get(objArray2[counter]));
103
104        Map mockMap = new MockMap();
105        hm2 = new IdentityHashMap(mockMap);
106        assertEquals("Size should be 0", 0, hm2.size());
107
108        try {
109            new IdentityHashMap(null);
110            fail("NullPointerException expected");
111        } catch (NullPointerException e) {
112            //expected
113        }
114    }
115
116    /**
117     * java.util.IdentityHashMap#clear()
118     */
119    public void test_clear() {
120        // Test for method void java.util.IdentityHashMap.clear()
121        hm.clear();
122        assertEquals("Clear failed to reset size", 0, hm.size());
123        for (int i = 0; i < hmSize; i++)
124            assertNull("Failed to clear all elements",
125                    hm.get(objArray2[i]));
126
127    }
128
129    /**
130     * java.util.IdentityHashMap#clone()
131     */
132    public void test_clone() {
133        // Test for method java.lang.Object java.util.IdentityHashMap.clone()
134        IdentityHashMap hm2 = (IdentityHashMap) hm.clone();
135        assertTrue("Clone answered equivalent IdentityHashMap", hm2 != hm);
136        for (int counter = 0; counter < hmSize; counter++)
137            assertTrue("Clone answered unequal IdentityHashMap", hm
138                    .get(objArray2[counter]) == hm2.get(objArray2[counter]));
139
140        IdentityHashMap map = new IdentityHashMap();
141        map.put("key", "value");
142        // get the keySet() and values() on the original Map
143        Set keys = map.keySet();
144        Collection values = map.values();
145        assertEquals("values() does not work",
146                "value", values.iterator().next());
147        assertEquals("keySet() does not work",
148                "key", keys.iterator().next());
149        AbstractMap map2 = (AbstractMap) map.clone();
150        map2.put("key", "value2");
151        Collection values2 = map2.values();
152        assertTrue("values() is identical", values2 != values);
153        // values() and keySet() on the cloned() map should be different
154        assertEquals("values() was not cloned",
155                "value2", values2.iterator().next());
156        map2.clear();
157        map2.put("key2", "value3");
158        Set key2 = map2.keySet();
159        assertTrue("keySet() is identical", key2 != keys);
160        assertEquals("keySet() was not cloned",
161                "key2", key2.iterator().next());
162    }
163
164    /**
165     * java.util.IdentityHashMap#containsKey(java.lang.Object)
166     */
167    public void test_containsKeyLjava_lang_Object() {
168        // Test for method boolean
169        // java.util.IdentityHashMap.containsKey(java.lang.Object)
170        assertTrue("Returned false for valid key", hm
171                .containsKey(objArray2[23]));
172        assertTrue("Returned true for copy of valid key", !hm
173                .containsKey(new Integer(23).toString()));
174        assertTrue("Returned true for invalid key", !hm.containsKey("KKDKDKD"));
175
176        IdentityHashMap m = new IdentityHashMap();
177        m.put(null, "test");
178        assertTrue("Failed with null key", m.containsKey(null));
179        assertTrue("Failed with missing key matching null hash", !m
180                .containsKey(new Integer(0)));
181    }
182
183    /**
184     * java.util.IdentityHashMap#containsValue(java.lang.Object)
185     */
186    public void test_containsValueLjava_lang_Object() {
187        // Test for method boolean
188        // java.util.IdentityHashMap.containsValue(java.lang.Object)
189        assertTrue("Returned false for valid value", hm
190                .containsValue(objArray[19]));
191        assertTrue("Returned true for invalid valie", !hm
192                .containsValue(new Integer(-9)));
193    }
194
195    /**
196     * java.util.IdentityHashMap#entrySet()
197     */
198    public void test_entrySet() {
199        // Test for method java.util.Set java.util.IdentityHashMap.entrySet()
200        Set s = hm.entrySet();
201        Iterator i = s.iterator();
202        assertTrue("Returned set of incorrect size", hm.size() == s.size());
203        while (i.hasNext()) {
204            Map.Entry m = (Map.Entry) i.next();
205            assertTrue("Returned incorrect entry set", hm.containsKey(m
206                    .getKey())
207                    && hm.containsValue(m.getValue()));
208        }
209    }
210
211    /**
212     * java.util.IdentityHashMap#get(java.lang.Object)
213     */
214    public void test_getLjava_lang_Object() {
215        // Test for method java.lang.Object
216        // java.util.IdentityHashMap.get(java.lang.Object)
217        assertNull("Get returned non-null for non existent key",
218                hm.get("T"));
219        hm.put("T", "HELLO");
220        assertEquals("Get returned incorecct value for existing key", "HELLO", hm.get("T")
221                );
222
223        IdentityHashMap m = new IdentityHashMap();
224        m.put(null, "test");
225        assertEquals("Failed with null key", "test", m.get(null));
226        assertNull("Failed with missing key matching null hash", m
227                .get(new Integer(0)));
228    }
229
230    /**
231     * java.util.IdentityHashMap#isEmpty()
232     */
233    public void test_isEmpty() {
234        // Test for method boolean java.util.IdentityHashMap.isEmpty()
235        assertTrue("Returned false for new map", new IdentityHashMap()
236                .isEmpty());
237        assertTrue("Returned true for non-empty", !hm.isEmpty());
238    }
239
240    /**
241     * java.util.IdentityHashMap#keySet()
242     */
243    public void test_keySet() {
244        // Test for method java.util.Set java.util.IdentityHashMap.keySet()
245        Set s = hm.keySet();
246        assertTrue("Returned set of incorrect size()", s.size() == hm.size());
247        for (int i = 0; i < objArray.length; i++) {
248            assertTrue("Returned set does not contain all keys", s
249                    .contains(objArray2[i]));
250        }
251
252        IdentityHashMap m = new IdentityHashMap();
253        m.put(null, "test");
254        assertTrue("Failed with null key", m.keySet().contains(null));
255        assertNull("Failed with null key", m.keySet().iterator().next());
256
257        Map map = new IdentityHashMap(101);
258        map.put(new Integer(1), "1");
259        map.put(new Integer(102), "102");
260        map.put(new Integer(203), "203");
261        Iterator it = map.keySet().iterator();
262        Integer remove1 = (Integer) it.next();
263        it.hasNext();
264        it.remove();
265        Integer remove2 = (Integer) it.next();
266        it.remove();
267        ArrayList list = new ArrayList(Arrays.asList(new Integer[] {
268                new Integer(1), new Integer(102), new Integer(203) }));
269        list.remove(remove1);
270        list.remove(remove2);
271        assertTrue("Wrong result", it.next().equals(list.get(0)));
272        assertEquals("Wrong size", 1, map.size());
273        assertTrue("Wrong contents", map.keySet().iterator().next().equals(
274                list.get(0)));
275
276        Map map2 = new IdentityHashMap(101);
277        map2.put(new Integer(1), "1");
278        map2.put(new Integer(4), "4");
279        Iterator it2 = map2.keySet().iterator();
280        Integer remove3 = (Integer) it2.next();
281        Integer next;
282        if (remove3.intValue() == 1)
283            next = new Integer(4);
284        else
285            next = new Integer(1);
286        it2.hasNext();
287        it2.remove();
288        assertTrue("Wrong result 2", it2.next().equals(next));
289        assertEquals("Wrong size 2", 1, map2.size());
290        assertTrue("Wrong contents 2", map2.keySet().iterator().next().equals(
291                next));
292    }
293
294    /**
295     * java.util.IdentityHashMap#put(java.lang.Object, java.lang.Object)
296     */
297    public void test_putLjava_lang_ObjectLjava_lang_Object() {
298        // Test for method java.lang.Object
299        // java.util.IdentityHashMap.put(java.lang.Object, java.lang.Object)
300        hm.put("KEY", "VALUE");
301        assertEquals("Failed to install key/value pair",
302                "VALUE", hm.get("KEY"));
303
304        IdentityHashMap m = new IdentityHashMap();
305        Short s0 = new Short((short) 0);
306        m.put(s0, "short");
307        m.put(null, "test");
308        Integer i0 = new Integer(0);
309        m.put(i0, "int");
310        assertEquals("Failed adding to bucket containing null",
311                "short", m.get(s0));
312        assertEquals("Failed adding to bucket containing null2", "int", m.get(i0)
313                );
314    }
315
316    /**
317     * java.util.IdentityHashMap#putAll(java.util.Map)
318     */
319    public void test_putAllLjava_util_Map() {
320        // Test for method void java.util.IdentityHashMap.putAll(java.util.Map)
321        IdentityHashMap hm2 = new IdentityHashMap();
322        hm2.putAll(hm);
323        for (int i = 0; i < 1000; i++)
324            assertTrue("Failed to clear all elements", hm2.get(objArray2[i])
325                    .equals((new Integer(i))));
326
327        hm2 = new IdentityHashMap();
328        Map mockMap = new MockMap();
329        hm2.putAll(mockMap);
330        assertEquals("Size should be 0", 0, hm2.size());
331
332        try {
333            hm2.putAll(null);
334            fail("NullPointerException expected");
335        } catch (NullPointerException e) {
336            //expected
337        }
338    }
339
340    /**
341     * java.util.IdentityHashMap#remove(java.lang.Object)
342     */
343    public void test_removeLjava_lang_Object() {
344        // Test for method java.lang.Object
345        // java.util.IdentityHashMap.remove(java.lang.Object)
346        int size = hm.size();
347        Integer x = ((Integer) hm.remove(objArray2[9]));
348        assertTrue("Remove returned incorrect value", x.equals(new Integer(9)));
349        assertNull("Failed to remove given key", hm.get(objArray2[9]));
350        assertTrue("Failed to decrement size", hm.size() == (size - 1));
351        assertNull("Remove of non-existent key returned non-null", hm
352                .remove("LCLCLC"));
353
354        IdentityHashMap m = new IdentityHashMap();
355        m.put(null, "test");
356        assertNull("Failed with same hash as null",
357                m.remove(objArray[0]));
358        assertEquals("Failed with null key", "test", m.remove(null));
359    }
360
361    /**
362     * java.util.IdentityHashMap#size()
363     */
364    public void test_size() {
365        // Test for method int java.util.IdentityHashMap.size()
366        assertEquals("Returned incorrect size, ", (objArray.length + 2), hm
367                .size());
368    }
369
370    /**
371     * java.util.IdentityHashMap#equals(java.lang.Object)
372     */
373    public void test_equalsLjava_lang_Object() {
374        IdentityHashMap mapOne = new IdentityHashMap();
375        IdentityHashMap mapTwo = new IdentityHashMap();
376        IdentityHashMap mapThree = new IdentityHashMap();
377        IdentityHashMap mapFour = new IdentityHashMap();
378
379        String one = "one";
380        String alsoOne = new String(one); // use the new operator to ensure a
381        // new reference is constructed
382        String two = "two";
383        String alsoTwo = new String(two); // use the new operator to ensure a
384        // new reference is constructed
385
386        mapOne.put(one, two);
387        mapFour.put(one, two);
388
389        // these two are not equal to the above two
390        mapTwo.put(alsoOne, two);
391        mapThree.put(one, alsoTwo);
392
393        assertEquals("failure of equality of IdentityHashMaps", mapOne, mapFour);
394        assertTrue("failure of non-equality of IdentityHashMaps one and two",
395                !mapOne.equals(mapTwo));
396        assertTrue("failure of non-equality of IdentityHashMaps one and three",
397                !mapOne.equals(mapThree));
398        assertTrue("failure of non-equality of IdentityHashMaps two and three",
399                !mapTwo.equals(mapThree));
400
401        HashMap hashMapTwo = new HashMap();
402        HashMap hashMapThree = new HashMap();
403        hashMapTwo.put(alsoOne, two);
404        hashMapThree.put(one, alsoTwo);
405
406        assertTrue(
407                "failure of non-equality of IdentityHashMaps one and Hashmap two",
408                !mapOne.equals(hashMapTwo));
409        assertTrue(
410                "failure of non-equality of IdentityHashMaps one and Hashmap three",
411                !mapOne.equals(hashMapThree));
412    }
413
414    /**
415     * java.util.IdentityHashMap#values()
416     */
417    public void test_values() {
418        // Test for method java.util.Collection
419        // java.util.IdentityHashMap.values()
420        Collection c = hm.values();
421        assertTrue("Returned collection of incorrect size()", c.size() == hm
422                .size());
423        for (int i = 0; i < objArray.length; i++)
424            assertTrue("Returned collection does not contain all keys", c
425                    .contains(objArray[i]));
426
427        IdentityHashMap myIdentityHashMap = new IdentityHashMap();
428        for (int i = 0; i < 100; i++)
429            myIdentityHashMap.put(objArray2[i], objArray[i]);
430        Collection values = myIdentityHashMap.values();
431        values.remove(objArray[0]);
432        assertTrue(
433                "Removing from the values collection should remove from the original map",
434                !myIdentityHashMap.containsValue(objArray2[0]));
435
436    }
437
438    /**
439     * java.util.IdentityHashMap#Serialization()
440     */
441    public void test_Serialization() throws Exception {
442        IdentityHashMap<String, String> map = new IdentityHashMap<String, String>();
443        map.put(ID, "world");
444        // BEGIN android-added
445        // Regression test for null key in serialized IdentityHashMap (1178549)
446        // Together with this change the IdentityHashMap.golden.ser resource
447        // was replaced by a version that contains a map with a null key.
448        map.put(null, "null");
449        // END android-added
450        SerializationTest.verifySelf(map, comparator);
451        SerializationTest.verifyGolden(this, map, comparator);
452    }
453
454    /**
455     * Sets up the fixture, for example, open a network connection. This method
456     * is called before a test is executed.
457     */
458    protected void setUp() {
459        objArray = new Object[hmSize];
460        objArray2 = new Object[hmSize];
461        for (int i = 0; i < objArray.length; i++) {
462            objArray[i] = new Integer(i);
463            // android-changed: the containsKey test requires unique strings.
464            objArray2[i] = new String(objArray[i].toString());
465        }
466
467        hm = new IdentityHashMap();
468        for (int i = 0; i < objArray.length; i++)
469            hm.put(objArray2[i], objArray[i]);
470        hm.put("test", null);
471        hm.put(null, "test");
472    }
473
474    /**
475     * Tears down the fixture, for example, close a network connection. This
476     * method is called after a test is executed.
477     */
478    protected void tearDown() {
479        objArray = null;
480        objArray2 = null;
481        hm = null;
482    }
483
484    private static final SerializationTest.SerializableAssert comparator = new
485                             SerializationTest.SerializableAssert() {
486
487        public void assertDeserialized(Serializable initial, Serializable deserialized) {
488            IdentityHashMap<String, String> initialMap = (IdentityHashMap<String, String>) initial;
489            IdentityHashMap<String, String> deseriaMap = (IdentityHashMap<String, String>) deserialized;
490            assertEquals("should be equal", initialMap.size(), deseriaMap.size());
491        }
492
493    };
494}
495