jdk/test/sun/invoke/util/ValueConversionsTest.java
changeset 26466 3bbb6a284bd4
parent 23010 6dadb192ad81
child 26474 655d08549e43
equal deleted inserted replaced
26465:5ff735dd0d52 26466:3bbb6a284bd4
    23 
    23 
    24 package test.sun.invoke.util;
    24 package test.sun.invoke.util;
    25 
    25 
    26 import sun.invoke.util.ValueConversions;
    26 import sun.invoke.util.ValueConversions;
    27 import sun.invoke.util.Wrapper;
    27 import sun.invoke.util.Wrapper;
       
    28 
    28 import java.lang.invoke.MethodType;
    29 import java.lang.invoke.MethodType;
    29 import java.lang.invoke.MethodHandle;
    30 import java.lang.invoke.MethodHandle;
    30 import java.io.Serializable;
    31 import java.io.Serializable;
    31 import java.util.Arrays;
    32 import java.util.Arrays;
    32 import java.util.Collections;
       
    33 import org.junit.Test;
    33 import org.junit.Test;
    34 import static org.junit.Assert.*;
    34 import static org.junit.Assert.*;
    35 
    35 
    36 /* @test
    36 /* @test
    37  * @summary unit tests for value-type conversion utilities
    37  * @summary unit tests for value-type conversion utilities
    38  * @compile -XDignore.symbol.file ValueConversionsTest.java
    38  * @compile -XDignore.symbol.file ValueConversionsTest.java
    39  * @run junit/othervm test.sun.invoke.util.ValueConversionsTest
    39  * @run junit/othervm test.sun.invoke.util.ValueConversionsTest
    40  * @run junit/othervm
       
    41  *          -DValueConversionsTest.MAX_ARITY=255 -DValueConversionsTest.START_ARITY=250
       
    42  *              test.sun.invoke.util.ValueConversionsTest
       
    43  */
    40  */
    44 
       
    45 // This might take a while and burn lots of metadata:
       
    46 // @run junit/othervm -DValueConversionsTest.MAX_ARITY=255 -DValueConversionsTest.EXHAUSTIVE=true test.sun.invoke.util.ValueConversionsTest
       
    47 
    41 
    48 /**
    42 /**
    49  *
    43  *
    50  * @author jrose
    44  * @author jrose
    51  */
    45  */
    52 public class ValueConversionsTest {
    46 public class ValueConversionsTest {
    53     private static final Class<?> CLASS = ValueConversionsTest.class;
       
    54     private static final int MAX_ARITY = Integer.getInteger(CLASS.getSimpleName()+".MAX_ARITY", 40);
       
    55     private static final int START_ARITY = Integer.getInteger(CLASS.getSimpleName()+".START_ARITY", 0);
       
    56     private static final boolean EXHAUSTIVE = Boolean.getBoolean(CLASS.getSimpleName()+".EXHAUSTIVE");
       
    57 
       
    58     @Test
    47     @Test
    59     public void testUnbox() throws Throwable {
    48     public void testUnbox() throws Throwable {
    60         testUnbox(false);
    49         testUnbox(false);
    61     }
    50     }
    62 
    51 
    64     public void testUnboxCast() throws Throwable {
    53     public void testUnboxCast() throws Throwable {
    65         testUnbox(true);
    54         testUnbox(true);
    66     }
    55     }
    67 
    56 
    68     private void testUnbox(boolean doCast) throws Throwable {
    57     private void testUnbox(boolean doCast) throws Throwable {
    69         //System.out.println("unbox");
       
    70         for (Wrapper dst : Wrapper.values()) {
    58         for (Wrapper dst : Wrapper.values()) {
    71             //System.out.println(dst);
       
    72             for (Wrapper src : Wrapper.values()) {
    59             for (Wrapper src : Wrapper.values()) {
    73                 testUnbox(doCast, dst, src);
    60                 testUnbox(doCast, dst, src);
    74             }
    61             }
    75         }
    62         }
    76     }
    63     }
   121         }
   108         }
   122     }
   109     }
   123 
   110 
   124     @Test
   111     @Test
   125     public void testBox() throws Throwable {
   112     public void testBox() throws Throwable {
   126         //System.out.println("box");
       
   127         for (Wrapper w : Wrapper.values()) {
   113         for (Wrapper w : Wrapper.values()) {
   128             if (w == Wrapper.VOID)  continue;  // skip this; no unboxed form
   114             if (w == Wrapper.VOID)  continue;  // skip this; no unboxed form
   129             //System.out.println(w);
       
   130             for (int n = -5; n < 10; n++) {
   115             for (int n = -5; n < 10; n++) {
   131                 Object box = w.wrap(n);
   116                 Object box = w.wrap(n);
   132                 MethodHandle boxer = ValueConversions.box(w.primitiveType());
   117                 MethodHandle boxer = ValueConversions.box(w.primitiveType());
   133                 Object expResult = box;
   118                 Object expResult = box;
   134                 Object result = null;
   119                 Object result = null;
   149         }
   134         }
   150     }
   135     }
   151 
   136 
   152     @Test
   137     @Test
   153     public void testCast() throws Throwable {
   138     public void testCast() throws Throwable {
   154         //System.out.println("cast");
       
   155         Class<?>[] types = { Object.class, Serializable.class, String.class, Number.class, Integer.class };
   139         Class<?>[] types = { Object.class, Serializable.class, String.class, Number.class, Integer.class };
   156         Object[] objects = { new Object(), Boolean.FALSE,      "hello",      (Long)12L,    (Integer)6    };
   140         Object[] objects = { new Object(), Boolean.FALSE,      "hello",      (Long)12L,    (Integer)6    };
   157         for (Class<?> dst : types) {
   141         for (Class<?> dst : types) {
   158             MethodHandle caster = ValueConversions.cast(dst);
   142             MethodHandle caster = ValueConversions.cast(dst);
   159             assertEquals(caster.type(), ValueConversions.identity().type());
   143             assertEquals(caster.type(), ValueConversions.identity().type());
   160             for (Object obj : objects) {
   144             for (Object obj : objects) {
   161                 Class<?> src = obj.getClass();
   145                 Class<?> src = obj.getClass();
   162                 boolean canCast = dst.isAssignableFrom(src);
   146                 boolean canCast = dst.isAssignableFrom(src);
   163                 //System.out.println("obj="+obj+" <: dst="+dst+(canCast ? " (OK)" : " (will fail)"));
       
   164                 try {
   147                 try {
   165                     Object result = caster.invokeExact(obj);
   148                     Object result = caster.invokeExact(obj);
   166                     if (canCast)
   149                     if (canCast)
   167                         assertEquals(obj, result);
   150                         assertEquals(obj, result);
   168                     else
   151                     else
   175         }
   158         }
   176     }
   159     }
   177 
   160 
   178     @Test
   161     @Test
   179     public void testIdentity() throws Throwable {
   162     public void testIdentity() throws Throwable {
   180         //System.out.println("identity");
       
   181         MethodHandle id = ValueConversions.identity();
   163         MethodHandle id = ValueConversions.identity();
   182         Object expResult = "foo";
   164         Object expResult = "foo";
   183         Object result = id.invokeExact(expResult);
   165         Object result = id.invokeExact(expResult);
   184         // compiler bug:  ValueConversions.identity().invokeExact("bar");
       
   185         assertEquals(expResult, result);
   166         assertEquals(expResult, result);
   186     }
   167     }
   187 
   168 
   188     @Test
   169     @Test
   189     public void testConvert() throws Throwable {
   170     public void testConvert() throws Throwable {
   190         //System.out.println("convert");
       
   191         for (long tval = 0, ctr = 0;;) {
   171         for (long tval = 0, ctr = 0;;) {
   192             if (++ctr > 99999)  throw new AssertionError("too many test values");
   172             if (++ctr > 99999)  throw new AssertionError("too many test values");
   193             // next test value:
   173             // prints 3776 test patterns (3776 = 8*59*8)
   194             //System.out.println(Long.toHexString(tval)); // prints 3776 test patterns
       
   195             tval = nextTestValue(tval);
   174             tval = nextTestValue(tval);
   196             if (tval == 0) {
   175             if (tval == 0) {
   197                 //System.out.println("test value count = "+ctr);  // 3776 = 8*59*8
       
   198                 break;  // repeat
   176                 break;  // repeat
   199             }
   177             }
   200         }
   178         }
   201         for (Wrapper src : Wrapper.values()) {
   179         for (Wrapper src : Wrapper.values()) {
   202             for (Wrapper dst : Wrapper.values()) {
   180             for (Wrapper dst : Wrapper.values()) {
   203                 testConvert(src, dst, 0);
   181                 testConvert(src, dst, 0);
   204             }
   182             }
   205         }
   183         }
   206     }
   184     }
   207     static void testConvert(Wrapper src, Wrapper dst, long tval) throws Throwable {
   185     static void testConvert(Wrapper src, Wrapper dst, long tval) throws Throwable {
   208         //System.out.println(src+" => "+dst);
       
   209         boolean testSingleCase = (tval != 0);
   186         boolean testSingleCase = (tval != 0);
   210         final long tvalInit = tval;
   187         final long tvalInit = tval;
   211         MethodHandle conv = ValueConversions.convertPrimitive(src, dst);
   188         MethodHandle conv = ValueConversions.convertPrimitive(src, dst);
   212         MethodType convType;
   189         MethodType convType;
   213         if (src == Wrapper.VOID)
   190         if (src == Wrapper.VOID)
   267                 midBit = (1L<<LOW_BITS);  // introduce a low bit
   244                 midBit = (1L<<LOW_BITS);  // introduce a low bit
   268             ux += midBit;
   245             ux += midBit;
   269         }
   246         }
   270         return tweakSign(ux);
   247         return tweakSign(ux);
   271     }
   248     }
   272 
       
   273     @Test
       
   274     public void testVarargsArray() throws Throwable {
       
   275         //System.out.println("varargsArray");
       
   276         final int MIN = START_ARITY;
       
   277         final int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
       
   278         for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, 17, MAX)) {
       
   279             MethodHandle target = ValueConversions.varargsArray(nargs);
       
   280             Object[] args = new Object[nargs];
       
   281             for (int i = 0; i < nargs; i++)
       
   282                 args[i] = "#"+i;
       
   283             Object res = target.invokeWithArguments(args);
       
   284             assertArrayEquals(args, (Object[])res);
       
   285         }
       
   286     }
       
   287 
       
   288     @Test
       
   289     public void testVarargsReferenceArray() throws Throwable {
       
   290         //System.out.println("varargsReferenceArray");
       
   291         testTypedVarargsArray(Object[].class);
       
   292         testTypedVarargsArray(String[].class);
       
   293         testTypedVarargsArray(Number[].class);
       
   294     }
       
   295 
       
   296     @Test
       
   297     public void testVarargsPrimitiveArray() throws Throwable {
       
   298         //System.out.println("varargsPrimitiveArray");
       
   299         testTypedVarargsArray(int[].class);
       
   300         testTypedVarargsArray(long[].class);
       
   301         testTypedVarargsArray(byte[].class);
       
   302         testTypedVarargsArray(boolean[].class);
       
   303         testTypedVarargsArray(short[].class);
       
   304         testTypedVarargsArray(char[].class);
       
   305         testTypedVarargsArray(float[].class);
       
   306         testTypedVarargsArray(double[].class);
       
   307     }
       
   308 
       
   309     private static int nextArgCount(int nargs, int density, int MAX) {
       
   310         if (EXHAUSTIVE)  return nargs + 1;
       
   311         if (nargs >= MAX)  return Integer.MAX_VALUE;
       
   312         int BOT = 20, TOP = MAX-5;
       
   313         if (density < 10) { BOT = 10; MAX = TOP-2; }
       
   314         if (nargs <= BOT || nargs >= TOP) {
       
   315             ++nargs;
       
   316         } else {
       
   317             int bump = Math.max(1, 100 / density);
       
   318             nargs += bump;
       
   319             if (nargs > TOP)  nargs = TOP;
       
   320         }
       
   321         return nargs;
       
   322     }
       
   323 
       
   324     private void testTypedVarargsArray(Class<?> arrayType) throws Throwable {
       
   325         //System.out.println(arrayType.getSimpleName());
       
   326         Class<?> elemType = arrayType.getComponentType();
       
   327         int MIN = START_ARITY;
       
   328         int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
       
   329         int density = 3;
       
   330         if (elemType == int.class || elemType == long.class)  density = 7;
       
   331         if (elemType == long.class || elemType == double.class) { MAX /= 2; MIN /= 2; }
       
   332         for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, density, MAX)) {
       
   333             Object[] args = makeTestArray(elemType, nargs);
       
   334             MethodHandle varargsArray = ValueConversions.varargsArray(arrayType, nargs);
       
   335             MethodType vaType = varargsArray.type();
       
   336             assertEquals(arrayType, vaType.returnType());
       
   337             if (nargs != 0) {
       
   338                 assertEquals(elemType, vaType.parameterType(0));
       
   339                 assertEquals(elemType, vaType.parameterType(vaType.parameterCount()-1));
       
   340             }
       
   341             assertEquals(MethodType.methodType(arrayType, Collections.<Class<?>>nCopies(nargs, elemType)),
       
   342                          vaType);
       
   343             Object res = varargsArray.invokeWithArguments(args);
       
   344             String resString = toArrayString(res);
       
   345             assertEquals(Arrays.toString(args), resString);
       
   346 
       
   347             MethodHandle spreader = varargsArray.asSpreader(arrayType, nargs);
       
   348             MethodType stype = spreader.type();
       
   349             assert(stype == MethodType.methodType(arrayType, arrayType));
       
   350             if (nargs <= 5) {
       
   351                 // invoke target as a spreader also:
       
   352                 @SuppressWarnings("cast")
       
   353                 Object res2 = spreader.invokeWithArguments((Object)res);
       
   354                 String res2String = toArrayString(res2);
       
   355                 assertEquals(Arrays.toString(args), res2String);
       
   356                 // invoke the spreader on a generic Object[] array; check for error
       
   357                 try {
       
   358                     Object res3 = spreader.invokeWithArguments((Object)args);
       
   359                     String res3String = toArrayString(res3);
       
   360                     assertTrue(arrayType.getName(), arrayType.isAssignableFrom(Object[].class));
       
   361                     assertEquals(Arrays.toString(args), res3String);
       
   362                 } catch (ClassCastException ex) {
       
   363                     assertFalse(arrayType.getName(), arrayType.isAssignableFrom(Object[].class));
       
   364                 }
       
   365             }
       
   366             if (nargs == 0) {
       
   367                 // invoke spreader on null arglist
       
   368                 Object res3 = spreader.invokeWithArguments((Object)null);
       
   369                 String res3String = toArrayString(res3);
       
   370                 assertEquals(Arrays.toString(args), res3String);
       
   371             }
       
   372         }
       
   373     }
       
   374 
       
   375     private static Object[] makeTestArray(Class<?> elemType, int len) {
       
   376         Wrapper elem = null;
       
   377         if (elemType.isPrimitive())
       
   378             elem = Wrapper.forPrimitiveType(elemType);
       
   379         else if (Wrapper.isWrapperType(elemType))
       
   380             elem = Wrapper.forWrapperType(elemType);
       
   381         Object[] args = new Object[len];
       
   382         for (int i = 0; i < len; i++) {
       
   383             Object arg = i * 100;
       
   384             if (elem == null) {
       
   385                 if (elemType == String.class)
       
   386                     arg = "#"+arg;
       
   387                 arg = elemType.cast(arg);  // just to make sure
       
   388             } else {
       
   389                 switch (elem) {
       
   390                     case BOOLEAN: arg = (i % 3 == 0);           break;
       
   391                     case CHAR:    arg = 'a' + i;                break;
       
   392                     case LONG:    arg = (long)i * 1000_000_000; break;
       
   393                     case FLOAT:   arg = (float)i / 100;         break;
       
   394                     case DOUBLE:  arg = (double)i / 1000_000;   break;
       
   395                 }
       
   396                 arg = elem.cast(arg, elemType);
       
   397             }
       
   398             args[i] = arg;
       
   399         }
       
   400         //System.out.println(elemType.getName()+Arrays.toString(args));
       
   401         return args;
       
   402     }
       
   403 
       
   404     private static String toArrayString(Object a) {
       
   405         if (a == null)  return "null";
       
   406         Class<?> elemType = a.getClass().getComponentType();
       
   407         if (elemType == null)  return a.toString();
       
   408         if (elemType.isPrimitive()) {
       
   409             switch (Wrapper.forPrimitiveType(elemType)) {
       
   410                 case INT:      return Arrays.toString((int[])a);
       
   411                 case BYTE:     return Arrays.toString((byte[])a);
       
   412                 case BOOLEAN:  return Arrays.toString((boolean[])a);
       
   413                 case SHORT:    return Arrays.toString((short[])a);
       
   414                 case CHAR:     return Arrays.toString((char[])a);
       
   415                 case FLOAT:    return Arrays.toString((float[])a);
       
   416                 case LONG:     return Arrays.toString((long[])a);
       
   417                 case DOUBLE:   return Arrays.toString((double[])a);
       
   418             }
       
   419         }
       
   420         return Arrays.toString((Object[])a);
       
   421     }
       
   422 
       
   423     @Test
       
   424     public void testVarargsList() throws Throwable {
       
   425         //System.out.println("varargsList");
       
   426         final int MIN = START_ARITY;
       
   427         final int MAX = MAX_ARITY-2;  // 253+1 would cause parameter overflow with 'this' added
       
   428         for (int nargs = MIN; nargs <= MAX; nargs = nextArgCount(nargs, 7, MAX)) {
       
   429             MethodHandle target = ValueConversions.varargsList(nargs);
       
   430             Object[] args = new Object[nargs];
       
   431             for (int i = 0; i < nargs; i++)
       
   432                 args[i] = "#"+i;
       
   433             Object res = target.invokeWithArguments(args);
       
   434             assertEquals(Arrays.asList(args), res);
       
   435         }
       
   436     }
       
   437 }
   249 }