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