1 /*
2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /* @test
25  * @summary basic tests for MethodHandle.invokeWithArguments
26  * @run testng test.java.lang.invoke.InvokeWithArgumentsTest
27  */
28 
29 package test.java.lang.invoke;
30 
31 import org.testng.Assert;
32 import org.testng.annotations.Test;
33 
34 import java.lang.invoke.MethodHandle;
35 import java.lang.invoke.MethodHandles;
36 import java.lang.invoke.WrongMethodTypeException;
37 
38 import static java.lang.invoke.MethodType.methodType;
39 
40 public class InvokeWithArgumentsTest {
41     static final MethodHandles.Lookup L = MethodHandles.lookup();
42 
arity(Object o1, Object o2, Object... a)43     static Object[] arity(Object o1, Object o2, Object... a) {
44         return a;
45     }
46 
47     @Test
testArity()48     public void testArity() throws Throwable {
49         MethodHandle mh = L.findStatic(L.lookupClass(), "arity",
50                                        methodType(Object[].class, Object.class, Object.class, Object[].class));
51 
52         try {
53             mh.invokeWithArguments("");
54             Assert.fail("WrongMethodTypeException expected");
55         } catch (WrongMethodTypeException e) {}
56     }
57 
passThrough(String... a)58     static Object[] passThrough(String... a) {
59         return a;
60     }
61 
pack(Object o, Object... a)62     static Object[] pack(Object o, Object... a) {
63         return a;
64     }
65 
66     @Test
testArrayNoPassThrough()67     public void testArrayNoPassThrough() throws Throwable {
68         String[] actual = {"A", "B"};
69 
70         MethodHandle mh = L.findStatic(L.lookupClass(), "passThrough",
71                                        methodType(Object[].class, String[].class));
72 
73         // Note: the actual array is not preserved, the elements will be
74         // unpacked and then packed into a new array before invoking the method
75         // Android-changed: Cast to Object[] to avoid compilation warning.
76         // String[] expected = (String[]) mh.invokeWithArguments(actual);
77         String[] expected = (String[]) mh.invokeWithArguments((Object[]) actual);
78 
79         Assert.assertTrue(actual != expected, "Array should not pass through");
80         Assert.assertEquals(actual, expected, "Array contents should be equal");
81     }
82 
83     @Test
testArrayPack()84     public void testArrayPack() throws Throwable {
85         String[] actual = new String[]{"A", "B"};
86 
87         MethodHandle mh = L.findStatic(L.lookupClass(), "pack",
88                                        methodType(Object[].class, Object.class, Object[].class));
89 
90         // Note: since String[] can be cast to Object, the actual String[] array
91         // will cast to Object become the single element of a new Object[] array
92         Object[] expected = (Object[]) mh.invokeWithArguments("", actual);
93 
94         Assert.assertEquals(1, expected.length, "Array should contain just one element");
95         Assert.assertTrue(actual == expected[0], "Array should pass through");
96     }
97 
intArray(int... a)98     static void intArray(int... a) {
99     }
100 
101     @Test
testPrimitiveArrayWithNull()102     public void testPrimitiveArrayWithNull() throws Throwable {
103         MethodHandle mh = L.findStatic(L.lookupClass(), "intArray",
104                                        methodType(void.class, int[].class));
105         try {
106             mh.invokeWithArguments(null, null);
107             Assert.fail("NullPointerException expected");
108         } catch (NullPointerException e) {}
109     }
110 
111     @Test
testPrimitiveArrayWithRef()112     public void testPrimitiveArrayWithRef() throws Throwable {
113         MethodHandle mh = L.findStatic(L.lookupClass(), "intArray",
114                                        methodType(void.class, int[].class));
115         try {
116             mh.invokeWithArguments("A", "B");
117             Assert.fail("ClassCastException expected");
118         } catch (ClassCastException e) {}
119     }
120 
121 
numberArray(Number... a)122     static void numberArray(Number... a) {
123     }
124 
125     @Test
testRefArrayWithCast()126     public void testRefArrayWithCast() throws Throwable {
127         MethodHandle mh = L.findStatic(L.lookupClass(), "numberArray",
128                                        methodType(void.class, Number[].class));
129         // All numbers, should not throw
130         mh.invokeWithArguments(1, 1.0, 1.0F, 1L);
131 
132         try {
133             mh.invokeWithArguments("A");
134             Assert.fail("ClassCastException expected");
135         } catch (ClassCastException e) {}
136     }
137 }
138