Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,8 @@ public void start(Callback callback) {
@Override
public synchronized void uncaughtException(final Thread thread, final Throwable throwable) {
try {
if (throwable instanceof Exception) {
report(throwable);
}
} catch (RuntimeException ex) {
report(throwable);
} catch (RuntimeException | Error ex) {
Log.w(LOG_TAG, "Failed to report the unhandled exception.", ex);
} finally {
Thread.UncaughtExceptionHandler rootHandler = _rootHandler;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import com.facebook.react.bridge.Callback;
import java.util.ArrayList;
Expand Down Expand Up @@ -139,17 +140,48 @@ public void failingCallbackStillForwards() {
}

@Test
public void errorIsForwardedWithoutConsumingTheCallback() {
public void stackOverflowErrorIsReportedAndForwarded() {
assertErrorReportedAndForwarded(new StackOverflowError("stack size 8MB"));
}

@Test
public void outOfMemoryErrorIsReportedAndForwarded() {
assertErrorReportedAndForwarded(new OutOfMemoryError("Failed to allocate a 24 byte allocation"));
}

@Test
public void noClassDefFoundErrorIsReportedAndForwarded() {
assertErrorReportedAndForwarded(new NoClassDefFoundError("com/example/Missing"));
}

@Test
public void secondCrashIsForwardedWithoutReporting() {
RecordingCallback callback = new RecordingCallback(handler);
handler.start(callback);

crash(new StackOverflowError());
crash(new RuntimeException("after error"));
crash(new StackOverflowError("first"));
crash(new RuntimeException("second"));

assertEquals(1, callback.calls.size());
assertEquals(2, rootHandler.received.size());
}

@Test
public void callbackThrowingErrorStillForwards() {
StackOverflowError error = new StackOverflowError("boom");
List<Object[]> calls = new ArrayList<>();
handler.start(args -> {
calls.add(args);
throw new OutOfMemoryError("callback failed");
});

crash(error);

assertEquals(1, calls.size());
assertEquals(1, rootHandler.received.size());
assertSame(error, rootHandler.received.get(0));
}

@Test
public void stopBeforeStartKeepsCurrentHandler() {
handler.stop();
Expand Down Expand Up @@ -190,6 +222,20 @@ public void reloadedInstanceStartingFirstForwardsThroughInvalidatedInstance() {
assertEquals(1, rootHandler.received.size());
}

private void assertErrorReportedAndForwarded(Throwable error) {
RecordingCallback callback = new RecordingCallback(handler);
handler.start(callback);

crash(error);

assertEquals(1, callback.calls.size());
assertEquals(error.getClass().getName(), callback.calls.get(0)[0]);
assertEquals(error.getMessage(), callback.calls.get(0)[1]);
assertTrue(((String) callback.calls.get(0)[2]).contains(getClass().getName()));
assertEquals(1, rootHandler.received.size());
assertSame(error, rootHandler.received.get(0));
}

private void crash(Throwable throwable) {
Thread.getDefaultUncaughtExceptionHandler().uncaughtException(Thread.currentThread(), throwable);
}
Expand Down
Loading