Skip to content

Commit 825dfbe

Browse files
author
Eric Denman
committed
ANDROID-4573 don't keep recursing down the nested exception trail
1 parent 6c14879 commit 825dfbe

2 files changed

Lines changed: 82 additions & 3 deletions

File tree

src/main/java/com/squareup/squash/SquashBacktrace.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ public static Map<String, Object> getIvars(Throwable error) {
7474
*/
7575
public static void populateNestedExceptions(List<NestedException> nestedExceptions,
7676
Throwable error) {
77-
if (error == null || error.getCause() == null) {
77+
// Only keep processing if the "cause" exception is set and != the "parent" exception.
78+
if (error == null || error.getCause() == null || error.getCause() == error) {
7879
return;
7980
}
8081
final Throwable cause = error.getCause();

src/test/java/com/squareup/squash/SquashEntryTest.java

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@
22
package com.squareup.squash;
33

44
import com.google.gson.Gson;
5-
import org.junit.Test;
6-
75
import java.io.IOException;
86
import java.util.List;
7+
import org.junit.Test;
98

109
import static org.fest.assertions.Assertions.assertThat;
1110
import static org.mockito.Mockito.mock;
@@ -151,6 +150,85 @@ private void assertBacktracesMatch(StackTraceElement[] myLittleStackTrace,
151150
assertBacktracesMatch(nestedStackTrace, (List<List<Object>>) backtrace.get(2));
152151
}
153152

153+
@Test public void testInfinitelyNestedExceptions() throws Exception {
154+
final String logMessage = "I LOVE TACOS";
155+
final Throwable nestedException = mock(Throwable.class);
156+
final Throwable doublyNestedException = mock(Throwable.class);
157+
final Throwable exception = mock(Throwable.class);
158+
StackTraceElement n0 = new StackTraceElement("com.taco.Burrito", "digest",
159+
"core-android/src/com/burrito/Burrito.java", 45);
160+
StackTraceElement n1 = new StackTraceElement("com.taco.Burrito", "eat",
161+
"core-android/src/com/burrito/Burrito.java", 10);
162+
StackTraceElement n2 =
163+
new StackTraceElement("com.taco.Dude", "purchase", "core-android/src/com/taco/Dude.java",
164+
65);
165+
StackTraceElement[] nestedStackTrace = new StackTraceElement[] {n0, n1, n2};
166+
StackTraceElement z0 =
167+
new StackTraceElement("com.taco.Dude", "wheresmycar", "core-android/src/com/taco/Dude.java",
168+
455);
169+
StackTraceElement z1 =
170+
new StackTraceElement("com.bro.Bro", "hollerback", "core-android/src/com/bro/Bro.java",
171+
105);
172+
StackTraceElement z2 =
173+
new StackTraceElement("com.taco.Dude", "holler", "core-android/src/com/taco/Dude.java",
174+
655);
175+
StackTraceElement[] doublyNestedStackTrace = new StackTraceElement[] {z0, z1, z2};
176+
StackTraceElement s0 =
177+
new StackTraceElement("com.taco.Taco", "digest", "core-android/src/com/taco/Taco.java", 50);
178+
StackTraceElement s1 =
179+
new StackTraceElement("com.taco.Taco", "eat", "core-android/src/com/taco/Taco.java", 80);
180+
StackTraceElement s2 =
181+
new StackTraceElement("com.taco.Dude", "purchase", "core-android/src/com/taco/Dude.java",
182+
112);
183+
StackTraceElement[] myLittleStackTrace = new StackTraceElement[] {s0, s1, s2};
184+
final String message = "ExceptionMessage";
185+
when(exception.getMessage()).thenReturn(message);
186+
when(exception.getStackTrace()).thenReturn(myLittleStackTrace);
187+
when(exception.getCause()).thenReturn(nestedException);
188+
189+
final String nestedExceptionMessage = "NestedExceptionMessage";
190+
when(nestedException.getMessage()).thenReturn(nestedExceptionMessage);
191+
when(nestedException.getStackTrace()).thenReturn(nestedStackTrace);
192+
when(nestedException.getCause()).thenReturn(doublyNestedException);
193+
194+
final String doublyNestedExceptionMessage = "DoublyNestedExceptionMessage";
195+
when(doublyNestedException.getMessage()).thenReturn(doublyNestedExceptionMessage);
196+
when(doublyNestedException.getStackTrace()).thenReturn(doublyNestedStackTrace);
197+
when(doublyNestedException.getCause()).thenReturn(doublyNestedException);
198+
199+
final SquashEntry logEntry = factory.create(logMessage, exception);
200+
SquashEntry deserialized = serializeAndDeserialize(logEntry);
201+
assertThat(deserialized.backtraces).isNotEmpty();
202+
List<Object> backtrace = deserialized.backtraces.get(0);
203+
assertThat(backtrace.get(0)).isEqualTo(Thread.currentThread().getName());
204+
assertThat(backtrace.get(1)).isEqualTo(true);
205+
List<List<Object>> stackElements = (List<List<Object>>) backtrace.get(2);
206+
assertBacktracesMatch(myLittleStackTrace, stackElements);
207+
assertThat(deserialized.ivars).isEmpty();
208+
assertThat(deserialized.log_message).isEqualTo(logMessage);
209+
assertThat(deserialized.message).isEqualTo(message);
210+
final List<SquashBacktrace.NestedException> nestedExceptions = deserialized.parent_exceptions;
211+
assertThat(nestedExceptions).hasSize(2);
212+
213+
final SquashBacktrace.NestedException nested1 = nestedExceptions.get(0);
214+
assertThat(nested1.class_name).isEqualTo(nestedException.getClass().getName());
215+
assertThat(nested1.ivars).isEmpty();
216+
assertThat(nested1.message).isEqualTo(nestedExceptionMessage);
217+
backtrace = nested1.backtraces.get(0);
218+
assertThat(backtrace.get(0)).isEqualTo(Thread.currentThread().getName());
219+
assertThat(backtrace.get(1)).isEqualTo(true);
220+
assertBacktracesMatch(nestedStackTrace, (List<List<Object>>) backtrace.get(2));
221+
222+
final SquashBacktrace.NestedException nested2 = nestedExceptions.get(1);
223+
assertThat(nested2.class_name).isEqualTo(doublyNestedException.getClass().getName());
224+
assertThat(nested2.ivars).isEmpty();
225+
assertThat(nested2.message).isEqualTo(doublyNestedExceptionMessage);
226+
backtrace = nested1.backtraces.get(0);
227+
assertThat(backtrace.get(0)).isEqualTo(Thread.currentThread().getName());
228+
assertThat(backtrace.get(1)).isEqualTo(true);
229+
assertBacktracesMatch(nestedStackTrace, (List<List<Object>>) backtrace.get(2));
230+
}
231+
154232
private class EntryFactory {
155233
public SquashEntry create(String logMessage, Throwable exception) {
156234
return new SquashEntry("testclient", "testAPIKey", logMessage, exception, "testAppVersion",

0 commit comments

Comments
 (0)