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