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