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