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 
setByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure)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 
setByte(MethodHandle m, byte value, boolean expectFailure)91     static void setByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable {
92         setByte(m, null, value, expectFailure);
93     }
94 
getByte(MethodHandle m, ValueHolder v, byte value, boolean expectFailure)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 
getByte(MethodHandle m, byte value, boolean expectFailure)113     static void getByte(MethodHandle m, byte value, boolean expectFailure) throws Throwable {
114         getByte(m, null, value, expectFailure);
115     }
116 
setChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure)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 
setChar(MethodHandle m, char value, boolean expectFailure)134     static void setChar(MethodHandle m, char value, boolean expectFailure) throws Throwable {
135         setChar(m, null, value, expectFailure);
136     }
137 
getChar(MethodHandle m, ValueHolder v, char value, boolean expectFailure)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 
getChar(MethodHandle m, char value, boolean expectFailure)156     static void getChar(MethodHandle m, char value, boolean expectFailure) throws Throwable {
157         getChar(m, null, value, expectFailure);
158     }
159 
setShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure)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 
setShort(MethodHandle m, short value, boolean expectFailure)177     static void setShort(MethodHandle m, short value, boolean expectFailure) throws Throwable {
178         setShort(m, null, value, expectFailure);
179     }
180 
getShort(MethodHandle m, ValueHolder v, short value, boolean expectFailure)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 
getShort(MethodHandle m, short value, boolean expectFailure)194     static void getShort(MethodHandle m, short value, boolean expectFailure) throws Throwable {
195         getShort(m, null, value, expectFailure);
196     }
197 
setInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure)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 
setInt(MethodHandle m, int value, boolean expectFailure)215     static void setInt(MethodHandle m, int value, boolean expectFailure) throws Throwable {
216         setInt(m, null, value, expectFailure);
217     }
218 
getInt(MethodHandle m, ValueHolder v, int value, boolean expectFailure)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 
getInt(MethodHandle m, int value, boolean expectFailure)232     static void getInt(MethodHandle m, int value, boolean expectFailure) throws Throwable {
233         getInt(m, null, value, expectFailure);
234     }
235 
setLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure)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 
setLong(MethodHandle m, long value, boolean expectFailure)253     static void setLong(MethodHandle m, long value, boolean expectFailure) throws Throwable {
254         setLong(m, null, value, expectFailure);
255     }
256 
getLong(MethodHandle m, ValueHolder v, long value, boolean expectFailure)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 
getLong(MethodHandle m, long value, boolean expectFailure)270     static void getLong(MethodHandle m, long value, boolean expectFailure) throws Throwable {
271         getLong(m, null, value, expectFailure);
272     }
273 
setFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure)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 
setFloat(MethodHandle m, float value, boolean expectFailure)291     static void setFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable {
292         setFloat(m, null, value, expectFailure);
293     }
294 
getFloat(MethodHandle m, ValueHolder v, float value, boolean expectFailure)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 
getFloat(MethodHandle m, float value, boolean expectFailure)308     static void getFloat(MethodHandle m, float value, boolean expectFailure) throws Throwable {
309         getFloat(m, null, value, expectFailure);
310     }
311 
setDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure)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 
setDouble(MethodHandle m, double value, boolean expectFailure)329     static void setDouble(MethodHandle m, double value, boolean expectFailure)
330             throws Throwable {
331         setDouble(m, null, value, expectFailure);
332     }
333 
getDouble(MethodHandle m, ValueHolder v, double value, boolean expectFailure)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 
getDouble(MethodHandle m, double value, boolean expectFailure)347     static void getDouble(MethodHandle m, double value, boolean expectFailure)
348             throws Throwable {
349         getDouble(m, null, value, expectFailure);
350     }
351 
setString(MethodHandle m, ValueHolder v, String value, boolean expectFailure)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 
setString(MethodHandle m, String value, boolean expectFailure)369     static void setString(MethodHandle m, String value, boolean expectFailure)
370             throws Throwable {
371         setString(m, null, value, expectFailure);
372     }
373 
getString(MethodHandle m, ValueHolder v, String value, boolean expectFailure)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 
getString(MethodHandle m, String value, boolean expectFailure)387     static void getString(MethodHandle m, String value, boolean expectFailure)
388             throws Throwable {
389         getString(m, null, value, expectFailure);
390     }
391 
setBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure)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 
setBoolean(MethodHandle m, boolean value, boolean expectFailure)409     static void setBoolean(MethodHandle m, boolean value, boolean expectFailure)
410             throws Throwable {
411         setBoolean(m, null, value, expectFailure);
412     }
413 
getBoolean(MethodHandle m, ValueHolder v, boolean value, boolean expectFailure)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 
getBoolean(MethodHandle m, boolean value, boolean expectFailure)428     static void getBoolean(MethodHandle m, boolean value, boolean expectFailure)
429             throws Throwable {
430         getBoolean(m, null, value, expectFailure);
431     }
432 
resultFor(PrimitiveType actualType, PrimitiveType expectedType, AccessorType actualAccessor, AccessorType expectedAccessor)433     static boolean resultFor(PrimitiveType actualType, PrimitiveType expectedType,
434                              AccessorType actualAccessor,
435                              AccessorType expectedAccessor) {
436         return (actualType != expectedType) || (actualAccessor != expectedAccessor);
437     }
438 
tryAccessor(MethodHandle methodHandle, ValueHolder valueHolder, PrimitiveType primitive, Object value, AccessorType accessor)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 
testBooleanSettersAndGetters()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 
testByteSettersAndGetters()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 
testCharSettersAndGetters()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 
testShortSettersAndGetters()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 
testIntSettersAndGetters()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 
testFloatSettersAndGetters()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 
testDoubleSettersAndGetters()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 
testLongSettersAndGetters()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 
testStringSettersAndGetters()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 
testLookup()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 
testStaticGetter()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 
testMemberGetter()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 
getDoubleAsNumber()803     /*package*/ static Number getDoubleAsNumber() {
804         return new Double(1.4e77);
805     }
getFloatAsNumber()806     /*package*/ static Number getFloatAsNumber() {
807         return new Float(7.77);
808     }
getFloatAsObject()809     /*package*/ static Object getFloatAsObject() {
810         return new Float(-7.77);
811     }
812 
testMemberSetter()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 
testStaticSetter()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