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 * @run testng TestTryFinallyNested 27 */ 28 29 import org.testng.Assert; 30 import org.testng.annotations.Test; 31 32 import java.lang.reflect.code.OpTransformer; 33 import java.lang.reflect.code.op.CoreOp; 34 import java.lang.reflect.code.Op; 35 import java.lang.reflect.code.interpreter.Interpreter; 36 import java.lang.invoke.MethodHandles; 37 import java.lang.reflect.Method; 38 import java.lang.runtime.CodeReflection; 39 import java.util.ArrayList; 40 import java.util.List; 41 import java.util.Optional; 42 import java.util.function.Consumer; 43 import java.util.function.IntConsumer; 44 import java.util.stream.Stream; 45 46 public class TestTryFinallyNested { 47 @CodeReflection 48 public static void tryCatchFinally(IntConsumer c, int i) { 49 try { 50 try { 51 if (i == 0) { 52 return; 53 } 54 c.accept(0); 55 } catch (IllegalStateException e) { 56 if (i == 1) { 57 return; 58 } 59 c.accept(1); 60 } finally { 61 if (i == 2) { 62 return; 63 } 64 c.accept(2); 65 } 66 if (i == 3) { 67 return; 68 } 69 c.accept(3); 70 } catch (IllegalStateException e) { 71 if (i == 4) { 72 return; 73 } 74 c.accept(4); 75 } finally { 76 if (i == 5) { 77 return; 78 } 79 c.accept(5); 80 } 81 c.accept(6); 82 } 83 84 @Test 85 public void testCatchFinally() { 86 CoreOp.FuncOp f = getFuncOp("tryCatchFinally"); 87 88 f.writeTo(System.out); 89 90 CoreOp.FuncOp lf = f.transform(OpTransformer.LOWERING_TRANSFORMER); 91 92 lf.writeTo(System.out); 93 94 for (int ra = -1; ra < 6; ra++) { 95 int fra = ra; 96 97 Consumer<IntConsumer> test = testConsumer( 98 c -> Interpreter.invoke(MethodHandles.lookup(), lf, c, fra), 99 c -> tryCatchFinally(c, fra) 100 ); 101 102 test.accept(i -> {}); 103 for (int ea = 0; ea < 6; ea++) { 104 int fea = ea; 105 test.accept(i -> { 106 if (i == fea) throw new IllegalStateException(); 107 }); 108 test.accept(i -> { 109 if (i == fea) throw new RuntimeException(); 110 }); 111 } 112 } 113 } 114 115 116 @CodeReflection 117 public static void tryCatchFinallyBreak(IntConsumer c, int i) { 118 a: try { 119 try { 120 if (i == 0) { 121 break a; 122 } 123 c.accept(0); 124 } catch (IllegalStateException e) { 125 if (i == 1) { 126 break a; 127 } 128 c.accept(1); 129 } finally { 130 if (i == 2) { 131 break a; 132 } 133 c.accept(2); 134 } 135 if (i == 3) { 136 break a; 137 } 138 c.accept(3); 139 } catch (IllegalStateException e) { 140 if (i == 4) { 141 break a; 142 } 143 c.accept(4); 144 } finally { 145 if (i == 5) { 146 break a; 147 } 148 c.accept(5); 149 } 150 c.accept(6); 151 } 152 153 @Test 154 public void testCatchFinallyBreak() { 155 CoreOp.FuncOp f = getFuncOp("tryCatchFinallyBreak"); 156 157 f.writeTo(System.out); 158 159 CoreOp.FuncOp lf = f.transform(OpTransformer.LOWERING_TRANSFORMER); 160 161 lf.writeTo(System.out); 162 163 for (int ra = -1; ra < 6; ra++) { 164 int fra = ra; 165 166 Consumer<IntConsumer> test = testConsumer( 167 c -> Interpreter.invoke(MethodHandles.lookup(), lf, c, fra), 168 c -> tryCatchFinallyBreak(c, fra) 169 ); 170 171 test.accept(i -> {}); 172 for (int ea = 0; ea < 6; ea++) { 173 int fea = ea; 174 test.accept(i -> { 175 if (i == fea) throw new IllegalStateException(); 176 }); 177 test.accept(i -> { 178 if (i == fea) throw new RuntimeException(); 179 }); 180 } 181 } 182 } 183 184 185 @CodeReflection 186 public static void tryForLoop(IntConsumer c) { 187 for (int i = 0; i < 8; i++) { 188 c.accept(0); 189 try { 190 if (i == 4) { 191 continue; 192 } else if (i == 5) { 193 break; 194 } 195 c.accept(1); 196 } finally { 197 c.accept(2); 198 } 199 c.accept(3); 200 } 201 c.accept(4); 202 } 203 204 @Test 205 public void testTryForLoop() { 206 CoreOp.FuncOp f = getFuncOp("tryForLoop"); 207 208 f.writeTo(System.out); 209 210 CoreOp.FuncOp lf = f.transform(OpTransformer.LOWERING_TRANSFORMER); 211 212 lf.writeTo(System.out); 213 214 Consumer<IntConsumer> test = testConsumer( 215 c -> Interpreter.invoke(MethodHandles.lookup(), lf, c), 216 TestTryFinallyNested::tryForLoop 217 ); 218 219 test.accept(i -> { }); 220 } 221 222 223 @CodeReflection 224 public static void tryLabeledForLoop(IntConsumer c) { 225 a: for (int i = 0; i < 8; i++) { 226 c.accept(0); 227 b: { 228 try { 229 if (i == 4) { 230 continue a; 231 } else if (i == 5) { 232 break b; 233 } else if (i == 6) { 234 break a; 235 } 236 c.accept(1); 237 } finally { 238 c.accept(2); 239 } 240 c.accept(3); 241 } 242 c.accept(4); 243 } 244 c.accept(5); 245 } 246 247 @Test 248 public void testTryLabeledForLoop() { 249 CoreOp.FuncOp f = getFuncOp("tryLabeledForLoop"); 250 251 f.writeTo(System.out); 252 253 CoreOp.FuncOp lf = f.transform(OpTransformer.LOWERING_TRANSFORMER); 254 255 lf.writeTo(System.out); 256 257 Consumer<IntConsumer> test = testConsumer( 258 c -> Interpreter.invoke(MethodHandles.lookup(), lf, c), 259 TestTryFinallyNested::tryLabeledForLoop 260 ); 261 262 test.accept(i -> { }); 263 } 264 265 266 @CodeReflection 267 public static void tryLambda(IntConsumer c, int i) { 268 try { 269 c.accept(0); 270 Runnable r = () -> { 271 if (i == 0) { 272 c.accept(1); 273 return; 274 } else { 275 c.accept(2); 276 } 277 c.accept(3); 278 }; 279 r.run(); 280 c.accept(4); 281 } finally { 282 c.accept(5); 283 } 284 } 285 286 @Test 287 public void testTryLambda() { 288 CoreOp.FuncOp f = getFuncOp("tryLambda"); 289 290 f.writeTo(System.out); 291 292 CoreOp.FuncOp lf = f.transform(OpTransformer.LOWERING_TRANSFORMER); 293 294 lf.writeTo(System.out); 295 296 for (int ra = 0; ra < 2; ra++) { 297 final int fra = ra; 298 Consumer<IntConsumer> test = testConsumer( 299 c -> Interpreter.invoke(MethodHandles.lookup(), lf, c, fra), 300 c -> tryLambda(c, fra) 301 ); 302 test.accept(i -> { }); 303 } 304 } 305 306 307 static CoreOp.FuncOp getFuncOp(String name) { 308 Optional<Method> om = Stream.of(TestTryFinallyNested.class.getDeclaredMethods()) 309 .filter(m -> m.getName().equals(name)) 310 .findFirst(); 311 312 Method m = om.get(); 313 return m.getCodeModel().get(); 314 } 315 316 static Consumer<IntConsumer> testConsumer(Consumer<IntConsumer> actualR, Consumer<IntConsumer> expectedR) { 317 return c -> { 318 List<Integer> actual = new ArrayList<>(); 319 IntConsumer actualC = actual::add; 320 Throwable actualT = null; 321 try { 322 actualR.accept(actualC.andThen(c)); 323 } catch (Interpreter.InterpreterException e) { 324 throw e; 325 } catch (Throwable t) { 326 actualT = t; 327 if (t instanceof AssertionError) { 328 t.printStackTrace(); 329 } 330 } 331 332 List<Integer> expected = new ArrayList<>(); 333 IntConsumer expectedC = expected::add; 334 Throwable expectedT = null; 335 try { 336 expectedR.accept(expectedC.andThen(c)); 337 } catch (Throwable t) { 338 expectedT = t; 339 } 340 341 Assert.assertEquals( 342 actualT != null ? actualT.getClass() : null, 343 expectedT != null ? expectedT.getClass() : null); 344 Assert.assertEquals(actual, expected); 345 }; 346 } 347 }