1 /*
2  * Copyright (C) 2015 Square, Inc.
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 package com.squareup.okhttp.testing;
17 
18 import org.junit.runner.Description;
19 import org.junit.runner.Result;
20 import org.junit.runner.notification.RunListener;
21 
22 import java.io.PrintWriter;
23 import java.io.StringWriter;
24 
25 /**
26  * A {@link org.junit.runner.notification.RunListener} used to install an aggressive default
27  * {@link java.lang.Thread.UncaughtExceptionHandler} similar to the one found on Android.
28  * No exceptions should escape from OkHttp that might cause apps to be killed or tests to fail on
29  * Android.
30  */
31 public class InstallUncaughtExceptionHandlerListener extends RunListener {
32 
33   private Thread.UncaughtExceptionHandler oldDefaultUncaughtExceptionHandler;
34   private Description lastTestStarted;
35 
testRunStarted(Description description)36   @Override public void testRunStarted(Description description) throws Exception {
37     System.err.println("Installing aggressive uncaught exception handler");
38     oldDefaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
39     Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
40       @Override public void uncaughtException(Thread thread, Throwable throwable) {
41         StringWriter errorText = new StringWriter(256);
42         errorText.append("Uncaught exception in OkHttp thread \"");
43         errorText.append(thread.getName());
44         errorText.append("\"\n");
45         throwable.printStackTrace(new PrintWriter(errorText));
46         errorText.append("\n");
47         if (lastTestStarted != null) {
48           errorText.append("Last test to start was: ");
49           errorText.append(lastTestStarted.getDisplayName());
50           errorText.append("\n");
51         }
52         System.err.print(errorText.toString());
53         System.exit(-1);
54       }
55     });
56   }
57 
testStarted(Description description)58   @Override public void testStarted(Description description) throws Exception {
59     lastTestStarted = description;
60   }
61 
testRunFinished(Result result)62   @Override public void testRunFinished(Result result) throws Exception {
63     Thread.setDefaultUncaughtExceptionHandler(oldDefaultUncaughtExceptionHandler);
64     System.err.println("Uninstalled aggressive uncaught exception handler");
65   }
66 }
67