1 /*
2 * Copyright (c) 2024, 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 import jdk.incubator.code.Reflect;
25 import jdk.incubator.code.Op;
26 import jdk.incubator.code.dialect.core.CoreOp;
27 import jdk.incubator.code.interpreter.Interpreter;
28 import org.junit.jupiter.api.Assertions;
29 import org.junit.jupiter.params.ParameterizedTest;
30 import org.junit.jupiter.params.provider.MethodSource;
31
32 import java.lang.invoke.MethodHandles;
33 import java.lang.reflect.InvocationTargetException;
34 import java.lang.reflect.Method;
35 import java.util.HashMap;
36 import java.util.Map;
37 import java.util.Set;
38 import java.util.stream.Stream;
39
40 /*
41 * @test
42 * @modules jdk.incubator.code
43 * @run junit TestConcat
44 * @run main Unreflect TestConcat
45 * @run junit TestConcat
46 */
47
48 public class TestConcat {
49
50 static final String TESTSTR = "TESTING STRING";
51
52 @Reflect
53 static String f() {
54 int test = 1;
55 String res = "HI " + TESTSTR + test;
56 return res;
57 }
58
59
60 @Reflect
61 public static String byteConcat1(byte b, String s) {
62 return b + s;
63 }
64
65 @Reflect
66 public static String byteConcat2(String s, byte b) {
67 return s + b;
68 }
69
70 @Reflect
71 public static String shortConcat1(short b, String s) {
72 return b + s;
73 }
74
75 @Reflect
76 public static String shortConcat2(String s, short b) {
77 return s + b;
78 }
79
80 @Reflect
81 public static String intConcat1(int b, String s) {
82 return b + s;
83 }
84
85 @Reflect
86 public static String intConcat2(String s, int b) {
87 return s + b;
88 }
89
90 @Reflect
91 public static String longConcat1(long b, String s) {
92 return b + s;
93 }
94
95 @Reflect
96 public static String longConcat2(String s, long b) {
97 return s + b;
98 }
99
100 @Reflect
101 public static String floatConcat1(float b, String s) {
102 return b + s;
103 }
104
105 @Reflect
106 public static String floatConcat2(String s, float b) {
107 return s + b;
108 }
109
110 @Reflect
111 public static String doubleConcat1(double b, String s) {
112 return b + s;
113 }
114
115 @Reflect
116 public static String doubleConcat2(String s, double b) {
117 return s + b;
118 }
119
120 @Reflect
121 public static String booleanConcat1(boolean b, String s) {
122 return b + s;
123 }
124
125 @Reflect
126 public static String booleanConcat2(String s, boolean b) {
127 return s + b;
128 }
129
130 @Reflect
131 public static String charConcat1(char b, String s) {
132 return b + s;
133 }
134 @Reflect
135 public static String charConcat2(String s, char b) {
136 return s + b;
137 }
138 @Reflect
139 public static String objectConcat1(Object b, String s) {
140 return b + s;
141 }
142
143 @Reflect
144 public static String objectConcat2(String s, Object b) {
145 return s + b;
146 }
147
148 @Reflect
149 public static String objectConcat3(TestObject b, String s) {
150 return b + s;
151 }
152
153 @Reflect
154 public static String objectConcat4(String s, TestObject b) {
155 return s + b;
156 }
157
158 @Reflect
159 public static String stringConcat(String b, String s) {
160 return b + s;
161 }
162
163
164 record TestMethodData(Class<?> first, Class<?> second, String third) {
165 }
166
167 static final Map<Class<?>, Object> valMap;
168 static {
169 valMap = new HashMap<>();
170 valMap.put(byte.class, (byte) 42);
171 valMap.put(short.class, (short) 42);
172 valMap.put(int.class, 42);
173 valMap.put(long.class, (long) 42);
174 valMap.put(float.class, 42f);
175 valMap.put(double.class, 42d);
176 valMap.put(char.class, 'z');
177 valMap.put(boolean.class, false);
178 valMap.put(Object.class, new Object() {
179 @Override
180 public String toString() {
181 return "I'm a test string.";
182 }
183 });
184 valMap.put(TestObject.class, new TestObject());
185 valMap.put(String.class, TESTSTR);
186 }
187 private static String testName(Class<?> n, Integer i){
188 return n.getSimpleName().toLowerCase() + "Concat" + i;
189 }
190
191 public static Stream<TestMethodData> testData() {
192 Set<Class<?>> types = Set.of(byte.class, short.class, int.class, long.class, float.class,
193 double.class, char.class, boolean.class, Object.class);
194
195 //Types from types concatenated to strings left-to-right and right-to-left
196 Stream<TestMethodData> s1 = types.stream().map(t -> new TestMethodData(t, String.class, testName(t, 1)));
197 Stream<TestMethodData> s2 = types.stream().map(t -> new TestMethodData(String.class, t, testName(t, 2)));
198
199 //Custom Object and basic string concat tests
200 Stream<TestMethodData> s3 = Stream.of(new TestMethodData(TestObject.class, String.class, testName(Object.class, 3)),
201 new TestMethodData(String.class, TestObject.class, testName(Object.class, 4)),
202 new TestMethodData(String.class, String.class, "stringConcat"));
203
204 return Stream.concat(Stream.concat(s1,s2),s3);
205 }
206
207 @ParameterizedTest
208 @MethodSource("testData")
209 public static void testRun(TestMethodData t) {
210 try {
211 Object[] args = new Object[] {valMap.get(t.first), valMap.get(t.second)};
212 Class<TestConcat> clazz = TestConcat.class;
213 Method method = clazz.getDeclaredMethod(t.third, t.first, t.second);
214 CoreOp.FuncOp f = Op.ofMethod(method).orElseThrow();
215 var res1 = Interpreter.invoke(MethodHandles.lookup(), f, args);
216 var res2 = method.invoke(null, args);
217
218 Assertions.assertEquals(res2, res1);
219
220 } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
221 throw new RuntimeException(e);
222 }
223 }
224
225 public static final class TestObject {
226 TestObject(){}
227
228 @Override
229 public String toString() {
230 return "TestObject String";
231 }
232 }
233 }