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
17package libcore.java.lang.invoke;
18
19import junit.framework.TestCase;
20
21import java.lang.invoke.MethodHandle;
22import java.lang.invoke.MethodHandles;
23import java.lang.invoke.WrongMethodTypeException;
24
25import static org.junit.Assert.assertEquals;
26import static org.junit.Assert.assertTrue;
27import static org.junit.Assert.fail;
28
29public 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