Fix exception handling in snippets. (#32)
* Don't try to call methods on snippet classes that couldn't be constructed
* Don't obscure the cause of exceptions
* Propagate the entire stack trace to the python side
* Decorate the stacktrace
diff --git a/examples/ex1_standalone_app/src/main/java/com/google/android/mobly/snippet/example1/ExampleSnippet2.java b/examples/ex1_standalone_app/src/main/java/com/google/android/mobly/snippet/example1/ExampleSnippet2.java
index 43c3db8..3077869 100644
--- a/examples/ex1_standalone_app/src/main/java/com/google/android/mobly/snippet/example1/ExampleSnippet2.java
+++ b/examples/ex1_standalone_app/src/main/java/com/google/android/mobly/snippet/example1/ExampleSnippet2.java
@@ -18,6 +18,7 @@
import com.google.android.mobly.snippet.Snippet;
import com.google.android.mobly.snippet.rpc.Rpc;
+import java.io.IOException;
public class ExampleSnippet2 implements Snippet {
@Rpc(description = "Returns the given string with the prefix \"bar\"")
@@ -25,6 +26,11 @@
return "bar " + input;
}
+ @Rpc(description = "Throws an exception")
+ public String throwSomething() throws IOException {
+ throw new IOException("Example exception from throwSomething()");
+ }
+
@Override
public void shutdown() {}
}
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/SnippetManager.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/SnippetManager.java
index edb872b..e27c473 100644
--- a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/SnippetManager.java
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/manager/SnippetManager.java
@@ -19,6 +19,7 @@
import android.os.Build;
import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
@@ -63,7 +64,7 @@
}
public Object invoke(Class<? extends Snippet> clazz, Method method, Object[] args)
- throws Exception {
+ throws Throwable {
if (method.isAnnotationPresent(RpcMinSdk.class)) {
int requiredSdkLevel = method.getAnnotation(RpcMinSdk.class).value();
if (Build.VERSION.SDK_INT < requiredSdkLevel) {
@@ -72,8 +73,12 @@
method.getName(), requiredSdkLevel, Build.VERSION.SDK_INT));
}
}
- Snippet object = get(clazz);
- return method.invoke(object, args);
+ try {
+ Snippet object = get(clazz);
+ return method.invoke(object, args);
+ } catch (InvocationTargetException e) {
+ throw e.getCause();
+ }
}
public void shutdown() {
@@ -88,21 +93,16 @@
}
}
- private Snippet get(Class<? extends Snippet> clazz) {
+ private Snippet get(Class<? extends Snippet> clazz) throws Exception {
Snippet object = mReceivers.get(clazz);
if (object != null) {
return object;
}
Constructor<? extends Snippet> constructor;
- try {
- constructor = clazz.getConstructor();
- object = constructor.newInstance();
- mReceivers.put(clazz, object);
- } catch (Exception e) {
- Log.e(e);
- }
-
+ constructor = clazz.getConstructor();
+ object = constructor.newInstance();
+ mReceivers.put(clazz, object);
return object;
}
}
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcResult.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcResult.java
index 0c1d0f2..ce02344 100644
--- a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcResult.java
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/JsonRpcResult.java
@@ -16,6 +16,8 @@
package com.google.android.mobly.snippet.rpc;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import org.json.JSONException;
import org.json.JSONObject;
@@ -48,10 +50,16 @@
}
public static JSONObject error(int id, Throwable t) throws JSONException {
+ StringWriter stackTraceWriter = new StringWriter();
+ stackTraceWriter.write("\n-------------- Java Stacktrace ---------------\n");
+ t.printStackTrace(new PrintWriter(stackTraceWriter));
+ stackTraceWriter.write("----------------------------------------------");
+ String stackTrace = stackTraceWriter.toString();
+
JSONObject json = new JSONObject();
json.put("id", id);
json.put("result", JSONObject.NULL);
- json.put("error", t.toString());
+ json.put("error", stackTrace);
return json;
}
}
diff --git a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java
index 8d18582..862278e 100644
--- a/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java
+++ b/third_party/sl4a/src/main/java/com/google/android/mobly/snippet/rpc/MethodDescriptor.java
@@ -88,17 +88,7 @@
}
}
- return invoke(manager, args);
- }
-
- private Object invoke(SnippetManager manager, Object[] args) throws Throwable {
- Object result;
- try {
- result = manager.invoke(mClass, mMethod, args);
- } catch (Throwable t) {
- throw t.getCause();
- }
- return result;
+ return manager.invoke(mClass, mMethod, args);
}
/**