blob: c0995a8468005a2f99e01ee91a98baba178c9c3c [file] [log] [blame]
Alex Light9fb1ab12017-09-05 09:32:49 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package art;
18
19import java.util.Arrays;
20import java.util.Collection;
21import java.util.Objects;
22import java.lang.reflect.Executable;
23import java.lang.reflect.Method;
24
25public class Test1929 {
26 public static boolean PRINT_FULL_EXCEPTION = false;
27 public static ExceptionHandler HANDLER = null;
28 public static Collection<Executable> TEST_METHODS;
29
30 public static void doNothing() {};
31 static {
32 try {
33 TEST_METHODS = Arrays.asList(
34 Test1929.class.getDeclaredMethod("doThrow"),
35 Test1929.class.getDeclaredMethod("throwCatchBaseTestException"),
36 Test1929.class.getDeclaredMethod("throwCatchBaseTestExceptionTwice"),
37 Test1929.class.getDeclaredMethod("throwCatchTestException"),
38 Test1929.class.getDeclaredMethod("throwCatchTestExceptionTwice"),
39 Test1929.class.getDeclaredMethod("throwCatchTestExceptionNoRethrow"));
40 } catch (Exception e) {
41 throw new Error("Unable to list test methods!", e);
42 }
43 }
44
45 public static interface ExceptionHandler {
46 public void exceptionOccurred(
47 Executable m, long loc, Throwable exception);
48 }
49
50 private static void PrintStack() {
51 System.out.println("\tCurrent Stack:");
52 for (StackTrace.StackFrameData e : StackTrace.GetStackTrace(Thread.currentThread())) {
53 if (Objects.equals(e.method.getDeclaringClass().getPackage(), Test1929.class.getPackage())) {
54 System.out.println("\t\t" + e.method + " @ line = " +
55 Breakpoint.locationToLine(e.method, e.current_location));
56 }
57 }
58 }
59
60 public static void ExceptionCatchEvent(
61 Thread thr, Executable method, long location, Throwable exception) {
62 System.out.println(thr.getName() + ": " + method + " @ line = " +
63 Breakpoint.locationToLine(method, location) + " caught " +
64 exception.getClass() + ": " + exception.getMessage());
65 PrintStack();
66 if (PRINT_FULL_EXCEPTION) {
67 System.out.print("exception is: ");
68 exception.printStackTrace(System.out);
69 }
70 if (HANDLER != null && TEST_METHODS.contains(method)) {
71 HANDLER.exceptionOccurred(method, location, exception);
72 }
73 }
74
75 public static class BaseTestException extends Error {
76 public BaseTestException(String e) { super(e); }
77 public BaseTestException(String e, Throwable t) { super(e, t); }
78 }
79 public static class TestException extends BaseTestException {
80 public TestException(String e) { super(e); }
81 public TestException(String e, Throwable t) { super(e, t); }
82 }
83
84 public static class TestExceptionNoRethrow extends TestException {
85 public TestExceptionNoRethrow(String e) { super(e); }
86 public TestExceptionNoRethrow(String e, Throwable t) { super(e, t); }
87 }
88
89 public static class DoNothingHandler implements ExceptionHandler {
90 public void exceptionOccurred(Executable m, long loc, Throwable exception) {
91 System.out.println("\tDoing nothing!");
92 return;
93 }
94 }
95
96 public static class ThrowCatchBase implements ExceptionHandler {
97 public void exceptionOccurred(Executable m, long loc, Throwable exception) {
98 System.out.println("\tThrowing BaseTestException and catching it!");
99 try {
100 throw new BaseTestException("ThrowBaseHandler during throw from " + m + " @ line = " +
101 Breakpoint.locationToLine(m, loc), exception);
102 } catch (BaseTestException t) {
103 System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
104 if (PRINT_FULL_EXCEPTION) {
105 t.printStackTrace(System.out);
106 }
107 }
108 }
109 }
110 public static class ThrowBaseTestExceptionHandler implements ExceptionHandler {
111 public void exceptionOccurred(Executable m, long loc, Throwable exception) {
112 System.out.println("\tThrowing BaseTestException!");
113 throw new BaseTestException("ThrowBaseHandler during throw from " + m + " @ line = " +
114 Breakpoint.locationToLine(m, loc), exception);
115 }
116 }
117
118 public static class ThrowTestExceptionNoRethrowHandler implements ExceptionHandler {
119 public void exceptionOccurred(Executable m, long loc, Throwable exception) {
120 if (exception instanceof TestExceptionNoRethrow) {
121 System.out.println("\tInstance of TestExceptionNoRethrow was thrown. Not throwing again.");
122 } else {
123 System.out.println("\tThrowing TestExceptionNoRethrow!");
124 throw new TestExceptionNoRethrow("ThrowTestExceptionNoRethrowHandler during throw from " +
125 m + " @ line = " + Breakpoint.locationToLine(m, loc), exception);
126 }
127 }
128 }
129 public static void doThrow() {
130 throw new TestException("doThrow");
131 }
132
133 public static class DoThrowClass implements Runnable {
134 public void run() { doThrow(); }
135 }
136
137 public static void throwCatchBaseTestException() {
138 try {
139 throw new TestException("throwCatchBaseTestException");
140 } catch (BaseTestException t) {
141 System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
142 if (PRINT_FULL_EXCEPTION) {
143 t.printStackTrace(System.out);
144 }
145 }
146 }
147
148 public static class DoThrowCatchBaseTestException implements Runnable {
149 public void run() { throwCatchBaseTestException(); }
150 }
151
Orion Hodson4a1cac42018-05-23 16:23:27 +0100152 // dx and d8 do an optimization around catch blocks that (while legal) breaks assumptions
Alex Light9fb1ab12017-09-05 09:32:49 -0700153 // this test relies on so we have the actual implementation be corrected smali. This does work
154 // for RI however.
Alex Light9fb1ab12017-09-05 09:32:49 -0700155
Alan Leungd5cbc562018-03-15 14:02:46 -0700156 // For reference:
157
158 // public static final class Impl {
159 // private Impl() {}
160 // public static void throwCatchBaseTestExceptionTwiceImpl() {
161 // try {
162 // try {
163 // throw new TestException("throwCatchBaseTestExceptionTwice");
164 // } catch (BaseTestException t) {
165 // System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
166 // if (PRINT_FULL_EXCEPTION) {
167 // t.printStackTrace(System.out);
168 // }
169 // }
170 // } catch (BaseTestException t) {
171 // System.out.println("2nd Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
172 // if (PRINT_FULL_EXCEPTION) {
173 // t.printStackTrace(System.out);
174 // }
175 // }
176 // }
177
178 // public static void throwCatchTestExceptionTwiceImpl() {
179 // try {
180 // try {
181 // throw new TestException("throwCatchTestExceptionTwice");
182 // } catch (TestException t) {
183 // System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
184 // if (PRINT_FULL_EXCEPTION) {
185 // t.printStackTrace(System.out);
186 // }
187 // }
188 // } catch (TestException t) {
189 // System.out.println("2nd Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
190 // if (PRINT_FULL_EXCEPTION) {
191 // t.printStackTrace(System.out);
192 // }
193 // }
194 // }
195 // }
Alex Light9fb1ab12017-09-05 09:32:49 -0700196
197 public static void throwCatchBaseTestExceptionTwice() {
198 // The implementation of this has to change depending upon the runtime slightly due to compiler
199 // optimizations present in DX/D8/Jack.
Alan Leungd5cbc562018-03-15 14:02:46 -0700200 try {
201 Class<?> Impl = Class.forName("art.Test1929$Impl");
202 Method m = Impl.getMethod("throwCatchBaseTestExceptionTwiceImpl");
203 m.invoke(null);
204 } catch (Exception e) {
205 e.printStackTrace(System.out);
206 }
Alex Light9fb1ab12017-09-05 09:32:49 -0700207 }
208
209 public static class DoThrowCatchBaseTestExceptionTwice implements Runnable {
210 public void run() { throwCatchBaseTestExceptionTwice(); }
211 }
212
213 public static void throwCatchTestException() {
214 try {
215 throw new TestException("throwCatchTestException");
216 } catch (TestException t) {
217 System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
218 if (PRINT_FULL_EXCEPTION) {
219 t.printStackTrace(System.out);
220 }
221 }
222 }
223
224 public static class DoThrowCatchTestException implements Runnable {
225 public void run() { throwCatchTestException(); }
226 }
227
228 public static void throwCatchTestExceptionTwice() {
229 // The implementation of this has to change depending upon the runtime slightly due to compiler
230 // optimizations present in DX/D8/Jack.
Alan Leungd5cbc562018-03-15 14:02:46 -0700231 try {
232 Class<?> Impl = Class.forName("art.Test1929$Impl");
233 Method m = Impl.getMethod("throwCatchTestExceptionTwiceImpl");
234 m.invoke(null);
235 } catch (Exception e) {
236 e.printStackTrace(System.out);
237 }
Alex Light9fb1ab12017-09-05 09:32:49 -0700238 }
239
240 public static class DoThrowCatchTestExceptionTwice implements Runnable {
241 public void run() { throwCatchTestExceptionTwice(); }
242 }
243
244 public static void throwCatchTestExceptionNoRethrow() {
245 try {
246 throw new TestException("throwCatchTestExceptionNoRethrow");
247 } catch (TestExceptionNoRethrow t) {
248 System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
249 if (PRINT_FULL_EXCEPTION) {
250 t.printStackTrace(System.out);
251 }
252 }
253 }
254
255 public static class DoThrowCatchTestExceptionNoRethrow implements Runnable {
256 public void run() { throwCatchTestExceptionNoRethrow(); }
257 }
258
259 public static void run() throws Exception {
260 // Set up breakpoints
261 Exceptions.setupExceptionTracing(
262 Test1929.class,
263 TestException.class,
264 null,
265 Test1929.class.getDeclaredMethod(
266 "ExceptionCatchEvent",
267 Thread.class,
268 Executable.class,
269 Long.TYPE,
270 Throwable.class));
271 Exceptions.enableExceptionCatchEvent(Thread.currentThread());
272
273 ExceptionHandler[] handlers = new ExceptionHandler[] {
274 new DoNothingHandler(),
275 new ThrowCatchBase(),
276 new ThrowBaseTestExceptionHandler(),
277 new ThrowTestExceptionNoRethrowHandler(),
278 };
279
280 Runnable[] tests = new Runnable[] {
281 new DoThrowClass(),
282 new DoThrowCatchBaseTestException(),
283 new DoThrowCatchBaseTestExceptionTwice(),
284 new DoThrowCatchTestException(),
285 new DoThrowCatchTestExceptionTwice(),
286 new DoThrowCatchTestExceptionNoRethrow(),
287 };
288
289 for (ExceptionHandler handler : handlers) {
290 for (Runnable test : tests) {
291 try {
292 HANDLER = handler;
293 System.out.printf("Test \"%s\": Running breakpoint with handler \"%s\"\n",
294 test.getClass().getName(), handler.getClass().getName());
295 test.run();
296 System.out.printf("Test \"%s\": No error caught with handler \"%s\"\n",
297 test.getClass().getName(), handler.getClass().getName());
298 } catch (Throwable e) {
299 System.out.printf("Test \"%s\": Caught error %s:\"%s\" with handler \"%s\"\n",
300 test.getClass().getName(),
301 e.getClass().getName(),
302 e.getMessage(),
303 handler.getClass().getName());
304 if (PRINT_FULL_EXCEPTION) {
305 e.printStackTrace(System.out);
306 }
307 }
308 System.out.printf("Test \"%s\": Finished running with handler \"%s\"\n",
309 test.getClass().getName(), handler.getClass().getName());
310 HANDLER = null;
311 }
312 }
313 Exceptions.disableExceptionCatchEvent(Thread.currentThread());
314 }
315}