Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/util/HashMap/Bug8186171Test.java
38811 views
/*1* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.2*3* This code is free software; you can redistribute it and/or modify it4* under the terms of the GNU General Public License version 2 only, as5* published by the Free Software Foundation.6*7* This code is distributed in the hope that it will be useful, but WITHOUT8* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or9* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License10* version 2 for more details (a copy is included in the LICENSE file that11* accompanied this code).12*13* You should have received a copy of the GNU General Public License version14* 2 along with this work; if not, write to the Free Software Foundation,15* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.16*17* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA18* or visit www.oracle.com if you need additional information or have any19* questions.20*/21import java.util.List;22import java.util.Map;23import java.util.HashMap;24import java.util.Iterator;25import java.util.ArrayList;26import java.util.concurrent.ThreadLocalRandom;2728import org.testng.annotations.Test;29import static org.testng.Assert.assertEquals;30import static org.testng.Assert.assertFalse;31import static org.testng.Assert.assertTrue;3233/*34* @test35* @bug 818617136* @run testng Bug8186171Test37* @summary Verify the fix for scenario reported in JDK-818617138* @author [email protected]39*/40@Test41public class Bug8186171Test{4243/**44* Tests and extends the scenario reported in45* https://bugs.openjdk.java.net/browse/JDK-818617146* HashMap: Entry.setValue may not work after Iterator.remove() called for previous entries47* Runs 1000 times as it is based on randomization.48*/49@Test(invocationCount = 1000)50static void testBug8186171NonDeterministic()51{52final ThreadLocalRandom rnd = ThreadLocalRandom.current();5354final Object v1 = rnd.nextBoolean() ? null : 1;55final Object v2 = (rnd.nextBoolean() && v1 != null) ? null : 2;5657/** If true, always lands in first bucket in hash tables. */58final boolean poorHash = rnd.nextBoolean();5960class Key implements Comparable<Key> {61final int i;62Key(int i) { this.i = i; }63public int hashCode() { return poorHash ? 0 : super.hashCode(); }64public int compareTo(Key x) {65return Integer.compare(this.i, x.i);66}67}6869// HashMap and ConcurrentHashMap have:70// TREEIFY_THRESHOLD = 8; UNTREEIFY_THRESHOLD = 6;71final int size = rnd.nextInt(1, 25);7273List<Key> keys = new ArrayList<>();74for (int i = size; i-->0; ) keys.add(new Key(i));75Key keyToFrob = keys.get(rnd.nextInt(keys.size()));7677Map<Key, Object> m = new HashMap<Key, Object>();7879for (Key key : keys) m.put(key, v1);8081for (Iterator<Map.Entry<Key, Object>> it = m.entrySet().iterator();82it.hasNext(); ) {83Map.Entry<Key, Object> entry = it.next();84if (entry.getKey() == keyToFrob)85entry.setValue(v2); // does this have the expected effect?86else87it.remove();88}8990assertFalse(m.containsValue(v1));91assertTrue(m.containsValue(v2));92assertTrue(m.containsKey(keyToFrob));93assertEquals(1, m.size());94}959697/**98* Tests and extends the scenario reported in99* https://bugs.openjdk.java.net/browse/JDK-8186171100* HashMap: Entry.setValue may not work after Iterator.remove() called for previous entries101* Runs single time by reproducing exact scenario for issue mentioned in 8186171102*/103@Test()104static void testBug8186171Deterministic(){105class Key implements Comparable<Key>106{107final int i;108Key(int i) { this.i = i; }109110@Override111public int hashCode() { return 0; } //Returning same hashcode so that all keys landup to same bucket112113@Override114public int compareTo(Key x){115if(this.i == x.i){116return 0;117}118else {119return Integer.compare(this.i, x.i);120}121}122@Override123public String toString()124{125return "Key_" + i;126}127}128129// HashMap have TREEIFY_THRESHOLD = 8; UNTREEIFY_THRESHOLD = 6;130final int size = 11;131List<Key> keys = new ArrayList<>();132133for (int i = 0; i < size; i++){134keys.add(new Key(i));135}136137Key keyToFrob = keys.get(9);138Map<Key, Object> m = new HashMap<Key, Object>();139for (Key key : keys) m.put(key, null);140141for (Iterator<Map.Entry<Key, Object>> it = m.entrySet().iterator(); it.hasNext(); ){142Map.Entry<Key, Object> entry = it.next();143if (entry.getKey() == keyToFrob){144entry.setValue(2);145}146else{147it.remove();148}149}150151assertFalse(m.containsValue(null));152assertTrue(m.containsValue(2));153assertTrue(m.containsKey(keyToFrob));154assertEquals(1, m.size());155}156}157158159