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 org.apache.harmony.tests.java.util;
19
20import libcore.java.util.SpliteratorTester;
21import org.apache.harmony.testframework.serialization.SerializationTest;
22import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
23import tests.support.Support_MapTest2;
24import java.io.Serializable;
25import java.util.AbstractMap;
26import java.util.ArrayList;
27import java.util.Arrays;
28import java.util.Collection;
29import java.util.Comparator;
30import java.util.ConcurrentModificationException;
31import java.util.HashMap;
32import java.util.HashSet;
33import java.util.IdentityHashMap;
34import java.util.Iterator;
35import java.util.Map;
36import java.util.Set;
37import java.util.TreeMap;
38import java.util.TreeSet;
39import java.util.function.BiFunction;
40
41public class IdentityHashMapTest extends junit.framework.TestCase {
42    private static final String ID = "hello";
43
44    class MockMap extends AbstractMap {
45        public Set entrySet() {
46            return null;
47        }
48        public int size(){
49            return 0;
50        }
51    }
52    /*
53     * TODO: change all the statements testing the keys and values with equals()
54     * method to check for reference equality instead
55     */
56
57    IdentityHashMap hm;
58
59    final static int hmSize = 1000;
60
61    Object[] objArray;
62
63    Object[] objArray2;
64
65    /**
66     * java.util.IdentityHashMap#IdentityHashMap()
67     */
68    public void test_Constructor() {
69        // Test for method java.util.IdentityHashMap()
70        new Support_MapTest2(new IdentityHashMap()).runTest();
71
72        IdentityHashMap hm2 = new IdentityHashMap();
73        assertEquals("Created incorrect IdentityHashMap", 0, hm2.size());
74    }
75
76    /**
77     * java.util.IdentityHashMap#IdentityHashMap(int)
78     */
79    public void test_ConstructorI() {
80        // Test for method java.util.IdentityHashMap(int)
81        IdentityHashMap hm2 = new IdentityHashMap(5);
82        assertEquals("Created incorrect IdentityHashMap", 0, hm2.size());
83        try {
84            new IdentityHashMap(-1);
85            fail("Failed to throw IllegalArgumentException for initial capacity < 0");
86        } catch (IllegalArgumentException e) {
87            //expected
88        }
89
90        IdentityHashMap empty = new IdentityHashMap(0);
91        assertNull("Empty IdentityHashMap access", empty.get("nothing"));
92        empty.put("something", "here");
93        assertTrue("cannot get element", empty.get("something") == "here");
94    }
95
96    /**
97     * java.util.IdentityHashMap#IdentityHashMap(java.util.Map)
98     */
99    public void test_ConstructorLjava_util_Map() {
100        // Test for method java.util.IdentityHashMap(java.util.Map)
101        Map myMap = new TreeMap();
102        for (int counter = 0; counter < hmSize; counter++)
103            myMap.put(objArray2[counter], objArray[counter]);
104        IdentityHashMap hm2 = new IdentityHashMap(myMap);
105        for (int counter = 0; counter < hmSize; counter++)
106            assertTrue("Failed to construct correct IdentityHashMap", hm
107                    .get(objArray2[counter]) == hm2.get(objArray2[counter]));
108
109        Map mockMap = new MockMap();
110        hm2 = new IdentityHashMap(mockMap);
111        assertEquals("Size should be 0", 0, hm2.size());
112
113        try {
114            new IdentityHashMap(null);
115            fail("NullPointerException expected");
116        } catch (NullPointerException e) {
117            //expected
118        }
119    }
120
121    /**
122     * java.util.IdentityHashMap#clear()
123     */
124    public void test_clear() {
125        // Test for method void java.util.IdentityHashMap.clear()
126        hm.clear();
127        assertEquals("Clear failed to reset size", 0, hm.size());
128        for (int i = 0; i < hmSize; i++)
129            assertNull("Failed to clear all elements",
130                    hm.get(objArray2[i]));
131
132    }
133
134    /**
135     * java.util.IdentityHashMap#clone()
136     */
137    public void test_clone() {
138        // Test for method java.lang.Object java.util.IdentityHashMap.clone()
139        IdentityHashMap hm2 = (IdentityHashMap) hm.clone();
140        assertTrue("Clone answered equivalent IdentityHashMap", hm2 != hm);
141        for (int counter = 0; counter < hmSize; counter++)
142            assertTrue("Clone answered unequal IdentityHashMap", hm
143                    .get(objArray2[counter]) == hm2.get(objArray2[counter]));
144
145        IdentityHashMap map = new IdentityHashMap();
146        map.put("key", "value");
147        // get the keySet() and values() on the original Map
148        Set keys = map.keySet();
149        Collection values = map.values();
150        assertEquals("values() does not work",
151                "value", values.iterator().next());
152        assertEquals("keySet() does not work",
153                "key", keys.iterator().next());
154        AbstractMap map2 = (AbstractMap) map.clone();
155        map2.put("key", "value2");
156        Collection values2 = map2.values();
157        assertTrue("values() is identical", values2 != values);
158        // values() and keySet() on the cloned() map should be different
159        assertEquals("values() was not cloned",
160                "value2", values2.iterator().next());
161        map2.clear();
162        map2.put("key2", "value3");
163        Set key2 = map2.keySet();
164        assertTrue("keySet() is identical", key2 != keys);
165        assertEquals("keySet() was not cloned",
166                "key2", key2.iterator().next());
167    }
168
169    /**
170     * java.util.IdentityHashMap#containsKey(java.lang.Object)
171     */
172    public void test_containsKeyLjava_lang_Object() {
173        // Test for method boolean
174        // java.util.IdentityHashMap.containsKey(java.lang.Object)
175        assertTrue("Returned false for valid key", hm
176                .containsKey(objArray2[23]));
177        assertTrue("Returned true for copy of valid key", !hm
178                .containsKey(new Integer(23).toString()));
179        assertTrue("Returned true for invalid key", !hm.containsKey("KKDKDKD"));
180
181        IdentityHashMap m = new IdentityHashMap();
182        m.put(null, "test");
183        assertTrue("Failed with null key", m.containsKey(null));
184        assertTrue("Failed with missing key matching null hash", !m
185                .containsKey(new Integer(0)));
186    }
187
188    /**
189     * java.util.IdentityHashMap#containsValue(java.lang.Object)
190     */
191    public void test_containsValueLjava_lang_Object() {
192        // Test for method boolean
193        // java.util.IdentityHashMap.containsValue(java.lang.Object)
194        assertTrue("Returned false for valid value", hm
195                .containsValue(objArray[19]));
196        assertTrue("Returned true for invalid valie", !hm
197                .containsValue(new Integer(-9)));
198    }
199
200    /**
201     * java.util.IdentityHashMap#entrySet()
202     */
203    public void test_entrySet() {
204        // Test for method java.util.Set java.util.IdentityHashMap.entrySet()
205        Set s = hm.entrySet();
206        Iterator i = s.iterator();
207        assertTrue("Returned set of incorrect size", hm.size() == s.size());
208        while (i.hasNext()) {
209            Map.Entry m = (Map.Entry) i.next();
210            assertTrue("Returned incorrect entry set", hm.containsKey(m
211                    .getKey())
212                    && hm.containsValue(m.getValue()));
213        }
214    }
215
216    /**
217     * java.util.IdentityHashMap#get(java.lang.Object)
218     */
219    public void test_getLjava_lang_Object() {
220        // Test for method java.lang.Object
221        // java.util.IdentityHashMap.get(java.lang.Object)
222        assertNull("Get returned non-null for non existent key",
223                hm.get("T"));
224        hm.put("T", "HELLO");
225        assertEquals("Get returned incorecct value for existing key", "HELLO", hm.get("T")
226                );
227
228        IdentityHashMap m = new IdentityHashMap();
229        m.put(null, "test");
230        assertEquals("Failed with null key", "test", m.get(null));
231        assertNull("Failed with missing key matching null hash", m
232                .get(new Integer(0)));
233    }
234
235    /**
236     * java.util.IdentityHashMap#isEmpty()
237     */
238    public void test_isEmpty() {
239        // Test for method boolean java.util.IdentityHashMap.isEmpty()
240        assertTrue("Returned false for new map", new IdentityHashMap()
241                .isEmpty());
242        assertTrue("Returned true for non-empty", !hm.isEmpty());
243    }
244
245    /**
246     * java.util.IdentityHashMap#keySet()
247     */
248    public void test_keySet() {
249        // Test for method java.util.Set java.util.IdentityHashMap.keySet()
250        Set s = hm.keySet();
251        assertTrue("Returned set of incorrect size()", s.size() == hm.size());
252        for (int i = 0; i < objArray.length; i++) {
253            assertTrue("Returned set does not contain all keys", s
254                    .contains(objArray2[i]));
255        }
256
257        IdentityHashMap m = new IdentityHashMap();
258        m.put(null, "test");
259        assertTrue("Failed with null key", m.keySet().contains(null));
260        assertNull("Failed with null key", m.keySet().iterator().next());
261
262        Map map = new IdentityHashMap(101);
263        map.put(new Integer(1), "1");
264        map.put(new Integer(102), "102");
265        map.put(new Integer(203), "203");
266        Iterator it = map.keySet().iterator();
267        Integer remove1 = (Integer) it.next();
268        it.hasNext();
269        it.remove();
270        Integer remove2 = (Integer) it.next();
271        it.remove();
272        ArrayList list = new ArrayList(Arrays.asList(new Integer[] {
273                new Integer(1), new Integer(102), new Integer(203) }));
274        list.remove(remove1);
275        list.remove(remove2);
276        assertTrue("Wrong result", it.next().equals(list.get(0)));
277        assertEquals("Wrong size", 1, map.size());
278        assertTrue("Wrong contents", map.keySet().iterator().next().equals(
279                list.get(0)));
280
281        Map map2 = new IdentityHashMap(101);
282        map2.put(new Integer(1), "1");
283        map2.put(new Integer(4), "4");
284        Iterator it2 = map2.keySet().iterator();
285        Integer remove3 = (Integer) it2.next();
286        Integer next;
287        if (remove3.intValue() == 1)
288            next = new Integer(4);
289        else
290            next = new Integer(1);
291        it2.hasNext();
292        it2.remove();
293        assertTrue("Wrong result 2", it2.next().equals(next));
294        assertEquals("Wrong size 2", 1, map2.size());
295        assertTrue("Wrong contents 2", map2.keySet().iterator().next().equals(
296                next));
297    }
298
299    /**
300     * java.util.IdentityHashMap#put(java.lang.Object, java.lang.Object)
301     */
302    public void test_putLjava_lang_ObjectLjava_lang_Object() {
303        // Test for method java.lang.Object
304        // java.util.IdentityHashMap.put(java.lang.Object, java.lang.Object)
305        hm.put("KEY", "VALUE");
306        assertEquals("Failed to install key/value pair",
307                "VALUE", hm.get("KEY"));
308
309        IdentityHashMap m = new IdentityHashMap();
310        Short s0 = new Short((short) 0);
311        m.put(s0, "short");
312        m.put(null, "test");
313        Integer i0 = new Integer(0);
314        m.put(i0, "int");
315        assertEquals("Failed adding to bucket containing null",
316                "short", m.get(s0));
317        assertEquals("Failed adding to bucket containing null2", "int", m.get(i0)
318                );
319
320        IdentityHashMap<Object, Object> map = new IdentityHashMap<Object, Object>();
321
322        // Test null as a key.
323        Object value = "Some value";
324        map.put(null, value);
325        assertSame("Assert 0: Failure getting null key", value, map.get(null));
326
327        // Test null as a value
328        Object key = "Some key";
329        map.put(key, null);
330        assertNull("Assert 1: Failure getting null value", map.get(key));
331    }
332
333    /**
334     * java.util.IdentityHashMap#putAll(java.util.Map)
335     */
336    public void test_putAllLjava_util_Map() {
337        // Test for method void java.util.IdentityHashMap.putAll(java.util.Map)
338        IdentityHashMap hm2 = new IdentityHashMap();
339        hm2.putAll(hm);
340        for (int i = 0; i < 1000; i++)
341            assertTrue("Failed to clear all elements", hm2.get(objArray2[i])
342                    .equals((new Integer(i))));
343
344        hm2 = new IdentityHashMap();
345        Map mockMap = new MockMap();
346        hm2.putAll(mockMap);
347        assertEquals("Size should be 0", 0, hm2.size());
348
349        try {
350            hm2.putAll(null);
351            fail("NullPointerException expected");
352        } catch (NullPointerException e) {
353            //expected
354        }
355    }
356
357    /**
358     * java.util.IdentityHashMap#remove(java.lang.Object)
359     */
360    public void test_removeLjava_lang_Object() {
361        // Test for method java.lang.Object
362        // java.util.IdentityHashMap.remove(java.lang.Object)
363        int size = hm.size();
364        Integer x = ((Integer) hm.remove(objArray2[9]));
365        assertTrue("Remove returned incorrect value", x.equals(new Integer(9)));
366        assertNull("Failed to remove given key", hm.get(objArray2[9]));
367        assertTrue("Failed to decrement size", hm.size() == (size - 1));
368        assertNull("Remove of non-existent key returned non-null", hm
369                .remove("LCLCLC"));
370
371        IdentityHashMap m = new IdentityHashMap();
372        m.put(null, "test");
373        assertNull("Failed with same hash as null",
374                m.remove(objArray[0]));
375        assertEquals("Failed with null key", "test", m.remove(null));
376
377        // Regression for HARMONY-37
378        IdentityHashMap<String, String> hashMap = new IdentityHashMap<String, String>();
379        hashMap.remove("absent");
380        assertEquals("Assert 0: Size is incorrect", 0, hashMap.size());
381
382        hashMap.put("key", "value");
383        hashMap.remove("key");
384        assertEquals("Assert 1: After removing non-null element size is incorrect", 0, hashMap.size());
385
386        hashMap.put(null, null);
387        assertEquals("Assert 2: adding literal null failed", 1, hashMap.size());
388        hashMap.remove(null);
389        assertEquals("Assert 3: After removing null element size is incorrect", 0, hashMap.size());
390    }
391
392    /**
393     * java.util.IdentityHashMap#size()
394     */
395    public void test_size() {
396        // Test for method int java.util.IdentityHashMap.size()
397        assertEquals("Returned incorrect size, ", (objArray.length + 2), hm
398                .size());
399    }
400
401    /**
402     * java.util.IdentityHashMap#equals(java.lang.Object)
403     */
404    public void test_equalsLjava_lang_Object() {
405        IdentityHashMap mapOne = new IdentityHashMap();
406        IdentityHashMap mapTwo = new IdentityHashMap();
407        IdentityHashMap mapThree = new IdentityHashMap();
408        IdentityHashMap mapFour = new IdentityHashMap();
409
410        String one = "one";
411        String alsoOne = new String(one); // use the new operator to ensure a
412        // new reference is constructed
413        String two = "two";
414        String alsoTwo = new String(two); // use the new operator to ensure a
415        // new reference is constructed
416
417        mapOne.put(one, two);
418        mapFour.put(one, two);
419
420        // these two are not equal to the above two
421        mapTwo.put(alsoOne, two);
422        mapThree.put(one, alsoTwo);
423
424        assertEquals("failure of equality of IdentityHashMaps", mapOne, mapFour);
425        assertTrue("failure of non-equality of IdentityHashMaps one and two",
426                !mapOne.equals(mapTwo));
427        assertTrue("failure of non-equality of IdentityHashMaps one and three",
428                !mapOne.equals(mapThree));
429        assertTrue("failure of non-equality of IdentityHashMaps two and three",
430                !mapTwo.equals(mapThree));
431
432        HashMap hashMapTwo = new HashMap();
433        HashMap hashMapThree = new HashMap();
434        hashMapTwo.put(alsoOne, two);
435        hashMapThree.put(one, alsoTwo);
436
437        assertTrue(
438                "failure of non-equality of IdentityHashMaps one and Hashmap two",
439                !mapOne.equals(hashMapTwo));
440        assertTrue(
441                "failure of non-equality of IdentityHashMaps one and Hashmap three",
442                !mapOne.equals(hashMapThree));
443    }
444
445    /**
446     * java.util.IdentityHashMap#Serialization()
447     */
448    public void test_Serialization() throws Exception {
449        IdentityHashMap<String, String> map = new IdentityHashMap<String, String>();
450        map.put(ID, "world");
451        // BEGIN Android-added
452        // Regression test for null key in serialized IdentityHashMap (1178549)
453        // Together with this change the IdentityHashMap.golden.ser resource
454        // was replaced by a version that contains a map with a null key.
455        map.put(null, "null");
456        // END Android-added
457        SerializationTest.verifySelf(map, comparator);
458        SerializationTest.verifyGolden(this, map, comparator);
459    }
460
461    /**
462     * Sets up the fixture, for example, open a network connection. This method
463     * is called before a test is executed.
464     */
465    protected void setUp() {
466        objArray = new Object[hmSize];
467        objArray2 = new Object[hmSize];
468        for (int i = 0; i < objArray.length; i++) {
469            objArray[i] = new Integer(i);
470            // Android-changed: the containsKey test requires unique strings.
471            objArray2[i] = new String(objArray[i].toString());
472        }
473
474        hm = new IdentityHashMap();
475        for (int i = 0; i < objArray.length; i++)
476            hm.put(objArray2[i], objArray[i]);
477        hm.put("test", null);
478        hm.put(null, "test");
479    }
480
481    /**
482     * Tears down the fixture, for example, close a network connection. This
483     * method is called after a test is executed.
484     */
485    protected void tearDown() {
486        objArray = null;
487        objArray2 = null;
488        hm = null;
489    }
490
491    private static final SerializationTest.SerializableAssert comparator = new
492                             SerializationTest.SerializableAssert() {
493
494        public void assertDeserialized(Serializable initial, Serializable deserialized) {
495            IdentityHashMap<String, String> initialMap = (IdentityHashMap<String, String>) initial;
496            IdentityHashMap<String, String> deseriaMap = (IdentityHashMap<String, String>) deserialized;
497            assertEquals("should be equal", initialMap.size(), deseriaMap.size());
498        }
499
500    };
501
502    /**
503     * java.util.IdentityHashMap#containsKey(java.lang.Object)
504     * java.util.IdentityHashMap#containsValue(java.lang.Object)
505     * java.util.IdentityHashMap#put(java.lang.Object, java.lang.Object)
506     * java.util.IdentityHashMap#get(java.lang.Object)
507     */
508    public void test_null_Keys_and_Values() {
509        // tests with null keys and values
510        IdentityHashMap map = new IdentityHashMap();
511        Object result;
512
513        // null key and null value
514        result = map.put(null, null);
515        assertTrue("testA can not find null key", map.containsKey(null));
516        assertTrue("testA can not find null value", map.containsValue(null));
517        assertNull("testA can not get null value for null key",
518                map.get(null));
519        assertNull("testA put returned wrong value", result);
520
521        // null value
522        String value = "a value";
523        result = map.put(null, value);
524        assertTrue("testB can not find null key", map.containsKey(null));
525        assertTrue("testB can not find a value with null key", map
526                .containsValue(value));
527        assertTrue("testB can not get value for null key",
528                map.get(null) == value);
529        assertNull("testB put returned wrong value", result);
530
531        // a null key
532        String key = "a key";
533        result = map.put(key, null);
534        assertTrue("testC can not find a key with null value", map
535                .containsKey(key));
536        assertTrue("testC can not find null value", map.containsValue(null));
537        assertNull("testC can not get null value for key", map.get(key));
538        assertNull("testC put returned wrong value", result);
539
540        // another null key
541        String anothervalue = "another value";
542        result = map.put(null, anothervalue);
543        assertTrue("testD can not find null key", map.containsKey(null));
544        assertTrue("testD can not find a value with null key", map
545                .containsValue(anothervalue));
546        assertTrue("testD can not get value for null key",
547                map.get(null) == anothervalue);
548        assertTrue("testD put returned wrong value", result == value);
549
550        // remove a null key
551        result = map.remove(null);
552        assertTrue("testE remove returned wrong value", result == anothervalue);
553        assertTrue("testE should not find null key", !map.containsKey(null));
554        assertTrue("testE should not find a value with null key", !map
555                .containsValue(anothervalue));
556        assertNull("testE should not get value for null key",
557                map.get(null));
558    }
559
560    /**
561     * java.util.IdentityHashMap#remove(java.lang.Object)
562     * java.util.IdentityHashMap#keySet()
563     */
564    public void test_remove() {
565        IdentityHashMap map = new IdentityHashMap();
566        map.put(null, null);
567        map.put("key1", "value1");
568        map.put("key2", "value2");
569        map.remove("key1");
570
571        assertTrue("Did not remove key1", !map.containsKey("key1"));
572        assertTrue("Did not remove the value for key1", !map
573                .containsValue("value1"));
574
575        assertTrue("Modified key2", map.get("key2") != null
576                && map.get("key2") == "value2");
577        assertNull("Modified null entry", map.get(null));
578    }
579
580    /**
581     * java.util.IdentityHashMap#entrySet()
582     * java.util.IdentityHashMap#keySet()
583     * java.util.IdentityHashMap#values()
584     */
585    public void test_sets() {
586        // tests with null keys and values
587        IdentityHashMap map = new IdentityHashMap();
588
589        // null key and null value
590        map.put("key", "value");
591        map.put(null, null);
592        map.put("a key", null);
593        map.put("another key", null);
594
595        Set keyset = map.keySet();
596        Collection valueset = map.values();
597        Set entries = map.entrySet();
598        Iterator it = entries.iterator();
599        while (it.hasNext()) {
600            Map.Entry entry = (Map.Entry) it.next();
601            assertTrue("EntrySetIterator can not find entry ", entries
602                    .contains(entry));
603
604            assertTrue("entry key not found in map", map.containsKey(entry
605                    .getKey()));
606            assertTrue("entry value not found in map", map.containsValue(entry
607                    .getValue()));
608
609            assertTrue("entry key not found in the keyset", keyset
610                    .contains(entry.getKey()));
611            assertTrue("entry value not found in the valueset", valueset
612                    .contains(entry.getValue()));
613        }
614    }
615
616    /**
617     * java.util.IdentityHashMap#entrySet()
618     * java.util.IdentityHashMap#remove(java.lang.Object)
619     */
620    public void test_entrySet_removeAll() {
621        IdentityHashMap map = new IdentityHashMap();
622        for (int i = 0; i < 1000; i++) {
623            map.put(new Integer(i), new Integer(i));
624        }
625        Set set = map.entrySet();
626
627        set.removeAll(set);
628        assertEquals("did not remove all elements in the map", 0, map.size());
629        assertTrue("did not remove all elements in the entryset", set.isEmpty());
630
631        Iterator it = set.iterator();
632        assertTrue("entrySet iterator still has elements", !it.hasNext());
633    }
634
635    /**
636     * java.util.IdentityHashMap#keySet()
637     * java.util.IdentityHashMap#clear()
638     */
639    public void test_keySet_clear() {
640        IdentityHashMap map = new IdentityHashMap();
641        for (int i = 0; i < 1000; i++) {
642            map.put(new Integer(i), new Integer(i));
643        }
644        Set set = map.keySet();
645        set.clear();
646
647        assertEquals("did not remove all elements in the map", 0, map.size());
648        assertTrue("did not remove all elements in the keyset", set.isEmpty());
649
650        Iterator it = set.iterator();
651        assertTrue("keySet iterator still has elements", !it.hasNext());
652    }
653
654    /**
655     * java.util.IdentityHashMap#values()
656     */
657    public void test_values() {
658
659        IdentityHashMap map = new IdentityHashMap();
660        for (int i = 0; i < 10; i++) {
661            map.put(new Integer(i), new Integer(i));
662        }
663
664        Integer key = new Integer(20);
665        Integer value = new Integer(40);
666        map.put(key, value);
667
668        Collection vals = map.values();
669        boolean result = vals.remove(key);
670        assertTrue("removed entries incorrectly", map.size() == 11 && !result);
671        assertTrue("removed key incorrectly", map.containsKey(key));
672        assertTrue("removed value incorrectly", map.containsValue(value));
673
674        result = vals.remove(value);
675        assertTrue("Did not remove entry as expected", map.size() == 10
676                && result);
677        assertTrue("Did not remove key as expected", !map.containsKey(key));
678        assertTrue("Did not remove value as expected", !map
679                .containsValue(value));
680
681        // put an equivalent key to a value
682        key = new Integer(1);
683        value = new Integer(100);
684        map.put(key, value);
685
686        result = vals.remove(key);
687        assertTrue("TestB. removed entries incorrectly", map.size() == 11
688                && !result);
689        assertTrue("TestB. removed key incorrectly", map.containsKey(key));
690        assertTrue("TestB. removed value incorrectly", map.containsValue(value));
691
692        result = vals.remove(value);
693        assertTrue("TestB. Did not remove entry as expected", map.size() == 10
694                && result);
695        assertTrue("TestB. Did not remove key as expected", !map
696                .containsKey(key));
697        assertTrue("TestB. Did not remove value as expected", !map
698                .containsValue(value));
699
700        vals.clear();
701        assertEquals("Did not remove all entries as expected", 0, map.size());
702    }
703
704    /**
705     * java.util.IdentityHashMap#keySet()
706     * java.util.IdentityHashMap#remove(java.lang.Object)
707     */
708    public void test_keySet_removeAll() {
709        IdentityHashMap map = new IdentityHashMap();
710        for (int i = 0; i < 1000; i++) {
711            map.put(new Integer(i), new Integer(i));
712        }
713        Set set = map.keySet();
714        set.removeAll(set);
715
716        assertEquals("did not remove all elements in the map", 0, map.size());
717        assertTrue("did not remove all elements in the keyset", set.isEmpty());
718
719        Iterator it = set.iterator();
720        assertTrue("keySet iterator still has elements", !it.hasNext());
721    }
722
723    /**
724     * java.util.IdentityHashMap#keySet()
725     */
726    public void test_keySet_retainAll() {
727        IdentityHashMap map = new IdentityHashMap();
728        for (int i = 0; i < 1000; i++) {
729            map.put(new Integer(i), new Integer(i));
730        }
731        Set set = map.keySet();
732
733        // retain all the elements
734        boolean result = set.retainAll(set);
735        assertTrue("retain all should return false", !result);
736        assertEquals("did not retain all", 1000, set.size());
737
738        // send empty set to retainAll
739        result = set.retainAll(new TreeSet());
740        assertTrue("retain all should return true", result);
741        assertEquals("did not remove all elements in the map", 0, map.size());
742        assertTrue("did not remove all elements in the keyset", set.isEmpty());
743
744        Iterator it = set.iterator();
745        assertTrue("keySet iterator still has elements", !it.hasNext());
746    }
747
748    /**
749     * java.util.IdentityHashMap#keySet()
750     * java.util.IdentityHashMap#remove(java.lang.Object)
751     */
752    public void test_keyset_remove() {
753        IdentityHashMap map = new IdentityHashMap();
754
755        Integer key = new Integer(21);
756
757        map.put(new Integer(1), null);
758        map.put(new Integer(11), null);
759        map.put(key, null);
760        map.put(new Integer(31), null);
761        map.put(new Integer(41), null);
762        map.put(new Integer(51), null);
763        map.put(new Integer(61), null);
764        map.put(new Integer(71), null);
765        map.put(new Integer(81), null);
766        map.put(new Integer(91), null);
767
768        Set set = map.keySet();
769
770        Set newset = new HashSet();
771        Iterator it = set.iterator();
772        while (it.hasNext()) {
773            Object element = it.next();
774            if (element == key) {
775                it.remove();
776            } else
777                newset.add(element);
778        }
779        int size = newset.size();
780        assertTrue("keyset and newset don't have same size",
781                newset.size() == size);
782        assertTrue("element is in newset ", !newset.contains(key));
783        assertTrue("element not removed from keyset", !set.contains(key));
784        assertTrue("element not removed from map", !map.containsKey(key));
785
786        assertTrue("newset and keyset do not have same elements 1", newset
787                .equals(set));
788        assertTrue("newset and keyset do not have same elements 2", set
789                .equals(newset));
790    }
791
792    public void test_clone_scenario1() {
793        IdentityHashMap hashMap = new IdentityHashMap();
794        assertEquals(0, hashMap.hashCode());
795        Object cloneHashMap = hashMap.clone();
796        ((IdentityHashMap) cloneHashMap).put("key", "value");
797        assertEquals(0, hashMap.hashCode());
798        assertTrue(0 != cloneHashMap.hashCode());
799    }
800
801    public void test_clone_scenario2() {
802        IdentityHashMap hashMap = new IdentityHashMap();
803        assertEquals(0, hashMap.hashCode());
804        Object cloneHashMap = hashMap.clone();
805        hashMap.put("key", "value");
806        assertEquals(1, hashMap.size());
807        assertEquals(0, ((IdentityHashMap) cloneHashMap).size());
808        assertEquals("value", hashMap.get("key"));
809        assertNull(((IdentityHashMap) cloneHashMap).get("key"));
810        assertTrue(0 != hashMap.hashCode());
811        assertEquals(0, cloneHashMap.hashCode());
812    }
813
814    public void test_clone_scenario3() {
815        IdentityHashMap hashMap = new IdentityHashMap();
816        assertEquals(0, hashMap.hashCode());
817        hashMap.put("key", "value");
818        Object cloneHashMap = hashMap.clone();
819        assertEquals(1, hashMap.size());
820        assertEquals(1, ((IdentityHashMap) cloneHashMap).size());
821        assertEquals("value", hashMap.get("key"));
822        assertEquals("value", ((IdentityHashMap) cloneHashMap).get("key"));
823        assertEquals(hashMap.hashCode(), cloneHashMap.hashCode());
824    }
825
826    public void test_clone_scenario4() {
827        IdentityHashMap hashMap = new IdentityHashMap();
828        Object cloneHashMap = hashMap.clone();
829        assertNull(((IdentityHashMap) cloneHashMap).get((Object) null));
830        hashMap.put((Object) null, cloneHashMap);
831        assertNull(((IdentityHashMap) cloneHashMap).get((Object) null));
832        assertEquals(cloneHashMap, hashMap.get((Object) null));
833    }
834
835    public void test_clone_scenario5() throws Exception {
836        IdentityHashMap hashMap = new IdentityHashMap();
837        Object cloneHashMap = hashMap.clone();
838        assertNull(hashMap.remove((Object) null));
839        ((IdentityHashMap) cloneHashMap).put((Object) null, cloneHashMap);
840        assertNull(hashMap.remove((Object) null));
841        assertEquals(cloneHashMap, ((IdentityHashMap) cloneHashMap)
842                .get((Object) null));
843    }
844
845    /*
846    * Regression test for HARMONY-6419
847    */
848    public void test_underlyingMap() {
849        IdentityHashMap<String, String> ihm = new IdentityHashMap<String, String>();
850        String key = "key";
851        String value = "value";
852        ihm.put(key, value);
853
854        Set<Map.Entry<String, String>> set = ihm.entrySet();
855        assertEquals(1, set.size());
856
857        Map.Entry<String, String> entry = set.iterator().next();
858
859        String newValue = "newvalue";
860        entry.setValue(newValue);
861        assertSame(newValue, ihm.get(key));
862    }
863
864    public void test_forEach() throws Exception {
865        IdentityHashMap<String, String> map = new IdentityHashMap<>();
866        map.put("one", "1");
867        map.put("two", "2");
868        map.put("three", "3");
869
870        IdentityHashMap<String, String> output = new IdentityHashMap<>();
871        map.forEach((k, v) -> output.put(k,v));
872        assertEquals(map, output);
873
874        HashSet<String> setOutput = new HashSet<>();
875        map.keySet().forEach((k) -> setOutput.add(k));
876        assertEquals(map.keySet(), setOutput);
877
878        setOutput.clear();
879        map.values().forEach((v) -> setOutput.add(v));
880        assertEquals(new HashSet<>(map.values()), setOutput);
881
882        HashSet<Map.Entry<String,String>> entrySetOutput = new HashSet<>();
883        map.entrySet().forEach((v) -> entrySetOutput.add(v));
884        assertEquals(map.entrySet(), entrySetOutput);
885    }
886
887
888    public void test_forEach_NPE() throws Exception {
889        IdentityHashMap<String, String> map = new IdentityHashMap<>();
890        try {
891            map.forEach(null);
892            fail();
893        } catch(NullPointerException expected) {}
894
895        try {
896            map.keySet().forEach(null);
897            fail();
898        } catch(NullPointerException expected) {}
899
900        try {
901            map.values().forEach(null);
902            fail();
903        } catch(NullPointerException expected) {}
904
905        try {
906            map.entrySet().forEach(null);
907            fail();
908        } catch(NullPointerException expected) {}
909    }
910
911    public void test_forEach_CME() throws Exception {
912        IdentityHashMap<String, String> map = new IdentityHashMap<>();
913        map.put("one", "1");
914        map.put("two", "2");
915        map.put("three", "3");
916
917        IdentityHashMap<String, String> outputMap = new IdentityHashMap<>();
918        try {
919            map.forEach(new java.util.function.BiConsumer<String, String>() {
920                    @Override
921                    public void accept(String k, String v) {
922                        outputMap.put(k, v);
923                        map.put("foo1", v);
924                    }
925                });
926            fail();
927        } catch(ConcurrentModificationException expected) {}
928        // We should get a CME and DO NOT continue forEach evaluation
929        assertEquals(1, outputMap.size());
930
931        outputMap.clear();
932        try {
933            map.keySet().forEach(new java.util.function.Consumer<String>() {
934                    @Override
935                    public void accept(String k) {
936                        outputMap.put(k, "foo");
937                        map.put("foo2", "boo");
938                    }
939                });
940            fail();
941        } catch(ConcurrentModificationException expected) {}
942        // We should get a CME and DO NOT continue forEach evaluation
943        assertEquals(1, outputMap.size());
944
945        outputMap.clear();
946        try {
947            map.values().forEach(new java.util.function.Consumer<String>() {
948                    @Override
949                    public void accept(String k)  {
950                        outputMap.put(k, "foo");
951                        map.put("foo3", "boo");
952                    }
953                });
954            fail();
955        } catch(ConcurrentModificationException expected) {}
956        // We should get a CME and DO NOT continue forEach evaluation
957        assertEquals(1, outputMap.size());
958
959        outputMap.clear();
960        try {
961            map.entrySet().forEach(new java.util.function.Consumer<Map.Entry<String,String>>() {
962                    @Override
963                    public void accept(Map.Entry<String,String> k)  {
964                        outputMap.put(k.getKey(), "foo");
965                        map.put("foo4", "boo");
966                    }
967                });
968            fail();
969        } catch(ConcurrentModificationException expected) {}
970        // We should get a CME and DO NOT continue forEach evaluation
971        assertEquals(1, outputMap.size());
972    }
973
974    public void test_spliterator_keySet() {
975        IdentityHashMap<String, String> hashMap = new IdentityHashMap<>();
976        hashMap.put("a", "1");
977        hashMap.put("b", "2");
978        hashMap.put("c", "3");
979        hashMap.put("d", "4");
980        hashMap.put("e", "5");
981        hashMap.put("f", "6");
982        hashMap.put("g", "7");
983        hashMap.put("h", "8");
984        hashMap.put("i", "9");
985        hashMap.put("j", "10");
986        hashMap.put("k", "11");
987        hashMap.put("l", "12");
988        hashMap.put("m", "13");
989        hashMap.put("n", "14");
990        hashMap.put("o", "15");
991        hashMap.put("p", "16");
992
993        Set<String> keys = hashMap.keySet();
994        ArrayList<String> expectedKeys = new ArrayList<>(keys);
995
996        SpliteratorTester.runBasicIterationTests(keys.spliterator(), expectedKeys);
997        SpliteratorTester.runBasicSplitTests(keys, expectedKeys);
998        SpliteratorTester.testSpliteratorNPE(keys.spliterator());
999        SpliteratorTester.assertSupportsTrySplit(keys);
1000    }
1001
1002    public void test_spliterator_valueSet() {
1003        IdentityHashMap<String, String> hashMap = new IdentityHashMap<>();
1004        hashMap.put("a", "1");
1005        hashMap.put("b", "2");
1006        hashMap.put("c", "3");
1007        hashMap.put("d", "4");
1008        hashMap.put("e", "5");
1009        hashMap.put("f", "6");
1010        hashMap.put("g", "7");
1011        hashMap.put("h", "8");
1012        hashMap.put("i", "9");
1013        hashMap.put("j", "10");
1014        hashMap.put("k", "11");
1015        hashMap.put("l", "12");
1016        hashMap.put("m", "13");
1017        hashMap.put("n", "14");
1018        hashMap.put("o", "15");
1019        hashMap.put("p", "16");
1020
1021        Collection<String> values = hashMap.values();
1022        ArrayList<String> expectedValues = new ArrayList<>(values);
1023
1024        SpliteratorTester.runBasicIterationTests(values.spliterator(), expectedValues);
1025        SpliteratorTester.runBasicSplitTests(values, expectedValues);
1026        SpliteratorTester.testSpliteratorNPE(values.spliterator());
1027        SpliteratorTester.assertSupportsTrySplit(values);
1028    }
1029
1030    public void test_spliterator_entrySet() {
1031        IdentityHashMap<String, String> hashMap = new IdentityHashMap<>();
1032        hashMap.put("a", "1");
1033        hashMap.put("b", "2");
1034        hashMap.put("c", "3");
1035        hashMap.put("d", "4");
1036        hashMap.put("e", "5");
1037        hashMap.put("f", "6");
1038        hashMap.put("g", "7");
1039        hashMap.put("h", "8");
1040        hashMap.put("i", "9");
1041        hashMap.put("j", "10");
1042        hashMap.put("k", "11");
1043        hashMap.put("l", "12");
1044        hashMap.put("m", "13");
1045        hashMap.put("n", "14");
1046        hashMap.put("o", "15");
1047        hashMap.put("p", "16");
1048
1049        Set<Map.Entry<String, String>> values = hashMap.entrySet();
1050        ArrayList<Map.Entry<String, String>> expectedValues = new ArrayList<>(values);
1051
1052        Comparator<Map.Entry<String, String>> comparator =
1053                (a, b) -> (a.getKey().compareTo(b.getKey()));
1054
1055        SpliteratorTester.runBasicIterationTests(values.spliterator(), expectedValues);
1056        SpliteratorTester.runBasicSplitTests(values, expectedValues, comparator);
1057        SpliteratorTester.testSpliteratorNPE(values.spliterator());
1058        SpliteratorTester.assertSupportsTrySplit(values);
1059    }
1060
1061    public void test_replaceAll() {
1062        IdentityHashMap<String, String> map = new IdentityHashMap<>();
1063        String key1 = "key1";
1064        String key2 = "key2";
1065        String key3 = "key3";
1066
1067        map.put(key1, "1");
1068        map.put(key2, "2");
1069        map.put(key3, "3");
1070
1071        map.replaceAll((k, v) -> k + v);
1072
1073        assertEquals("key11", map.get(key1));
1074        assertEquals("key22", map.get(key2));
1075        assertEquals("key33", map.get(key3));
1076        assertEquals(3, map.size());
1077
1078        try {
1079            map.replaceAll(new BiFunction<String, String, String>() {
1080                @Override
1081                public String apply(String s, String s2) {
1082                    map.put("key4", "4");
1083                    return "";
1084                }
1085            });
1086            fail();
1087        } catch (ConcurrentModificationException expected) {}
1088    }
1089
1090
1091    // comparator for IdentityHashMap objects
1092    private static final SerializableAssert COMPARATOR = new SerializableAssert() {
1093        public void assertDeserialized(Serializable initial,
1094                Serializable deserialized) {
1095
1096            IdentityHashMap init = (IdentityHashMap) initial;
1097            IdentityHashMap desr = (IdentityHashMap) deserialized;
1098
1099            assertEquals("Size", init.size(), desr.size());
1100        }
1101    };
1102}
1103