use of com.microsoft.appcenter.crashes.model.ErrorReport in project mobile-center-sdk-android by Microsoft.
the class Crashes method buildErrorReport.
@VisibleForTesting
ErrorReport buildErrorReport(ManagedErrorLog log) {
UUID id = log.getId();
if (mErrorReportCache.containsKey(id)) {
ErrorReport report = mErrorReportCache.get(id).report;
report.setDevice(log.getDevice());
return report;
} else {
String stackTrace = null;
/* If exception in the log doesn't have stack trace try get it from the .throwable file. */
File file = ErrorLogHelper.getStoredThrowableFile(id);
if (file != null) {
if (file.length() > 0) {
stackTrace = FileManager.read(file);
}
}
if (stackTrace == null) {
if (MINIDUMP_FILE.equals(log.getException().getType())) {
stackTrace = getStackTraceString(new NativeException());
} else {
stackTrace = buildStackTrace(log.getException());
}
}
ErrorReport report = ErrorLogHelper.getErrorReportFromErrorLog(log, stackTrace);
mErrorReportCache.put(id, new ErrorLogReport(log, report));
return report;
}
}
use of com.microsoft.appcenter.crashes.model.ErrorReport in project mobile-center-sdk-android by Microsoft.
the class WrapperSdkExceptionManager method buildHandledErrorReport.
/**
* Get a generic error report representation for an handled exception.
* Since this is used by wrapper SDKs, stack trace and thread name are not known at Java level.
*
* @param context context.
* @param errorReportId The error report identifier.
* @return an error report.
*/
public static ErrorReport buildHandledErrorReport(Context context, String errorReportId) {
ErrorReport report = new ErrorReport();
report.setId(errorReportId);
report.setAppErrorTime(new Date());
report.setAppStartTime(new Date(Crashes.getInstance().getInitializeTimestamp()));
try {
report.setDevice(Crashes.getInstance().getDeviceInfo(context));
} catch (DeviceInfoHelper.DeviceInfoException e) {
/* The exception is already logged, just adding this log for context and avoid empty catch. */
AppCenterLog.warn(LOG_TAG, "Handled error report cannot get device info, errorReportId=" + errorReportId);
}
return report;
}
use of com.microsoft.appcenter.crashes.model.ErrorReport in project mobile-center-sdk-android by Microsoft.
the class CrashesAndroidTest method testNoDuplicateCallbacksOrSending.
@Test
public void testNoDuplicateCallbacksOrSending() throws Exception {
/* Crash on 1st process. */
Crashes.unsetInstance();
assertFalse(Crashes.hasCrashedInLastSession().get());
android.util.Log.i(TAG, "Process 1");
Thread.UncaughtExceptionHandler uncaughtExceptionHandler = mock(Thread.UncaughtExceptionHandler.class);
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
CrashesListener crashesListener = mock(CrashesListener.class);
/* While testing should process, call methods that require the handler to test we avoid a dead lock and run directly. */
when(crashesListener.shouldProcess(any(ErrorReport.class))).thenAnswer(new Answer<Boolean>() {
@Override
public Boolean answer(InvocationOnMock invocationOnMock) {
assertNotNull(AppCenter.getInstallId().get());
return AppCenter.isEnabled().get() && Crashes.isEnabled().get();
}
});
when(crashesListener.shouldAwaitUserConfirmation()).thenReturn(true);
startFresh(crashesListener);
final RuntimeException exception = new RuntimeException();
final Thread thread = new Thread() {
@Override
public void run() {
throw exception;
}
};
thread.start();
thread.join();
verify(uncaughtExceptionHandler).uncaughtException(thread, exception);
File[] files = ErrorLogHelper.getErrorStorageDirectory().listFiles(mMinidumpFilter);
assertNotNull(files);
assertEquals(1, files.length);
verifyZeroInteractions(crashesListener);
/* Second process: enqueue log but network is down... */
android.util.Log.i(TAG, "Process 2");
startFresh(crashesListener);
/* Check last session error report. */
Crashes.getLastSessionCrashReport().thenAccept(new AppCenterConsumer<ErrorReport>() {
@Override
public void accept(ErrorReport errorReport) {
assertNotNull(errorReport);
assertNotNull(errorReport.getStackTrace());
}
});
assertTrue(Crashes.hasCrashedInLastSession().get());
/* Wait U.I. thread callback (shouldAwaitUserConfirmation). */
final Semaphore semaphore = new Semaphore(0);
HandlerUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
semaphore.release();
}
});
semaphore.acquire();
/* Waiting user confirmation so no log sent yet. */
verify(mChannel, never()).enqueue(isA(ManagedErrorLog.class), anyString(), anyInt());
files = ErrorLogHelper.getErrorStorageDirectory().listFiles(mMinidumpFilter);
assertNotNull(files);
assertEquals(1, files.length);
verify(crashesListener).shouldProcess(any(ErrorReport.class));
verify(crashesListener).shouldAwaitUserConfirmation();
verifyNoMoreInteractions(crashesListener);
/* Confirm to resume processing. */
Crashes.notifyUserConfirmation(Crashes.ALWAYS_SEND);
assertTrue(Crashes.isEnabled().get());
ArgumentCaptor<ManagedErrorLog> log = ArgumentCaptor.forClass(ManagedErrorLog.class);
verify(mChannel).enqueue(log.capture(), anyString(), eq(CRITICAL));
assertNotNull(log.getValue());
assertEquals(mUserId, log.getValue().getUserId());
files = ErrorLogHelper.getErrorStorageDirectory().listFiles(mMinidumpFilter);
assertNotNull(files);
assertEquals(0, files.length);
verify(crashesListener).getErrorAttachments(any(ErrorReport.class));
verifyNoMoreInteractions(crashesListener);
/* Third process: sending succeeds. */
android.util.Log.i(TAG, "Process 3");
mChannel = mock(Channel.class);
ArgumentCaptor<Channel.GroupListener> groupListener = ArgumentCaptor.forClass(Channel.GroupListener.class);
startFresh(crashesListener);
verify(mChannel).addGroup(anyString(), anyInt(), anyInt(), anyInt(), isNull(Ingestion.class), groupListener.capture());
groupListener.getValue().onBeforeSending(log.getValue());
groupListener.getValue().onSuccess(log.getValue());
/* Wait callback to be processed in background thread (file manipulations) then called back in UI. */
/*
* Wait background thread to process the 2 previous commands,
* to do we check if crashed in last session, since we restarted process again after crash,
* it's false even if we couldn't send the log yet.
*/
assertFalse(Crashes.hasCrashedInLastSession().get());
assertNull(Crashes.getLastSessionCrashReport().get());
/* Wait U.I. thread callbacks. */
HandlerUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
semaphore.release();
}
});
semaphore.acquire();
files = ErrorLogHelper.getErrorStorageDirectory().listFiles(mMinidumpFilter);
assertNotNull(files);
assertEquals(0, files.length);
verify(mChannel, never()).enqueue(isA(ManagedErrorLog.class), anyString(), anyInt());
verify(crashesListener).onBeforeSending(any(ErrorReport.class));
verify(crashesListener).onSendingSucceeded(any(ErrorReport.class));
verifyNoMoreInteractions(crashesListener);
}
use of com.microsoft.appcenter.crashes.model.ErrorReport in project mobile-center-sdk-android by Microsoft.
the class CrashesTest method crashTest.
/**
* Crash and sending report test.
* <p>
* We can't truly restart application in tests, so some kind of crashes can't be tested by this method.
* Out of memory or stack overflow - crash the test process;
* UI states errors - problems with restart activity;
* <p>
* Also to avoid flakiness, please setup your test environment
* (https://google.github.io/android-testing-support-library/docs/espresso/setup/index.html#setup-your-test-environment).
* On your device, under Settings->Developer options disable the following 3 settings:
* - Window animation scale
* - Transition animation scale
* - Animator duration scale
*
* @param titleId Title string resource to find list item.
* @throws InterruptedException If the current thread is interrupted.
*/
private void crashTest(@StringRes int titleId) throws InterruptedException {
/* Crash. */
onView(allOf(withChild(withText(R.string.title_crashes)), withChild(withText(R.string.description_crashes)))).perform(click());
CrashFailureHandler failureHandler = new CrashFailureHandler();
onCrash(titleId).withFailureHandler(failureHandler).perform(click());
/* Check error report. */
assertTrue(Crashes.hasCrashedInLastSession().get());
ErrorReport errorReport = Crashes.getLastSessionCrashReport().get();
assertNotNull(errorReport);
assertNotNull(errorReport.getId());
assertEquals(mContext.getMainLooper().getThread().getName(), errorReport.getThreadName());
assertThat("AppStartTime", new Date().getTime() - errorReport.getAppStartTime().getTime(), lessThan(60000L));
assertThat("AppErrorTime", new Date().getTime() - errorReport.getAppErrorTime().getTime(), lessThan(10000L));
assertNotNull(errorReport.getDevice());
assertTrue(errorReport.getStackTrace().contains(failureHandler.uncaughtException.getMessage()));
/* Send report. */
waitFor(onView(withText(R.string.crash_confirmation_dialog_send_button)).inRoot(isDialog()), 1000).perform(click());
/* Check toasts. */
waitFor(onToast(mActivityTestRule.getActivity(), withText(R.string.crash_before_sending)), TOAST_DELAY).check(matches(isDisplayed()));
onView(isRoot()).perform(waitFor(CHECK_DELAY));
waitFor(onToast(mActivityTestRule.getActivity(), anyOf(withContainsText(R.string.crash_sent_succeeded), withText(R.string.crash_sent_failed))), TOAST_DELAY).check(matches(isDisplayed()));
}
use of com.microsoft.appcenter.crashes.model.ErrorReport in project mobile-center-sdk-android by Microsoft.
the class CrashesTest method handleUserConfirmationDoNotSend.
@Test
public void handleUserConfirmationDoNotSend() throws JSONException {
/* Prepare data. Mock classes. */
mockStatic(ErrorLogHelper.class);
when(ErrorLogHelper.getStoredErrorLogFiles()).thenReturn(new File[] { mock(File.class) });
when(ErrorLogHelper.getNewMinidumpFiles()).thenReturn(new File[0]);
when(ErrorLogHelper.getErrorReportFromErrorLog(any(ManagedErrorLog.class), anyString())).thenReturn(new ErrorReport());
File pendingFolder = mock(File.class);
when(ErrorLogHelper.getPendingMinidumpDirectory()).thenReturn(pendingFolder);
when(FileManager.read(any(File.class))).thenReturn("");
CrashesListener mockListener = mock(CrashesListener.class);
when(mockListener.shouldProcess(any(ErrorReport.class))).thenReturn(true);
when(mockListener.shouldAwaitUserConfirmation()).thenReturn(true);
/* Prepare data. Set values. */
Crashes crashes = Crashes.getInstance();
LogSerializer logSerializer = mock(LogSerializer.class);
when(logSerializer.deserializeLog(anyString(), anyString())).thenReturn(mErrorLog);
crashes.setLogSerializer(logSerializer);
crashes.setInstanceListener(mockListener);
crashes.onStarting(mAppCenterHandler);
crashes.onStarted(mock(Context.class), mock(Channel.class), "", null, true);
/* Verify. */
Crashes.notifyUserConfirmation(Crashes.DONT_SEND);
verify(mockListener, never()).getErrorAttachments(any(ErrorReport.class));
verifyStatic();
ErrorLogHelper.cleanPendingMinidumps();
verifyStatic();
ErrorLogHelper.removeStoredErrorLogFile(mErrorLog.getId());
verifyStatic(never());
ErrorLogHelper.removeLostThrowableFiles();
}
Aggregations