Home | History | Annotate | Download | only in invoke
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package libcore.java.lang.invoke;
     18 
     19 import junit.framework.TestCase;
     20 
     21 import java.lang.invoke.MethodHandle;
     22 import java.lang.invoke.MethodHandles;
     23 import java.lang.invoke.WrongMethodTypeException;
     24 
     25 import static org.junit.Assert.assertEquals;
     26 import static org.junit.Assert.assertTrue;
     27 import static org.junit.Assert.fail;
     28 
     29 public class MethodHandleAccessorsTest extends junit.framework.TestCase {
     30     public static class ValueHolder {
     31         public boolean m_z = false;
     32         public byte m_b = 0;
     33         public char m_c = 'a';
     34         public short m_s = 0;
     35         public int m_i = 0;
     36         public float m_f = 0.0f;
     37         public double m_d = 0.0;
     38         public long m_j = 0;
     39         public String m_l = "a";
     40 
     41         public static boolean s_z;
     42         public static byte s_b;
     43         public static char s_c;
     44         public static short s_s;
     45         public static int s_i;
     46         public static float s_f;
     47         public static double s_d;
     48         public static long s_j;
     49         public static String s_l;
     50 
     51         public final int m_fi = 0xa5a5a5a5;
     52         public static final int s_fi = 0x5a5a5a5a;
     53     }
     54 
     55     private static enum PrimitiveType {
     56         Boolean,
     57         Byte,
     58         Char,
     59         Short,
     60         Int,
     61         Long,
     62         Float,
     63         Double,
     64         String,
     65     }
     66 
     67     private static enum AccessorType {
     68         IPUT,
     69         SPUT,
     70         IGET,
     71         SGET,
     72     }
     73 
     74     static void setByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure)
     75             throws Throwable {
     76         boolean exceptionThrown = false;
     77         try {
     78             if (v == null) {
     79                 m.invokeExact(value);
     80             }
     81             else {
     82                 m.invokeExact(v, value);
     83             }
     84         }
     85         catch (WrongMethodTypeException e) {
     86             exceptionThrown = true;
     87         }
     88         assertEquals(exceptionThrown, expectFailure);
     89     }
     90 
     91     static void setByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable {
     92         setByte(m, null, value, expectFailure);
     93     }
     94 
     95     static void getByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure)
     96             throws Throwable {
     97         boolean exceptionThrown = false;
     98         try {
     99             final byte got;
    100             if (v == null) {
    101                 got = (byte)m.invokeExact();
    102             } else {
    103                 got = (byte)m.invokeExact(v);
    104             }
    105             assertTrue(got == value);
    106         }
    107         catch (WrongMethodTypeException e) {
    108             exceptionThrown = true;
    109         }
    110         assertEquals(exceptionThrown, expectFailure);
    111     }
    112 
    113     static void getByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable {
    114         getByte(m, null, value, expectFailure);
    115     }
    116 
    117     static void setChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure)
    118             throws Throwable {
    119         boolean exceptionThrown = false;
    120         try {
    121             if (v == null) {
    122                 m.invokeExact(value);
    123             }
    124             else {
    125                 m.invokeExact(v, value);
    126             }
    127         }
    128         catch (WrongMethodTypeException e) {
    129             exceptionThrown = true;
    130         }
    131         assertEquals(exceptionThrown, expectFailure);
    132     }
    133 
    134     static void setChar(MethodHandle m, char value, boolean expectFailure) throws Throwable {
    135         setChar(m, null, value, expectFailure);
    136     }
    137 
    138     static void getChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure)
    139             throws Throwable {
    140         boolean exceptionThrown = false;
    141         try {
    142             final char got;
    143             if (v == null) {
    144                 got = (char)m.invokeExact();
    145             } else {
    146                 got = (char)m.invokeExact(v);
    147             }
    148             assertTrue(got == value);
    149         }
    150         catch (WrongMethodTypeException e) {
    151             exceptionThrown = true;
    152         }
    153         assertEquals(exceptionThrown, expectFailure);
    154     }
    155 
    156     static void getChar(MethodHandle m, char value, boolean expectFailure) throws Throwable {
    157         getChar(m, null, value, expectFailure);
    158     }
    159 
    160     static void setShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure)
    161             throws Throwable {
    162         boolean exceptionThrown = false;
    163         try {
    164             if (v == null) {
    165                 m.invokeExact(value);
    166             }
    167             else {
    168                 m.invokeExact(v, value);
    169             }
    170         }
    171         catch (WrongMethodTypeException e) {
    172             exceptionThrown = true;
    173         }
    174         assertEquals(exceptionThrown, expectFailure);
    175     }
    176 
    177     static void setShort(MethodHandle m, short value, boolean expectFailure) throws Throwable {
    178         setShort(m, null, value, expectFailure);
    179     }
    180 
    181     static void getShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure)
    182             throws Throwable {
    183         boolean exceptionThrown = false;
    184         try {
    185             final short got = (v == null) ? (short)m.invokeExact() : (short)m.invokeExact(v);
    186             assertTrue(got == value);
    187         }
    188         catch (WrongMethodTypeException e) {
    189             exceptionThrown = true;
    190         }
    191         assertEquals(exceptionThrown, expectFailure);
    192     }
    193 
    194     static void getShort(MethodHandle m, short value, boolean expectFailure) throws Throwable {
    195         getShort(m, null, value, expectFailure);
    196     }
    197 
    198     static void setInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure)
    199             throws Throwable {
    200         boolean exceptionThrown = false;
    201         try {
    202             if (v == null) {
    203                 m.invokeExact(value);
    204             }
    205             else {
    206                 m.invokeExact(v, value);
    207             }
    208         }
    209         catch (WrongMethodTypeException e) {
    210             exceptionThrown = true;
    211         }
    212         assertEquals(exceptionThrown, expectFailure);
    213     }
    214 
    215     static void setInt(MethodHandle m, int value, boolean expectFailure) throws Throwable {
    216         setInt(m, null, value, expectFailure);
    217     }
    218 
    219     static void getInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure)
    220             throws Throwable {
    221         boolean exceptionThrown = false;
    222         try {
    223             final int got = (v == null) ? (int)m.invokeExact() : (int)m.invokeExact(v);
    224             assertTrue(got == value);
    225         }
    226         catch (WrongMethodTypeException e) {
    227             exceptionThrown = true;
    228         }
    229         assertEquals(exceptionThrown, expectFailure);
    230     }
    231 
    232     static void getInt(MethodHandle m, int value, boolean expectFailure) throws Throwable {
    233         getInt(m, null, value, expectFailure);
    234     }
    235 
    236     static void setLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure)
    237             throws Throwable {
    238         boolean exceptionThrown = false;
    239         try {
    240             if (v == null) {
    241                 m.invokeExact(value);
    242             }
    243             else {
    244                 m.invokeExact(v, value);
    245             }
    246         }
    247         catch (WrongMethodTypeException e) {
    248             exceptionThrown = true;
    249         }
    250         assertEquals(exceptionThrown, expectFailure);
    251     }
    252 
    253     static void setLong(MethodHandle m, long value, boolean expectFailure) throws Throwable {
    254         setLong(m, null, value, expectFailure);
    255     }
    256 
    257     static void getLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure)
    258             throws Throwable {
    259         boolean exceptionThrown = false;
    260         try {
    261             final long got = (v == null) ? (long)m.invokeExact() : (long)m.invokeExact(v);
    262             assertTrue(got == value);
    263         }
    264         catch (WrongMethodTypeException e) {
    265             exceptionThrown = true;
    266         }
    267         assertEquals(exceptionThrown, expectFailure);
    268     }
    269 
    270     static void getLong(MethodHandle m, long value, boolean expectFailure) throws Throwable {
    271         getLong(m, null, value, expectFailure);
    272     }
    273 
    274     static void setFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure)
    275             throws Throwable {
    276         boolean exceptionThrown = false;
    277         try {
    278             if (v == null) {
    279                 m.invokeExact(value);
    280             }
    281             else {
    282                 m.invokeExact(v, value);
    283             }
    284         }
    285         catch (WrongMethodTypeException e) {
    286             exceptionThrown = true;
    287         }
    288         assertEquals(exceptionThrown, expectFailure);
    289     }
    290 
    291     static void setFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable {
    292         setFloat(m, null, value, expectFailure);
    293     }
    294 
    295     static void getFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure)
    296             throws Throwable {
    297         boolean exceptionThrown = false;
    298         try {
    299             final float got = (v == null) ? (float)m.invokeExact() : (float)m.invokeExact(v);
    300             assertTrue(got == value);
    301         }
    302         catch (WrongMethodTypeException e) {
    303             exceptionThrown = true;
    304         }
    305         assertEquals(exceptionThrown, expectFailure);
    306     }
    307 
    308     static void getFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable {
    309         getFloat(m, null, value, expectFailure);
    310     }
    311 
    312     static void setDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure)
    313             throws Throwable {
    314         boolean exceptionThrown = false;
    315         try {
    316             if (v == null) {
    317                 m.invokeExact(value);
    318             }
    319             else {
    320                 m.invokeExact(v, value);
    321             }
    322         }
    323         catch (WrongMethodTypeException e) {
    324             exceptionThrown = true;
    325         }
    326         assertEquals(exceptionThrown, expectFailure);
    327     }
    328 
    329     static void setDouble(MethodHandle m, double value, boolean expectFailure)
    330             throws Throwable {
    331         setDouble(m, null, value, expectFailure);
    332     }
    333 
    334     static void getDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure)
    335             throws Throwable {
    336         boolean exceptionThrown = false;
    337         try {
    338             final double got = (v == null) ? (double)m.invokeExact() : (double)m.invokeExact(v);
    339             assertTrue(got == value);
    340         }
    341         catch (WrongMethodTypeException e) {
    342             exceptionThrown = true;
    343         }
    344         assertEquals(exceptionThrown, expectFailure);
    345     }
    346 
    347     static void getDouble(MethodHandle m, double value, boolean expectFailure)
    348             throws Throwable {
    349         getDouble(m, null, value, expectFailure);
    350     }
    351 
    352     static void setString(MethodHandle m, ValueHolder v, String value, boolean expectFailure)
    353             throws Throwable {
    354         boolean exceptionThrown = false;
    355         try {
    356             if (v == null) {
    357                 m.invokeExact(value);
    358             }
    359             else {
    360                 m.invokeExact(v, value);
    361             }
    362         }
    363         catch (WrongMethodTypeException e) {
    364             exceptionThrown = true;
    365         }
    366         assertEquals(exceptionThrown, expectFailure);
    367     }
    368 
    369     static void setString(MethodHandle m, String value, boolean expectFailure)
    370             throws Throwable {
    371         setString(m, null, value, expectFailure);
    372     }
    373 
    374     static void getString(MethodHandle m, ValueHolder v, String value, boolean expectFailure)
    375             throws Throwable {
    376         boolean exceptionThrown = false;
    377         try {
    378             final String got = (v == null) ? (String)m.invokeExact() : (String)m.invokeExact(v);
    379             assertTrue(got.equals(value));
    380         }
    381         catch (WrongMethodTypeException e) {
    382             exceptionThrown = true;
    383         }
    384         assertEquals(exceptionThrown, expectFailure);
    385     }
    386 
    387     static void getString(MethodHandle m, String value, boolean expectFailure)
    388             throws Throwable {
    389         getString(m, null, value, expectFailure);
    390     }
    391 
    392     static void setBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure)
    393             throws Throwable {
    394         boolean exceptionThrown = false;
    395         try {
    396             if (v == null) {
    397                 m.invokeExact(value);
    398             }
    399             else {
    400                 m.invokeExact(v, value);
    401             }
    402         }
    403         catch (WrongMethodTypeException e) {
    404             exceptionThrown = true;
    405         }
    406         assertEquals(exceptionThrown, expectFailure);
    407     }
    408 
    409     static void setBoolean(MethodHandle m, boolean value, boolean expectFailure)
    410             throws Throwable {
    411         setBoolean(m, null, value, expectFailure);
    412     }
    413 
    414     static void getBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure)
    415             throws Throwable {
    416         boolean exceptionThrown = false;
    417         try {
    418             final boolean got =
    419                     (v == null) ? (boolean)m.invokeExact() : (boolean)m.invokeExact(v);
    420             assertTrue(got == value);
    421         }
    422         catch (WrongMethodTypeException e) {
    423             exceptionThrown = true;
    424         }
    425         assertEquals(exceptionThrown, expectFailure);
    426     }
    427 
    428     static void getBoolean(MethodHandle m, boolean value, boolean expectFailure)
    429             throws Throwable {
    430         getBoolean(m, null, value, expectFailure);
    431     }
    432 
    433     static boolean resultFor(PrimitiveType actualType, PrimitiveType expectedType,
    434                              AccessorType actualAccessor,
    435                              AccessorType expectedAccessor) {
    436         return (actualType != expectedType) || (actualAccessor != expectedAccessor);
    437     }
    438 
    439     static void tryAccessor(MethodHandle methodHandle,
    440                             ValueHolder valueHolder,
    441                             PrimitiveType primitive,
    442                             Object value,
    443                             AccessorType accessor) throws Throwable {
    444         boolean booleanValue =
    445                 value instanceof Boolean ? ((Boolean)value).booleanValue() : false;
    446         setBoolean(methodHandle, valueHolder, booleanValue,
    447                 resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.IPUT));
    448         setBoolean(methodHandle, booleanValue,
    449                 resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.SPUT));
    450         getBoolean(methodHandle, valueHolder, booleanValue,
    451                 resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.IGET));
    452         getBoolean(methodHandle, booleanValue,
    453                 resultFor(primitive, PrimitiveType.Boolean, accessor, AccessorType.SGET));
    454 
    455         byte byteValue = value instanceof Byte ? ((Byte)value).byteValue() : (byte)0;
    456         setByte(methodHandle, valueHolder, byteValue,
    457                 resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.IPUT));
    458         setByte(methodHandle, byteValue,
    459                 resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.SPUT));
    460         getByte(methodHandle, valueHolder, byteValue,
    461                 resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.IGET));
    462         getByte(methodHandle, byteValue,
    463                 resultFor(primitive, PrimitiveType.Byte, accessor, AccessorType.SGET));
    464 
    465         char charValue = value instanceof Character ? ((Character)value).charValue() : 'z';
    466         setChar(methodHandle, valueHolder, charValue,
    467                 resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.IPUT));
    468         setChar(methodHandle, charValue,
    469                 resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.SPUT));
    470         getChar(methodHandle, valueHolder, charValue,
    471                 resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.IGET));
    472         getChar(methodHandle, charValue,
    473                 resultFor(primitive, PrimitiveType.Char, accessor, AccessorType.SGET));
    474 
    475         short shortValue = value instanceof Short ? ((Short)value).shortValue() : (short)0;
    476         setShort(methodHandle, valueHolder, shortValue,
    477                 resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.IPUT));
    478         setShort(methodHandle, shortValue,
    479                 resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.SPUT));
    480         getShort(methodHandle, valueHolder, shortValue,
    481                 resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.IGET));
    482         getShort(methodHandle, shortValue,
    483                 resultFor(primitive, PrimitiveType.Short, accessor, AccessorType.SGET));
    484 
    485         int intValue = value instanceof Integer ? ((Integer)value).intValue() : -1;
    486         setInt(methodHandle, valueHolder, intValue,
    487                 resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.IPUT));
    488         setInt(methodHandle, intValue,
    489                 resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.SPUT));
    490         getInt(methodHandle, valueHolder, intValue,
    491                 resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.IGET));
    492         getInt(methodHandle, intValue,
    493                 resultFor(primitive, PrimitiveType.Int, accessor, AccessorType.SGET));
    494 
    495         long longValue = value instanceof Long ? ((Long)value).longValue() : (long)-1;
    496         setLong(methodHandle, valueHolder, longValue,
    497                 resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.IPUT));
    498         setLong(methodHandle, longValue,
    499                 resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.SPUT));
    500         getLong(methodHandle, valueHolder, longValue,
    501                 resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.IGET));
    502         getLong(methodHandle, longValue,
    503                 resultFor(primitive, PrimitiveType.Long, accessor, AccessorType.SGET));
    504 
    505         float floatValue = value instanceof Float ? ((Float)value).floatValue() : -1.0f;
    506         setFloat(methodHandle, valueHolder, floatValue,
    507                 resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.IPUT));
    508         setFloat(methodHandle, floatValue,
    509                 resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.SPUT));
    510         getFloat(methodHandle, valueHolder, floatValue,
    511                 resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.IGET));
    512         getFloat(methodHandle, floatValue,
    513                 resultFor(primitive, PrimitiveType.Float, accessor, AccessorType.SGET));
    514 
    515         double doubleValue = value instanceof Double ? ((Double)value).doubleValue() : -1.0;
    516         setDouble(methodHandle, valueHolder, doubleValue,
    517                 resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.IPUT));
    518         setDouble(methodHandle, doubleValue,
    519                 resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.SPUT));
    520         getDouble(methodHandle, valueHolder, doubleValue,
    521                 resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.IGET));
    522         getDouble(methodHandle, doubleValue,
    523                 resultFor(primitive, PrimitiveType.Double, accessor, AccessorType.SGET));
    524 
    525         String stringValue = value instanceof String ? ((String) value) : "No Spock, no";
    526         setString(methodHandle, valueHolder, stringValue,
    527                 resultFor(primitive, PrimitiveType.String, accessor, AccessorType.IPUT));
    528         setString(methodHandle, stringValue,
    529                 resultFor(primitive, PrimitiveType.String, accessor, AccessorType.SPUT));
    530         getString(methodHandle, valueHolder, stringValue,
    531                 resultFor(primitive, PrimitiveType.String, accessor, AccessorType.IGET));
    532         getString(methodHandle, stringValue,
    533                 resultFor(primitive, PrimitiveType.String, accessor, AccessorType.SGET));
    534     }
    535 
    536     public void testBooleanSettersAndGetters() throws Throwable {
    537         ValueHolder valueHolder = new ValueHolder();
    538         MethodHandles.Lookup lookup = MethodHandles.lookup();
    539 
    540         boolean[] booleans = {false, true, false};
    541         for (boolean b : booleans) {
    542             Boolean boxed = new Boolean(b);
    543             tryAccessor(lookup.findSetter(ValueHolder.class, "m_z", boolean.class),
    544                 valueHolder, PrimitiveType.Boolean, boxed, AccessorType.IPUT);
    545             tryAccessor(lookup.findGetter(ValueHolder.class, "m_z", boolean.class),
    546                 valueHolder, PrimitiveType.Boolean, boxed, AccessorType.IGET);
    547             assertTrue(valueHolder.m_z == b);
    548             tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_z", boolean.class),
    549                 valueHolder, PrimitiveType.Boolean, boxed, AccessorType.SPUT);
    550             tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_z", boolean.class),
    551                 valueHolder, PrimitiveType.Boolean, boxed, AccessorType.SGET);
    552             assertTrue(ValueHolder.s_z == b);
    553         }
    554     }
    555 
    556     public void testByteSettersAndGetters() throws Throwable {
    557         ValueHolder valueHolder = new ValueHolder();
    558         MethodHandles.Lookup lookup = MethodHandles.lookup();
    559 
    560         byte[] bytes = {(byte) 0x73, (byte) 0xfe};
    561         for (byte b : bytes) {
    562             Byte boxed = new Byte(b);
    563             tryAccessor(lookup.findSetter(ValueHolder.class, "m_b", byte.class),
    564                 valueHolder, PrimitiveType.Byte, boxed, AccessorType.IPUT);
    565             tryAccessor(lookup.findGetter(ValueHolder.class, "m_b", byte.class),
    566                 valueHolder, PrimitiveType.Byte, boxed, AccessorType.IGET);
    567             assertTrue(valueHolder.m_b == b);
    568             tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_b", byte.class),
    569                 valueHolder, PrimitiveType.Byte, boxed, AccessorType.SPUT);
    570             tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_b", byte.class),
    571                 valueHolder, PrimitiveType.Byte, boxed, AccessorType.SGET);
    572             assertTrue(ValueHolder.s_b == b);
    573         }
    574     }
    575 
    576     public void testCharSettersAndGetters() throws Throwable {
    577         ValueHolder valueHolder = new ValueHolder();
    578         MethodHandles.Lookup lookup = MethodHandles.lookup();
    579 
    580         char[] chars = {'a', 'b', 'c'};
    581         for (char c : chars) {
    582             Character boxed = new Character(c);
    583             tryAccessor(lookup.findSetter(ValueHolder.class, "m_c", char.class),
    584                 valueHolder, PrimitiveType.Char, boxed, AccessorType.IPUT);
    585             tryAccessor(lookup.findGetter(ValueHolder.class, "m_c", char.class),
    586                 valueHolder, PrimitiveType.Char, boxed, AccessorType.IGET);
    587             assertTrue(valueHolder.m_c == c);
    588             tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_c", char.class),
    589                 valueHolder, PrimitiveType.Char, boxed, AccessorType.SPUT);
    590             tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_c", char.class),
    591                 valueHolder, PrimitiveType.Char, boxed, AccessorType.SGET);
    592             assertTrue(ValueHolder.s_c == c);
    593         }
    594     }
    595 
    596     public void testShortSettersAndGetters() throws Throwable {
    597         ValueHolder valueHolder = new ValueHolder();
    598         MethodHandles.Lookup lookup = MethodHandles.lookup();
    599 
    600         short[] shorts = {(short) 0x1234, (short) 0x4321};
    601         for (short s : shorts) {
    602             Short boxed = new Short(s);
    603             tryAccessor(lookup.findSetter(ValueHolder.class, "m_s", short.class),
    604                 valueHolder, PrimitiveType.Short, boxed, AccessorType.IPUT);
    605             tryAccessor(lookup.findGetter(ValueHolder.class, "m_s", short.class),
    606                 valueHolder, PrimitiveType.Short, boxed, AccessorType.IGET);
    607             assertTrue(valueHolder.m_s == s);
    608             tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_s", short.class),
    609                 valueHolder, PrimitiveType.Short, boxed, AccessorType.SPUT);
    610             tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_s", short.class),
    611                 valueHolder, PrimitiveType.Short, boxed, AccessorType.SGET);
    612             assertTrue(ValueHolder.s_s == s);
    613         }
    614     }
    615 
    616     public void testIntSettersAndGetters() throws Throwable {
    617         ValueHolder valueHolder = new ValueHolder();
    618         MethodHandles.Lookup lookup = MethodHandles.lookup();
    619 
    620         int[] ints = {-100000000, 10000000};
    621         for (int i : ints) {
    622             Integer boxed = new Integer(i);
    623             tryAccessor(lookup.findSetter(ValueHolder.class, "m_i", int.class),
    624                 valueHolder, PrimitiveType.Int, boxed, AccessorType.IPUT);
    625             tryAccessor(lookup.findGetter(ValueHolder.class, "m_i", int.class),
    626                 valueHolder, PrimitiveType.Int, boxed, AccessorType.IGET);
    627             assertTrue(valueHolder.m_i == i);
    628             tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_i", int.class),
    629                 valueHolder, PrimitiveType.Int, boxed, AccessorType.SPUT);
    630             tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_i", int.class),
    631                 valueHolder, PrimitiveType.Int, boxed, AccessorType.SGET);
    632             assertTrue(ValueHolder.s_i == i);
    633         }
    634     }
    635 
    636     public void testFloatSettersAndGetters() throws Throwable {
    637         ValueHolder valueHolder = new ValueHolder();
    638         MethodHandles.Lookup lookup = MethodHandles.lookup();
    639 
    640         float[] floats = {0.99f, -1.23e-17f};
    641         for (float f : floats) {
    642             Float boxed = new Float(f);
    643             tryAccessor(lookup.findSetter(ValueHolder.class, "m_f", float.class),
    644                 valueHolder, PrimitiveType.Float, boxed, AccessorType.IPUT);
    645             tryAccessor(lookup.findGetter(ValueHolder.class, "m_f", float.class),
    646                 valueHolder, PrimitiveType.Float, boxed, AccessorType.IGET);
    647             assertTrue(valueHolder.m_f == f);
    648             tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_f", float.class),
    649                 valueHolder, PrimitiveType.Float, boxed, AccessorType.SPUT);
    650             tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_f", float.class),
    651                 valueHolder, PrimitiveType.Float, boxed, AccessorType.SGET);
    652             assertTrue(ValueHolder.s_f == f);
    653         }
    654     }
    655 
    656     public void testDoubleSettersAndGetters() throws Throwable {
    657         ValueHolder valueHolder = new ValueHolder();
    658         MethodHandles.Lookup lookup = MethodHandles.lookup();
    659 
    660         double[] doubles = {0.44444444444e37, -0.555555555e-37};
    661         for (double d : doubles) {
    662             Double boxed = new Double(d);
    663             tryAccessor(lookup.findSetter(ValueHolder.class, "m_d", double.class),
    664                 valueHolder, PrimitiveType.Double, boxed, AccessorType.IPUT);
    665             tryAccessor(lookup.findGetter(ValueHolder.class, "m_d", double.class),
    666                 valueHolder, PrimitiveType.Double, boxed, AccessorType.IGET);
    667             assertTrue(valueHolder.m_d == d);
    668             tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_d", double.class),
    669                 valueHolder, PrimitiveType.Double, boxed, AccessorType.SPUT);
    670             tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_d", double.class),
    671                 valueHolder, PrimitiveType.Double, boxed, AccessorType.SGET);
    672             assertTrue(ValueHolder.s_d == d);
    673         }
    674     }
    675 
    676     public void testLongSettersAndGetters() throws Throwable {
    677         ValueHolder valueHolder = new ValueHolder();
    678         MethodHandles.Lookup lookup = MethodHandles.lookup();
    679 
    680         long[] longs = {0x0123456789abcdefl, 0xfedcba9876543210l};
    681         for (long j : longs) {
    682             Long boxed = new Long(j);
    683             tryAccessor(lookup.findSetter(ValueHolder.class, "m_j", long.class),
    684                 valueHolder, PrimitiveType.Long, boxed, AccessorType.IPUT);
    685             tryAccessor(lookup.findGetter(ValueHolder.class, "m_j", long.class),
    686                 valueHolder, PrimitiveType.Long, boxed, AccessorType.IGET);
    687             assertTrue(valueHolder.m_j == j);
    688             tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_j", long.class),
    689                 valueHolder, PrimitiveType.Long, boxed, AccessorType.SPUT);
    690             tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_j", long.class),
    691                 valueHolder, PrimitiveType.Long, boxed, AccessorType.SGET);
    692             assertTrue(ValueHolder.s_j == j);
    693         }
    694     }
    695 
    696     public void testStringSettersAndGetters() throws Throwable {
    697         ValueHolder valueHolder = new ValueHolder();
    698         MethodHandles.Lookup lookup = MethodHandles.lookup();
    699 
    700         String [] strings = { "octopus", "crab" };
    701         for (String s : strings) {
    702             tryAccessor(lookup.findSetter(ValueHolder.class, "m_l", String.class),
    703                     valueHolder, PrimitiveType.String, s, AccessorType.IPUT);
    704             tryAccessor(lookup.findGetter(ValueHolder.class, "m_l", String.class),
    705                     valueHolder, PrimitiveType.String, s, AccessorType.IGET);
    706             assertTrue(s.equals(valueHolder.m_l));
    707             tryAccessor(lookup.findStaticSetter(ValueHolder.class, "s_l", String.class),
    708                     valueHolder, PrimitiveType.String, s, AccessorType.SPUT);
    709             tryAccessor(lookup.findStaticGetter(ValueHolder.class, "s_l", String.class),
    710                     valueHolder, PrimitiveType.String, s, AccessorType.SGET);
    711             assertTrue(s.equals(ValueHolder.s_l));
    712         }
    713     }
    714 
    715     public void testLookup() throws Throwable {
    716         // NB having a static field test here is essential for
    717         // this test. MethodHandles need to ensure the class
    718         // (ValueHolder) is initialized. This happens in the
    719         // invoke-polymorphic dispatch.
    720         MethodHandles.Lookup lookup = MethodHandles.lookup();
    721         try {
    722             MethodHandle mh = lookup.findStaticGetter(ValueHolder.class, "s_fi", int.class);
    723             int initialValue = (int)mh.invokeExact();
    724             System.out.println(initialValue);
    725         } catch (NoSuchFieldException e) { fail(); }
    726         try {
    727             MethodHandle mh = lookup.findStaticSetter(ValueHolder.class, "s_i", int.class);
    728             mh.invokeExact(0);
    729         } catch (NoSuchFieldException e) { fail(); }
    730         try {
    731             lookup.findStaticGetter(ValueHolder.class, "s_fi", byte.class);
    732             fail();
    733         } catch (NoSuchFieldException e) {}
    734         try {
    735             lookup.findGetter(ValueHolder.class, "s_fi", byte.class);
    736             fail();
    737         } catch (NoSuchFieldException e) {}
    738         try {
    739             lookup.findStaticSetter(ValueHolder.class, "s_fi", int.class);
    740             fail();
    741         } catch (IllegalAccessException e) {}
    742 
    743         lookup.findGetter(ValueHolder.class, "m_fi", int.class);
    744         try {
    745             lookup.findGetter(ValueHolder.class, "m_fi", byte.class);
    746             fail();
    747         } catch (NoSuchFieldException e) {}
    748         try {
    749             lookup.findStaticGetter(ValueHolder.class, "m_fi", byte.class);
    750             fail();
    751         } catch (NoSuchFieldException e) {}
    752         try {
    753             lookup.findSetter(ValueHolder.class, "m_fi", int.class);
    754             fail();
    755         } catch (IllegalAccessException e) {}
    756     }
    757 
    758     public void testStaticGetter() throws Throwable {
    759         MethodHandles.Lookup lookup = MethodHandles.lookup();
    760         MethodHandle h0 = lookup.findStaticGetter(ValueHolder.class, "s_fi", int.class);
    761         h0.invoke();
    762         Number t = (Number)h0.invoke();
    763         int u = (int)h0.invoke();
    764         Integer v = (Integer)h0.invoke();
    765         long w = (long)h0.invoke();
    766         try {
    767             byte x = (byte)h0.invoke();
    768             fail();
    769         } catch (WrongMethodTypeException e) {}
    770         try {
    771             String y = (String)h0.invoke();
    772             fail();
    773         } catch (WrongMethodTypeException e) {}
    774         try {
    775             Long z = (Long)h0.invoke();
    776             fail();
    777         } catch (WrongMethodTypeException e) {}
    778     }
    779 
    780     public void testMemberGetter() throws Throwable {
    781         ValueHolder valueHolder = new ValueHolder();
    782         MethodHandles.Lookup lookup = MethodHandles.lookup();
    783         MethodHandle h0 = lookup.findGetter(ValueHolder.class, "m_fi", int.class);
    784         h0.invoke(valueHolder);
    785         Number t = (Number)h0.invoke(valueHolder);
    786         int u = (int)h0.invoke(valueHolder);
    787         Integer v = (Integer)h0.invoke(valueHolder);
    788         long w = (long)h0.invoke(valueHolder);
    789         try {
    790             byte x = (byte)h0.invoke(valueHolder);
    791             fail();
    792         } catch (WrongMethodTypeException e) {}
    793         try {
    794             String y = (String)h0.invoke(valueHolder);
    795             fail();
    796         } catch (WrongMethodTypeException e) {}
    797         try {
    798             Long z = (Long)h0.invoke(valueHolder);
    799             fail();
    800         } catch (WrongMethodTypeException e) {}
    801     }
    802 
    803     /*package*/ static Number getDoubleAsNumber() {
    804         return new Double(1.4e77);
    805     }
    806     /*package*/ static Number getFloatAsNumber() {
    807         return new Float(7.77);
    808     }
    809     /*package*/ static Object getFloatAsObject() {
    810         return new Float(-7.77);
    811     }
    812 
    813     public void testMemberSetter() throws Throwable {
    814         ValueHolder valueHolder = new ValueHolder();
    815         MethodHandles.Lookup lookup = MethodHandles.lookup();
    816         MethodHandle h0 = lookup.findSetter(ValueHolder.class, "m_f", float.class);
    817         h0.invoke(valueHolder, 0.22f);
    818         h0.invoke(valueHolder, new Float(1.11f));
    819         Number floatNumber = getFloatAsNumber();
    820         h0.invoke(valueHolder, floatNumber);
    821         assertTrue(valueHolder.m_f == floatNumber.floatValue());
    822         Object objNumber = getFloatAsObject();
    823         h0.invoke(valueHolder, objNumber);
    824         assertTrue(valueHolder.m_f == ((Float) objNumber).floatValue());
    825         try {
    826             h0.invoke(valueHolder, (Float)null);
    827             fail();
    828         } catch (NullPointerException e) {}
    829 
    830         h0.invoke(valueHolder, (byte)1);
    831         h0.invoke(valueHolder, (short)2);
    832         h0.invoke(valueHolder, 3);
    833         h0.invoke(valueHolder, 4l);
    834 
    835         assertTrue(null == (Object) h0.invoke(valueHolder, 33));
    836         assertTrue(0.0f == (float) h0.invoke(valueHolder, 33));
    837         assertTrue(0l == (long) h0.invoke(valueHolder, 33));
    838 
    839         try {
    840             h0.invoke(valueHolder, 0.33);
    841             fail();
    842         } catch (WrongMethodTypeException e) {}
    843         try {
    844             Number doubleNumber = getDoubleAsNumber();
    845             h0.invoke(valueHolder, doubleNumber);
    846             fail();
    847         } catch (ClassCastException e) {}
    848         try {
    849             Number doubleNumber = null;
    850             h0.invoke(valueHolder, doubleNumber);
    851             fail();
    852         } catch (NullPointerException e) {}
    853         try {
    854             // Mismatched return type - float != void
    855             float tmp = (float)h0.invoke(valueHolder, 0.45f);
    856             assertTrue(tmp == 0.0);
    857         } catch (Exception e) { fail(); }
    858         try {
    859             h0.invoke(valueHolder, "bam");
    860             fail();
    861         } catch (WrongMethodTypeException e) {}
    862         try {
    863             String s = null;
    864             h0.invoke(valueHolder, s);
    865             fail();
    866         } catch (WrongMethodTypeException e) {}
    867     }
    868 
    869     public void testStaticSetter() throws Throwable {
    870         MethodHandles.Lookup lookup = MethodHandles.lookup();
    871         MethodHandle h0 = lookup.findStaticSetter(ValueHolder.class, "s_f", float.class);
    872         h0.invoke(0.22f);
    873         h0.invoke(new Float(1.11f));
    874         Number floatNumber = new Float(0.88f);
    875         h0.invoke(floatNumber);
    876         assertTrue(ValueHolder.s_f == floatNumber.floatValue());
    877 
    878         try {
    879             h0.invoke((Float)null);
    880             fail();
    881         } catch (NullPointerException e) {}
    882 
    883         h0.invoke((byte)1);
    884         h0.invoke((short)2);
    885         h0.invoke(3);
    886         h0.invoke(4l);
    887 
    888         assertTrue(null == (Object) h0.invoke(33));
    889         assertTrue(0.0f == (float) h0.invoke(33));
    890         assertTrue(0l == (long) h0.invoke(33));
    891 
    892         try {
    893             h0.invoke(0.33);
    894             fail();
    895         } catch (WrongMethodTypeException e) {}
    896         try {
    897             Number doubleNumber = getDoubleAsNumber();
    898             h0.invoke(doubleNumber);
    899             fail();
    900         } catch (ClassCastException e) {}
    901         try {
    902             Number doubleNumber = new Double(1.01);
    903             doubleNumber = (doubleNumber.doubleValue() != 0.1) ? null : doubleNumber;
    904             h0.invoke(doubleNumber);
    905             fail();
    906         } catch (NullPointerException e) {}
    907         try {
    908             // Mismatched return type - float != void
    909             float tmp = (float)h0.invoke(0.45f);
    910             assertTrue(tmp == 0.0);
    911         } catch (Exception e) { fail(); }
    912         try {
    913             h0.invoke("bam");
    914             fail();
    915         } catch (WrongMethodTypeException e) {}
    916         try {
    917             String s = null;
    918             h0.invoke(s);
    919             fail();
    920         } catch (WrongMethodTypeException e) {}
    921     }
    922 }
    923