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 junit TestTryNested
28 * @run main Unreflect TestTryNested
29 * @run junit TestTryNested
30 */
31
32 import jdk.incubator.code.Reflect;
33 import jdk.incubator.code.CodeTransformer;
34 import jdk.incubator.code.Op;
35 import jdk.incubator.code.dialect.core.CoreOp;
36 import jdk.incubator.code.interpreter.Interpreter;
37 import org.junit.jupiter.api.Assertions;
38 import org.junit.jupiter.api.Test;
39
40 import java.lang.invoke.MethodHandles;
41 import java.lang.reflect.Method;
42 import java.util.ArrayList;
43 import java.util.List;
44 import java.util.Optional;
45 import java.util.function.Consumer;
46 import java.util.function.IntConsumer;
47 import java.util.stream.Stream;
48
49 public class TestTryNested {
50 @Reflect
51 public static void tryCatchFinally(IntConsumer c, int i) {
52 try {
53 try {
54 if (i == 0) {
55 return;
56 }
57 c.accept(0);
58 } catch (IllegalStateException e) {
59 if (i == 1) {
60 return;
61 }
62 c.accept(1);
63 } finally {
64 if (i == 2) {
65 return;
66 }
67 c.accept(2);
68 }
69 if (i == 3) {
70 return;
71 }
72 c.accept(3);
73 } catch (IllegalStateException e) {
74 if (i == 4) {
75 return;
76 }
77 c.accept(4);
78 } finally {
79 if (i == 5) {
80 return;
81 }
82 c.accept(5);
83 }
84 c.accept(6);
85 }
86
87 @Test
88 public void testCatchFinally() {
89 CoreOp.FuncOp f = getFuncOp("tryCatchFinally");
90
91 System.out.println(f.toText());
92
93 CoreOp.FuncOp lf = f.transform(CodeTransformer.LOWERING_TRANSFORMER);
94
95 System.out.println(lf.toText());
96
97 for (int ra = -1; ra < 6; ra++) {
98 int fra = ra;
99
100 Consumer<IntConsumer> test = testConsumer(
101 c -> Interpreter.invoke(MethodHandles.lookup(), lf, c, fra),
102 c -> tryCatchFinally(c, fra)
103 );
104
105 test.accept(i -> {});
106 for (int ea = 0; ea < 6; ea++) {
107 int fea = ea;
108 test.accept(i -> {
109 if (i == fea) throw new IllegalStateException();
110 });
111 test.accept(i -> {
112 if (i == fea) throw new RuntimeException();
113 });
114 }
115 }
116 }
117
118
119 @Reflect
120 public static void tryCatchBreak(IntConsumer c, int i) {
121 a: try {
122 try {
123 if (i == 0) {
124 break a;
125 }
126 c.accept(0);
127 } catch (IllegalStateException e) {
128 if (i == 1) {
129 break a;
130 }
131 c.accept(1);
132 }
133 if (i == 2) {
134 break a;
135 }
136 c.accept(2);
137 } catch (IllegalStateException e) {
138 if (i == 3) {
139 break a;
140 }
141 c.accept(3);
142 }
143 c.accept(4);
144 }
145
146 @Test
147 public void testCatchBreak() {
148 CoreOp.FuncOp f = getFuncOp("tryCatchBreak");
149
150 System.out.println(f.toText());
151
152 CoreOp.FuncOp lf = f.transform(CodeTransformer.LOWERING_TRANSFORMER);
153
154 System.out.println(lf.toText());
155
156 for (int ra = -1; ra < 4; ra++) {
157 int fra = ra;
158
159 Consumer<IntConsumer> test = testConsumer(
160 c -> Interpreter.invoke(MethodHandles.lookup(), lf, c, fra),
161 c -> tryCatchBreak(c, fra)
162 );
163
164 test.accept(i -> {});
165 for (int ea = 0; ea <= 4; ea++) {
166 int fea = ea;
167 test.accept(i -> {
168 if (i == fea) throw new IllegalStateException();
169 });
170 test.accept(i -> {
171 if (i == fea) throw new RuntimeException();
172 });
173 }
174 }
175 }
176
177 @Reflect
178 public static void tryCatchFinallyBreak(IntConsumer c, int i) {
179 a: try {
180 try {
181 if (i == 0) {
182 break a;
183 }
184 c.accept(0);
185 } catch (IllegalStateException e) {
186 if (i == 1) {
187 break a;
188 }
189 c.accept(1);
190 } finally {
191 if (i == 2) {
192 break a;
193 }
194 c.accept(2);
195 }
196 if (i == 3) {
197 break a;
198 }
199 c.accept(3);
200 } catch (IllegalStateException e) {
201 if (i == 4) {
202 break a;
203 }
204 c.accept(4);
205 } finally {
206 if (i == 5) {
207 break a;
208 }
209 c.accept(5);
210 }
211 c.accept(6);
212 }
213
214 @Test
215 public void testCatchFinallyBreak() {
216 CoreOp.FuncOp f = getFuncOp("tryCatchFinallyBreak");
217
218 System.out.println(f.toText());
219
220 CoreOp.FuncOp lf = f.transform(CodeTransformer.LOWERING_TRANSFORMER);
221
222 System.out.println(lf.toText());
223
224 for (int ra = -1; ra < 6; ra++) {
225 int fra = ra;
226
227 Consumer<IntConsumer> test = testConsumer(
228 c -> Interpreter.invoke(MethodHandles.lookup(), lf, c, fra),
229 c -> tryCatchFinallyBreak(c, fra)
230 );
231
232 test.accept(i -> {});
233 for (int ea = 0; ea <= 6; ea++) {
234 int fea = ea;
235 test.accept(i -> {
236 if (i == fea) throw new IllegalStateException();
237 });
238 test.accept(i -> {
239 if (i == fea) throw new RuntimeException();
240 });
241 }
242 }
243 }
244
245
246 @Reflect
247 public static void tryForLoop(IntConsumer c) {
248 for (int i = 0; i < 8; i++) {
249 c.accept(0);
250 try {
251 if (i == 4) {
252 continue;
253 } else if (i == 5) {
254 break;
255 }
256 c.accept(1);
257 } catch (IllegalStateException e) {
258 c.accept(2);
259 }
260 c.accept(3);
261 }
262 c.accept(4);
263 }
264
265 @Test
266 public void testTryForLoop() {
267 CoreOp.FuncOp f = getFuncOp("tryForLoop");
268
269 System.out.println(f.toText());
270
271 CoreOp.FuncOp lf = f.transform(CodeTransformer.LOWERING_TRANSFORMER);
272
273 System.out.println(lf.toText());
274
275 Consumer<IntConsumer> test = testConsumer(
276 c -> Interpreter.invoke(MethodHandles.lookup(), lf, c),
277 TestTryNested::tryForLoop
278 );
279
280 test.accept(i -> { });
281 for (int ea = 0; ea <= 4; ea++) {
282 int fea = ea;
283 test.accept(i -> {
284 if (i == fea) throw new IllegalStateException();
285 });
286 test.accept(i -> {
287 if (i == fea) throw new RuntimeException();
288 });
289 }
290 }
291
292 @Reflect
293 public static void tryForLoopFinally(IntConsumer c) {
294 for (int i = 0; i < 8; i++) {
295 c.accept(0);
296 try {
297 if (i == 4) {
298 continue;
299 } else if (i == 5) {
300 break;
301 }
302 c.accept(1);
303 } finally {
304 c.accept(2);
305 }
306 c.accept(3);
307 }
308 c.accept(4);
309 }
310
311 @Test
312 public void testTryForLoopFinally() {
313 CoreOp.FuncOp f = getFuncOp("tryForLoopFinally");
314
315 System.out.println(f.toText());
316
317 CoreOp.FuncOp lf = f.transform(CodeTransformer.LOWERING_TRANSFORMER);
318
319 System.out.println(lf.toText());
320
321 Consumer<IntConsumer> test = testConsumer(
322 c -> Interpreter.invoke(MethodHandles.lookup(), lf, c),
323 TestTryNested::tryForLoopFinally
324 );
325
326 test.accept(i -> { });
327 for (int ea = 0; ea <= 4; ea++) {
328 int fea = ea;
329 test.accept(i -> {
330 if (i == fea) throw new IllegalStateException();
331 });
332 test.accept(i -> {
333 if (i == fea) throw new RuntimeException();
334 });
335 }
336 }
337
338
339 @Reflect
340 public static void tryLabeledForLoop(IntConsumer c) {
341 a: for (int i = 0; i < 8; i++) {
342 c.accept(0);
343 b: {
344 try {
345 if (i == 4) {
346 continue a;
347 } else if (i == 5) {
348 break b;
349 } else if (i == 6) {
350 break a;
351 }
352 c.accept(1);
353 } finally {
354 c.accept(2);
355 }
356 c.accept(3);
357 }
358 c.accept(4);
359 }
360 c.accept(5);
361 }
362
363 @Test
364 public void testTryLabeledForLoop() {
365 CoreOp.FuncOp f = getFuncOp("tryLabeledForLoop");
366
367 System.out.println(f.toText());
368
369 CoreOp.FuncOp lf = f.transform(CodeTransformer.LOWERING_TRANSFORMER);
370
371 System.out.println(lf.toText());
372
373 Consumer<IntConsumer> test = testConsumer(
374 c -> Interpreter.invoke(MethodHandles.lookup(), lf, c),
375 TestTryNested::tryLabeledForLoop
376 );
377
378 test.accept(i -> { });
379 }
380
381
382 @Reflect
383 public static void tryLambda(IntConsumer c, int i) {
384 try {
385 c.accept(0);
386 Runnable r = () -> {
387 if (i == 0) {
388 c.accept(1);
389 return;
390 } else {
391 c.accept(2);
392 }
393 c.accept(3);
394 };
395 r.run();
396 c.accept(4);
397 } finally {
398 c.accept(5);
399 }
400 }
401
402 @Test
403 public void testTryLambda() {
404 CoreOp.FuncOp f = getFuncOp("tryLambda");
405
406 System.out.println(f.toText());
407
408 CoreOp.FuncOp lf = f.transform(CodeTransformer.LOWERING_TRANSFORMER);
409
410 System.out.println(lf.toText());
411
412 for (int ra = 0; ra < 2; ra++) {
413 final int fra = ra;
414 Consumer<IntConsumer> test = testConsumer(
415 c -> Interpreter.invoke(MethodHandles.lookup(), lf, c, fra),
416 c -> tryLambda(c, fra)
417 );
418 test.accept(i -> { });
419 }
420 }
421
422
423 static CoreOp.FuncOp getFuncOp(String name) {
424 Optional<Method> om = Stream.of(TestTryNested.class.getDeclaredMethods())
425 .filter(m -> m.getName().equals(name))
426 .findFirst();
427
428 Method m = om.get();
429 return Op.ofMethod(m).get();
430 }
431
432 static Consumer<IntConsumer> testConsumer(Consumer<IntConsumer> actualR, Consumer<IntConsumer> expectedR) {
433 return c -> {
434 List<Integer> actual = new ArrayList<>();
435 IntConsumer actualC = actual::add;
436 Throwable actualT = null;
437 try {
438 actualR.accept(actualC.andThen(c));
439 } catch (Interpreter.InterpreterException e) {
440 throw e;
441 } catch (Throwable t) {
442 actualT = t;
443 if (t instanceof AssertionError) {
444 t.printStackTrace();
445 }
446 }
447
448 List<Integer> expected = new ArrayList<>();
449 IntConsumer expectedC = expected::add;
450 Throwable expectedT = null;
451 try {
452 expectedR.accept(expectedC.andThen(c));
453 } catch (Throwable t) {
454 expectedT = t;
455 }
456
457 Assertions.assertEquals(
458 expectedT != null ? expectedT.getClass() : null, actualT != null ? actualT.getClass() : null
459 );
460 Assertions.assertEquals(expected, actual);
461 };
462 }
463 }