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/*
25 * @test
26 * @bug 8173587
27 * @summary metafactory should fail if the method name is not legal
28 */
29import java.lang.invoke.*;
30import java.util.*;
31
32public class MetafactoryMethodNameTest {
33
34    public static void main(String... args) {
35        goodName("x");
36        goodName("xy");
37
38        goodName("]");
39        goodName("x]");
40        goodName("]y");
41        goodName("x]y");
42
43        goodName("&");
44        goodName("x&");
45        goodName("&y");
46        goodName("x&y");
47
48        badName(".");
49        badName("x.");
50        badName(".y");
51        badName("x.y");
52
53        badName(";");
54        badName("x;");
55        badName(";y");
56        badName("x;y");
57
58        badName("[");
59        badName("x[");
60        badName("[y");
61        badName("x[y");
62
63        badName("/");
64        badName("x/");
65        badName("/y");
66        badName("x/y");
67
68        badName("<");
69        badName("x<");
70        badName("<y");
71        badName("x<y");
72
73        badName(">");
74        badName("x>");
75        badName(">y");
76        badName("x>y");
77
78        badName("");
79        badName("<init>");
80        badName("<clinit>");
81    }
82
83    static MethodType mt(Class<?> ret, Class<?>... params) {
84        return MethodType.methodType(ret, params);
85    }
86
87    static MethodHandle smh(Class<?> c, String name, MethodType desc) {
88        try {
89            return MethodHandles.lookup().findStatic(c, name, desc);
90        } catch (ReflectiveOperationException e) {
91            throw new RuntimeException(e);
92        }
93    }
94
95    static Object[] arr(Object... args) {
96        return args;
97    }
98
99    public static class C {
100        public static void m() {}
101    }
102
103    public interface I {}
104
105    private static MethodHandles.Lookup lookup = MethodHandles.lookup();
106    private static MethodType toI = mt(I.class);
107    private static MethodType toVoid = mt(void.class);
108    private static MethodHandle mh = smh(C.class, "m", toVoid);
109    private static Class<?> lce = LambdaConversionException.class;
110
111    static void goodName(String name) {
112        succeedMFLinkage(lookup, name, toI, toVoid, mh, toVoid);
113        succeedAltMFLinkage(lookup, name, toI, arr(toVoid, mh, toVoid, LambdaMetafactory.FLAG_SERIALIZABLE));
114    }
115
116    static void badName(String name) {
117        failMFLinkage(lookup, name, toI, toVoid, mh, toVoid, lce);
118        failAltMFLinkage(lookup, name, toI, arr(toVoid, mh, toVoid, LambdaMetafactory.FLAG_SERIALIZABLE), lce);
119    }
120
121    static CallSite succeedMFLinkage(MethodHandles.Lookup lookup,
122                                    String name,
123                                    MethodType capType,
124                                    MethodType desc,
125                                    MethodHandle impl,
126                                    MethodType checked) {
127        try {
128            return LambdaMetafactory.metafactory(lookup, name, capType, desc, impl, checked);
129        } catch (Throwable t) {
130            String msg = String.format("Unexpected exception during linkage for metafactory(%s, %s, %s, %s, %s, %s)",
131                    lookup, name, capType, desc, impl, checked);
132            throw new AssertionError(msg, t);
133        }
134    }
135
136    static void failMFLinkage(MethodHandles.Lookup lookup,
137                              String name,
138                              MethodType capType,
139                              MethodType desc,
140                              MethodHandle impl,
141                              MethodType checked,
142                              Class<?> expectedExceptionType) {
143        try {
144            LambdaMetafactory.metafactory(lookup, name, capType, desc, impl, checked);
145        } catch (Throwable t) {
146            if (expectedExceptionType.isInstance(t)) {
147                return;
148            } else {
149                String msg = String.format("Unexpected exception: expected %s during linkage for metafactory(%s, %s, %s, %s, %s, %s)",
150                        expectedExceptionType.getName(),
151                        lookup, name, capType, desc, impl, checked);
152                throw new AssertionError(msg, t);
153            }
154        }
155        String msg = String.format("Unexpected success: expected %s during linkage for metafactory(%s, %s, %s, %s, %s, %s)",
156                expectedExceptionType.getName(),
157                lookup, name, capType, desc, impl, checked);
158        throw new AssertionError(msg);
159    }
160
161    static CallSite succeedAltMFLinkage(MethodHandles.Lookup lookup,
162                                        String name,
163                                        MethodType capType,
164                                        Object[] args) {
165        try {
166            return LambdaMetafactory.altMetafactory(lookup, name, capType, args);
167        } catch (Throwable t) {
168            String msg = String.format("Unexpected exception during linkage for metafactory(%s, %s, %s, %s)",
169                    lookup, name, capType, Arrays.asList(args));
170            throw new AssertionError(msg, t);
171        }
172    }
173
174    static void failAltMFLinkage(MethodHandles.Lookup lookup,
175                                 String name,
176                                 MethodType capType,
177                                 Object[] args,
178                                 Class<?> expectedExceptionType) {
179        try {
180            LambdaMetafactory.altMetafactory(lookup, name, capType, args);
181        } catch (Throwable t) {
182            if (expectedExceptionType.isInstance(t)) {
183                return;
184            } else {
185                String msg = String.format("Unexpected exception: expected %s during linkage for metafactory(%s, %s, %s, %s)",
186                        expectedExceptionType.getName(),
187                        lookup, name, capType, Arrays.asList(args));
188                throw new AssertionError(msg, t);
189            }
190        }
191        String msg = String.format("Unexpected success: expected %s during linkage for metafactory(%s, %s, %s, %s)",
192                expectedExceptionType.getName(),
193                lookup, name, capType, Arrays.asList(args));
194        throw new AssertionError(msg);
195    }
196
197}
198