Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/test/java/util/IdentityHashMap/Capacity.java
38821 views
/*1* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.lang.reflect.Field;24import java.util.ArrayList;25import java.util.Collections;26import java.util.IdentityHashMap;27import java.util.List;28import java.util.Random;2930import org.testng.annotations.DataProvider;31import org.testng.annotations.Test;3233import static org.testng.Assert.*;3435/*36* @test37* @bug 690436738* @summary IdentityHashMap reallocates storage when inserting expected39* number of elements40* @run testng Capacity41* @key randomness42*/4344@Test45public class Capacity {46static final Field tableField;47static final Random random = new Random();48static final Object[][] sizesData;4950@DataProvider(name="sizes", parallel = true)51public Object[][] sizesToTest() { return sizesData; }5253static {54try {55tableField = IdentityHashMap.class.getDeclaredField("table");56tableField.setAccessible(true);57} catch (NoSuchFieldException e) {58throw new LinkageError("table", e);59}6061ArrayList<Object[]> sizes = new ArrayList<>();62for (int size = 0; size < 200; size++)63sizes.add(new Object[] { size });6465// some numbers known to demonstrate bug 690436766for (int size : new int[] {682, 683, 1365, 2730, 2731, 5461})67sizes.add(new Object[] { size });6869// a few more random sizes to try70for (int i = 0; i != 128; i++)71sizes.add(new Object[] { random.nextInt(5000) });7273sizesData = sizes.toArray(new Object[0][]);74}7576static int capacity(IdentityHashMap<?,?> map) {77try {78return ((Object[]) tableField.get(map)).length / 2;79} catch (Throwable t) {80throw new LinkageError("table", t);81}82}8384static void assertCapacity(IdentityHashMap<?,?> map,85int expectedCapacity) {86assertEquals(capacity(map), expectedCapacity);87}8889static void growUsingPut(IdentityHashMap<Object,Object> map,90int elementsToAdd) {91for (int i = 0; i < elementsToAdd; i++)92map.put(new Object(), new Object());93}9495static void growUsingPutAll(IdentityHashMap<Object,Object> map,96int elementsToAdd) {97IdentityHashMap<Object,Object> other = new IdentityHashMap<>();98growUsingPut(other, elementsToAdd);99map.putAll(other);100}101102static void growUsingRepeatedPutAll(IdentityHashMap<Object,Object> map,103int elementsToAdd) {104for (int i = 0; i < elementsToAdd; i++)105map.putAll(Collections.singletonMap(new Object(),106new Object()));107}108109/**110* Checks that expected number of items can be inserted into111* the map without resizing of the internal storage112*/113@Test(dataProvider = "sizes")114public void canInsertExpectedItemsWithoutResizing(int size)115throws Throwable {116// First try growing using put()117IdentityHashMap<Object,Object> m = new IdentityHashMap<>(size);118int initialCapacity = capacity(m);119growUsingPut(m, size);120assertCapacity(m, initialCapacity);121122// Doubling from the expected size will cause exactly one123// resize, except near minimum capacity.124if (size > 1) {125growUsingPut(m, size);126assertCapacity(m, 2 * initialCapacity);127}128129// Try again, growing with putAll()130m = new IdentityHashMap<>(size);131initialCapacity = capacity(m);132growUsingPutAll(m, size);133assertCapacity(m, initialCapacity);134135// Doubling from the expected size will cause exactly one136// resize, except near minimum capacity.137if (size > 1) {138growUsingPutAll(m, size);139assertCapacity(m, 2 * initialCapacity);140}141}142143/**144* Given the expected size, computes such a number N of items that145* inserting (N+1) items will trigger resizing of the internal storage146*/147static int threshold(int size) throws Throwable {148IdentityHashMap<Object,Object> m = new IdentityHashMap<>(size);149int initialCapacity = capacity(m);150while (capacity(m) == initialCapacity)151growUsingPut(m, 1);152return m.size() - 1;153}154155/**156* Checks that inserting (threshold+1) item causes resizing157* of the internal storage158*/159@Test(dataProvider = "sizes")160public void passingThresholdCausesResize(int size) throws Throwable {161final int threshold = threshold(size);162IdentityHashMap<Object,Object> m = new IdentityHashMap<>(threshold);163int initialCapacity = capacity(m);164165growUsingPut(m, threshold);166assertCapacity(m, initialCapacity);167168growUsingPut(m, 1);169assertCapacity(m, 2 * initialCapacity);170}171172/**173* Checks that 4 methods of requiring capacity lead to the same174* internal capacity, unless sized below default capacity.175*/176@Test(dataProvider = "sizes")177public void differentGrowthPatternsResultInSameCapacity(int size)178throws Throwable {179if (size < 21) // 21 is default maxExpectedSize180return;181182IdentityHashMap<Object,Object> m;183m = new IdentityHashMap<Object,Object>(size);184int capacity1 = capacity(m);185186m = new IdentityHashMap<>();187growUsingPut(m, size);188int capacity2 = capacity(m);189190m = new IdentityHashMap<>();191growUsingPutAll(m, size);192int capacity3 = capacity(m);193194m = new IdentityHashMap<>();195growUsingRepeatedPutAll(m, size);196int capacity4 = capacity(m);197198if (capacity1 != capacity2 ||199capacity2 != capacity3 ||200capacity3 != capacity4)201throw new AssertionError("Capacities not equal: "202+ capacity1 + " "203+ capacity2 + " "204+ capacity3 + " "205+ capacity4);206}207208public void defaultExpectedMaxSizeIs21() {209assertCapacity(new IdentityHashMap<Long,Long>(), 32);210assertCapacity(new IdentityHashMap<Long,Long>(21), 32);211}212213public void minimumCapacityIs4() {214assertCapacity(new IdentityHashMap<Long,Long>(0), 4);215assertCapacity(new IdentityHashMap<Long,Long>(1), 4);216assertCapacity(new IdentityHashMap<Long,Long>(2), 4);217assertCapacity(new IdentityHashMap<Long,Long>(3), 8);218}219220@Test(enabled = false)221/** needs too much memory to run normally */222public void maximumCapacityIs2ToThe29() {223assertCapacity(new IdentityHashMap<Long,Long>(Integer.MAX_VALUE),2241 << 29);225}226}227228229