1 import org.testng.annotations.Test;
   2 
   3 import java.lang.invoke.MethodHandle;
   4 import java.lang.invoke.MethodHandles;
   5 import java.lang.invoke.MethodType;
   6 import java.lang.invoke.VarHandle;
   7 import java.util.HashMap;
   8 import java.util.stream.IntStream;
   9 
  10 import static java.util.stream.Collectors.toMap;
  11 import static org.testng.Assert.assertEquals;
  12 
  13 /**
  14  * @test
  15  * @bug 8210280
  16  * @run testng ResizeTest
  17  */
  18 
  19 public class ResizeTest {
  20     final MethodHandle TABLE_SIZE_FOR;
  21     final MethodHandle RESIZE;
  22     final VarHandle THRESHOLD;
  23     final VarHandle TABLE;
  24 
  25     public ResizeTest() throws IllegalAccessException, NoSuchMethodException, NoSuchFieldException,
  26                                        ClassNotFoundException {
  27         Class<?> mClass = HashMap.class;
  28         String nodeClassName = mClass.getName() + "$Node";
  29         Class<?> nodeArrayClass = Class.forName("[L" + nodeClassName + ";");
  30         MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(mClass, MethodHandles.lookup());
  31         TABLE = lookup.findVarHandle(mClass, "table", nodeArrayClass);
  32         this.TABLE_SIZE_FOR = lookup.findStatic(
  33                 mClass, "tableSizeFor",
  34                 MethodType.methodType(int.class, int.class));
  35         this.RESIZE = lookup.findVirtual(mClass, "resize", MethodType.methodType(nodeArrayClass, int.class));
  36         this.THRESHOLD = lookup.findVarHandle(mClass, "threshold", int.class);
  37     }
  38 
  39     int tableSizeFor(int n) {
  40         try {
  41             return (int) TABLE_SIZE_FOR.invoke(n);
  42         } catch (Throwable t) { throw new AssertionError(t); }
  43     }
  44 
  45     @Test
  46     public void testTableSizeFor() {
  47         assertEquals(tableSizeFor(0), 1);
  48         assertEquals(tableSizeFor(1), 1);
  49         assertEquals(tableSizeFor(2), 2);
  50         assertEquals(tableSizeFor(3), 4);
  51         assertEquals(tableSizeFor(15), 16);
  52         assertEquals(tableSizeFor(16), 16);
  53         assertEquals(tableSizeFor(17), 32);
  54         int maxSize = 1 << 30;
  55         assertEquals(tableSizeFor(maxSize - 1), maxSize);
  56         assertEquals(tableSizeFor(maxSize), maxSize);
  57         assertEquals(tableSizeFor(maxSize + 1), maxSize);
  58         assertEquals(tableSizeFor(Integer.MAX_VALUE), maxSize);
  59     }
  60 
  61     @Test
  62     public void putAllCapacityTest() {
  63         var map = new HashMap<Integer, Integer>();
  64         map.putAll(IntStream.range(0, 10).boxed().collect(toMap(i -> i, i -> i)));
  65 
  66         int capacity = ((Object[]) TABLE.get(map)).length;
  67         assertEquals(capacity, 16);
  68     }
  69 
  70     @Test
  71     public void callResizeWithSizeTest() throws Throwable {
  72         var map = new HashMap<Integer, Integer>();
  73 
  74         RESIZE.invoke(map, 0);
  75         int capacity = ((Object[]) TABLE.get(map)).length;
  76         assertEquals(capacity, 1);
  77 
  78         RESIZE.invoke(map, 15);
  79         capacity = ((Object[]) TABLE.get(map)).length;
  80         assertEquals(capacity, 16);
  81 
  82         RESIZE.invoke(map, 256);
  83         capacity = ((Object[]) TABLE.get(map)).length;
  84         assertEquals(capacity, 256);
  85 
  86         RESIZE.invoke(map, 257);
  87         capacity = ((Object[]) TABLE.get(map)).length;
  88         assertEquals(capacity, 512);
  89     }
  90 }