1 /*
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 
17 package art;
18 
19 import java.util.Arrays;
20 import java.util.Objects;
21 import java.lang.reflect.Executable;
22 import java.lang.reflect.Method;
23 
24 public class Test1928 {
25   public static boolean PRINT_FULL_EXCEPTION = false;
26   public static ExceptionHandler HANDLER = null;
27 
28   public static interface ExceptionHandler {
exceptionOccurred( Executable m, long loc, Throwable exception, Executable catch_m, long catch_l)29     public void exceptionOccurred(
30         Executable m, long loc, Throwable exception, Executable catch_m, long catch_l);
31   }
32 
PrintStack()33   private static void PrintStack() {
34     System.out.println("\tCurrent Stack:");
35     for (StackTrace.StackFrameData e : StackTrace.GetStackTrace(Thread.currentThread())) {
36       if (Objects.equals(e.method.getDeclaringClass().getPackage(), Test1928.class.getPackage())) {
37         System.out.println("\t\t" + e.method + " @ line = " +
38             Breakpoint.locationToLine(e.method, e.current_location));
39       }
40     }
41   }
42 
ExceptionEvent(Thread thr, Executable throw_method, long throw_location, Throwable exception, Executable catch_method, long catch_location)43   public static void ExceptionEvent(Thread thr,
44                                     Executable throw_method,
45                                     long throw_location,
46                                     Throwable exception,
47                                     Executable catch_method,
48                                     long catch_location) {
49     System.out.println(thr.getName() + ": " + throw_method + " @ line = " +
50         Breakpoint.locationToLine(throw_method, throw_location) + " throws " +
51         exception.getClass() + ": " + exception.getMessage());
52     String catch_message;
53     if (catch_method == null) {
54       catch_message = "<UNKNOWN>";
55     } else {
56       catch_message = catch_method.toString() + " @ line = " +
57           Breakpoint.locationToLine(catch_method, catch_location);
58     }
59     PrintStack();
60     System.out.println("\tWill be caught by: " + catch_message);
61     if (PRINT_FULL_EXCEPTION) {
62       System.out.print("exception is: ");
63       exception.printStackTrace(System.out);
64     }
65     if (HANDLER != null) {
66       HANDLER.exceptionOccurred(
67           throw_method, throw_location, exception, catch_method, catch_location);
68     }
69   }
70 
71   public static class BaseTestException extends Error {
BaseTestException(String e)72     public BaseTestException(String e) { super(e); }
BaseTestException(String e, Throwable t)73     public BaseTestException(String e, Throwable t) { super(e, t); }
74   }
75   public static class TestException extends BaseTestException {
TestException(String e)76     public TestException(String e) { super(e); }
TestException(String e, Throwable t)77     public TestException(String e, Throwable t) { super(e, t); }
78   }
79 
80   public static class TestExceptionNoRethrow extends TestException {
TestExceptionNoRethrow(String e)81     public TestExceptionNoRethrow(String e) { super(e); }
TestExceptionNoRethrow(String e, Throwable t)82     public TestExceptionNoRethrow(String e, Throwable t) { super(e, t); }
83   }
84 
85   public static class DoNothingHandler implements ExceptionHandler {
exceptionOccurred( Executable m, long loc, Throwable exception, Executable catch_m, long catch_l)86     public void exceptionOccurred(
87         Executable m, long loc, Throwable exception, Executable catch_m, long catch_l) {
88       System.out.println("\tDoing nothing!");
89       return;
90     }
91   }
92 
93   public static class ThrowCatchBase implements ExceptionHandler {
exceptionOccurred( Executable m, long loc, Throwable exception, Executable catch_m, long catch_l)94     public void exceptionOccurred(
95         Executable m, long loc, Throwable exception, Executable catch_m, long catch_l) {
96       System.out.println("\tThrowing BaseTestException and catching it!");
97       try {
98         throw new BaseTestException("ThrowBaseHandler during throw from " + m + " @ line = " +
99             Breakpoint.locationToLine(m, loc), exception);
100       } catch (BaseTestException t) {
101         System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
102         if (PRINT_FULL_EXCEPTION) {
103           t.printStackTrace(System.out);
104         }
105       }
106     }
107   }
108 
doThrow()109   public static void doThrow() {
110     throw new TestException("doThrow");
111   }
112 
113   public static class DoThrowClass implements Runnable {
run()114     public void run() { doThrow(); }
115   }
116 
throwCatchBaseTestException()117   public static void throwCatchBaseTestException() {
118     try {
119       throw new TestException("throwCatchBaseTestException");
120     } catch (BaseTestException t) {
121       System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
122       if (PRINT_FULL_EXCEPTION) {
123         t.printStackTrace(System.out);
124       }
125     }
126   }
127 
128   public static class DoThrowCatchBaseTestException implements Runnable {
run()129     public void run() { throwCatchBaseTestException(); }
130   }
131 
throwCatchTestException()132   public static void throwCatchTestException() {
133     try {
134       throw new TestException("throwCatchTestException");
135     } catch (TestException t) {
136       System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
137       if (PRINT_FULL_EXCEPTION) {
138         t.printStackTrace(System.out);
139       }
140     }
141   }
142 
143   public static class DoThrowCatchTestException implements Runnable {
run()144     public void run() { throwCatchTestException(); }
145   }
146 
throwCatchTestExceptionNoRethrow()147   public static void throwCatchTestExceptionNoRethrow() {
148     try {
149       throw new TestException("throwCatchTestExceptionNoRethrow");
150     } catch (TestExceptionNoRethrow t) {
151       System.out.println("Caught " + t.getClass().getName() + ": \"" + t.getMessage() + "\"");
152       if (PRINT_FULL_EXCEPTION) {
153         t.printStackTrace(System.out);
154       }
155     }
156   }
157 
158   public static class DoThrowCatchTestExceptionNoRethrow implements Runnable {
run()159     public void run() { throwCatchTestExceptionNoRethrow(); }
160   }
161 
run()162   public static void run() throws Exception {
163     // Set up
164     Exceptions.setupExceptionTracing(
165         Test1928.class,
166         TestException.class,
167         Test1928.class.getDeclaredMethod(
168             "ExceptionEvent",
169             Thread.class,
170             Executable.class,
171             Long.TYPE,
172             Throwable.class,
173             Executable.class,
174             Long.TYPE),
175         null);
176     Exceptions.enableExceptionEvent(Thread.currentThread());
177 
178     ExceptionHandler[] handlers = new ExceptionHandler[] {
179       new DoNothingHandler(),
180       new ThrowCatchBase(),
181     };
182 
183     Runnable[] tests = new Runnable[] {
184       new DoThrowClass(),
185       new DoThrowCatchBaseTestException(),
186       new DoThrowCatchTestException(),
187       new DoThrowCatchTestExceptionNoRethrow(),
188     };
189 
190     for (ExceptionHandler handler : handlers) {
191       for (Runnable test : tests) {
192         try {
193           HANDLER = handler;
194           System.out.printf("Test \"%s\": Running with handler \"%s\"\n",
195               test.getClass().getName(), handler.getClass().getName());
196           test.run();
197           System.out.printf("Test \"%s\": No error caught with handler \"%s\"\n",
198               test.getClass().getName(), handler.getClass().getName());
199         } catch (Throwable e) {
200           System.out.printf("Test \"%s\": Caught error %s:\"%s\" with handler \"%s\"\n",
201               test.getClass().getName(),
202               e.getClass().getName(),
203               e.getMessage(),
204               handler.getClass().getName());
205           if (PRINT_FULL_EXCEPTION) {
206             e.printStackTrace(System.out);
207           }
208         }
209         System.out.printf("Test \"%s\": Finished running with handler \"%s\"\n",
210             test.getClass().getName(), handler.getClass().getName());
211         HANDLER = null;
212       }
213     }
214     Exceptions.disableExceptionEvent(Thread.currentThread());
215   }
216 }
217