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 27 import jdk.incubator.code.OpTransformer; 28 import jdk.incubator.code.dialect.core.CoreOp; 29 import jdk.incubator.code.Op; 30 import jdk.incubator.code.bytecode.BytecodeGenerator; 31 import jdk.incubator.code.interpreter.Interpreter; 32 33 import java.lang.invoke.MethodHandle; 34 import java.lang.invoke.MethodHandles; 35 import java.lang.reflect.Method; 36 import jdk.incubator.code.CodeReflection; 37 import java.util.ArrayList; 38 import java.util.List; 39 import java.util.Optional; 40 import java.util.function.Consumer; 41 import java.util.function.IntConsumer; 42 import java.util.stream.Stream; 43 44 /* 45 * @test 46 * @modules jdk.incubator.code 47 * @run testng TestTryFinally 48 */ 49 50 public class TestTryFinally { 51 52 @CodeReflection 53 public static void tryCatchFinally(IntConsumer c) { 54 try { 55 c.accept(0); 56 c.accept(-1); 57 } catch (IllegalStateException e) { 58 c.accept(1); 59 c.accept(-1); 60 } finally { 61 c.accept(2); 62 c.accept(-1); 63 } 64 c.accept(3); 65 c.accept(-1); 66 } 67 68 @Test 69 public void testCatchFinally() { 70 CoreOp.FuncOp f = getFuncOp("tryCatchFinally"); 71 72 MethodHandle mh = generate(f); 73 74 Consumer<IntConsumer> test = testConsumer( 75 asConsumer(mh), 76 TestTryFinally::tryCatchFinally 77 ); 78 79 test(test); 80 } 81 82 83 @CodeReflection 84 public static void tryReturn(IntConsumer c) { 85 try { 86 c.accept(0); 87 c.accept(-1); 88 return; 89 } catch (IllegalStateException e) { 90 c.accept(1); 91 c.accept(-1); 92 } finally { 93 c.accept(2); 94 c.accept(-1); 95 } 96 c.accept(3); 97 c.accept(-1); 98 } 99 100 @Test 101 public void testTryReturn() { 102 CoreOp.FuncOp f = getFuncOp("tryReturn"); 103 104 MethodHandle mh = generate(f); 105 106 Consumer<IntConsumer> test = testConsumer( 107 asConsumer(mh), 108 TestTryFinally::tryReturn 109 ); 110 111 test(test); 112 } 113 114 115 @CodeReflection 116 public static void catchThrow(IntConsumer c) { 117 try { 118 c.accept(0); 119 c.accept(-1); 120 } catch (IllegalStateException e) { 121 c.accept(1); 122 c.accept(-1); 123 throw e; 124 } finally { 125 c.accept(2); 126 c.accept(-1); 127 } 128 c.accept(3); 129 c.accept(-1); 130 } 131 132 @Test 133 public void testCatchThrow() { 134 CoreOp.FuncOp f = getFuncOp("catchThrow"); 135 136 MethodHandle mh = generate(f); 137 138 Consumer<IntConsumer> test = testConsumer( 139 asConsumer(mh), 140 TestTryFinally::catchThrow 141 ); 142 143 test(test); 144 } 145 146 147 @CodeReflection 148 public static void finallyReturn(IntConsumer c) { 149 try { 150 c.accept(0); 151 c.accept(-1); 152 } catch (IllegalStateException e) { 153 c.accept(1); 154 c.accept(-1); 155 } finally { 156 c.accept(2); 157 c.accept(-1); 158 return; 159 } 160 } 161 162 @Test 163 public void testFinallyReturn() { 164 CoreOp.FuncOp f = getFuncOp("finallyReturn"); 165 166 MethodHandle mh = generate(f); 167 168 Consumer<IntConsumer> test = testConsumer( 169 asConsumer(mh), 170 TestTryFinally::finallyReturn 171 ); 172 173 test(test); 174 } 175 176 177 static void test(Consumer<IntConsumer> test) { 178 test.accept(i -> {}); 179 test.accept(i -> { 180 if (i == 0) throw new IllegalStateException(); 181 }); 182 test.accept(i -> { 183 if (i == 0) throw new RuntimeException(); 184 }); 185 test.accept(i -> { 186 if (i == 2) throw new RuntimeException(); 187 }); 188 test.accept(i -> { 189 if (i == 0) throw new IllegalStateException(); 190 if (i == 1) throw new RuntimeException(); 191 }); 192 test.accept(i -> { 193 if (i == 3) throw new RuntimeException(); 194 }); 195 } 196 197 static MethodHandle generate(CoreOp.FuncOp f) { 198 System.out.println(f.toText()); 199 200 CoreOp.FuncOp lf = f.transform(OpTransformer.LOWERING_TRANSFORMER); 201 System.out.println(lf.toText()); 202 203 return BytecodeGenerator.generate(MethodHandles.lookup(), lf); 204 } 205 206 static <T> Consumer<T> asConsumer(MethodHandle mh) { 207 return c -> { 208 try { 209 mh.invoke(c); 210 } catch (Throwable e) { 211 throw erase(e); 212 } 213 }; 214 } 215 216 @SuppressWarnings("unchecked") 217 public static <E extends Throwable> E erase(Throwable e) throws E { 218 return (E) e; 219 } 220 221 static CoreOp.FuncOp getFuncOp(String name) { 222 Optional<Method> om = Stream.of(TestTryFinally.class.getDeclaredMethods()) 223 .filter(m -> m.getName().equals(name)) 224 .findFirst(); 225 226 Method m = om.get(); 227 return Op.ofMethod(m).get(); 228 } 229 230 static Consumer<IntConsumer> testConsumer(Consumer<IntConsumer> actualR, Consumer<IntConsumer> expectedR) { 231 return c -> { 232 List<Integer> actual = new ArrayList<>(); 233 IntConsumer actualC = actual::add; 234 Throwable actualT = null; 235 try { 236 actualR.accept(actualC.andThen(c)); 237 } catch (Interpreter.InterpreterException e) { 238 throw e; 239 } catch (Throwable t) { 240 actualT = t; 241 if (t instanceof AssertionError) { 242 t.printStackTrace(); 243 } 244 } 245 246 List<Integer> expected = new ArrayList<>(); 247 IntConsumer expectedC = expected::add; 248 Throwable expectedT = null; 249 try { 250 expectedR.accept(expectedC.andThen(c)); 251 } catch (Throwable t) { 252 expectedT = t; 253 } 254 255 Assert.assertEquals( 256 actualT != null ? actualT.getClass() : null, 257 expectedT != null ? expectedT.getClass() : null); 258 Assert.assertEquals(actual, expected); 259 }; 260 } 261 }