use of com.microsoft.appcenter.crashes.ingestion.models.ManagedErrorLog in project mobile-center-sdk-android by Microsoft.
the class CrashesAndroidTest method processingWithMinidump.
@Test
public void processingWithMinidump() throws Exception {
/* Simulate we have a minidump. */
File newMinidumpDirectory = ErrorLogHelper.getNewMinidumpDirectory();
File minidumpFile = new File(newMinidumpDirectory, "minidump.dmp");
StorageHelper.InternalStorage.write(minidumpFile, "mock minidump");
/* Set up crash listener. */
CrashesListener crashesListener = mock(CrashesListener.class);
when(crashesListener.shouldProcess(any(ErrorReport.class))).thenReturn(true);
when(crashesListener.shouldAwaitUserConfirmation()).thenReturn(true);
ErrorAttachmentLog textAttachment = ErrorAttachmentLog.attachmentWithText("Hello", "hello.txt");
when(crashesListener.getErrorAttachments(any(ErrorReport.class))).thenReturn(Collections.singletonList(textAttachment));
startFresh(crashesListener);
/* Check last session error report. */
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. */
ArgumentMatcher<Log> matchCrashLog = new ArgumentMatcher<Log>() {
@Override
public boolean matches(Object o) {
return o instanceof ManagedErrorLog;
}
};
verify(mChannel, never()).enqueue(argThat(matchCrashLog), anyString());
assertEquals(2, ErrorLogHelper.getErrorStorageDirectory().listFiles(mMinidumpFilter).length);
verify(crashesListener).shouldProcess(any(ErrorReport.class));
verify(crashesListener).shouldAwaitUserConfirmation();
verifyNoMoreInteractions(crashesListener);
/* Confirm to resume processing. */
final AtomicReference<Log> log = new AtomicReference<>();
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
log.set((Log) invocationOnMock.getArguments()[0]);
return null;
}
}).when(mChannel).enqueue(argThat(matchCrashLog), anyString());
Crashes.notifyUserConfirmation(Crashes.SEND);
assertTrue(Crashes.isEnabled().get());
verify(mChannel).enqueue(argThat(matchCrashLog), anyString());
assertNotNull(log.get());
assertEquals(1, ErrorLogHelper.getErrorStorageDirectory().listFiles(mMinidumpFilter).length);
verify(crashesListener).getErrorAttachments(any(ErrorReport.class));
verifyNoMoreInteractions(crashesListener);
/* Verify automatic minidump attachment. */
verify(mChannel).enqueue(argThat(new ArgumentMatcher<Log>() {
@Override
public boolean matches(Object argument) {
if (argument instanceof ErrorAttachmentLog) {
ErrorAttachmentLog log = (ErrorAttachmentLog) argument;
return "application/octet-stream".equals(log.getContentType()) && "minidump.dmp".equals(log.getFileName());
}
return false;
}
}), anyString());
/* Verify custom text attachment. */
verify(mChannel).enqueue(eq(textAttachment), anyString());
}
use of com.microsoft.appcenter.crashes.ingestion.models.ManagedErrorLog in project mobile-center-sdk-android by Microsoft.
the class Crashes method saveUncaughtException.
/**
* Save uncaught exception to disk.
*
* @param thread thread where exception occurred.
* @param throwable Java exception as is, can be null for non Java exceptions.
* @param modelException model exception, supports any language.
* @return error log identifier.
* @throws JSONException if an error occurred during JSON serialization of modelException.
* @throws IOException if an error occurred while accessing the file system.
*/
UUID saveUncaughtException(Thread thread, Throwable throwable, com.microsoft.appcenter.crashes.ingestion.models.Exception modelException) throws JSONException, IOException {
/* Ignore call if Crash is disabled. */
if (!Crashes.isEnabled().get()) {
return null;
}
/*
* Save only 1 crash. This is needed for example in Xamarin
* where we save as a Xamarin crash before Java handler is called.
*/
if (mSavedUncaughtException) {
return null;
}
mSavedUncaughtException = true;
/* Save error log. */
ManagedErrorLog errorLog = ErrorLogHelper.createErrorLog(mContext, thread, modelException, Thread.getAllStackTraces(), mInitializeTimestamp, true);
return saveErrorLogFiles(throwable, errorLog);
}
use of com.microsoft.appcenter.crashes.ingestion.models.ManagedErrorLog in project mobile-center-sdk-android by Microsoft.
the class ErrorLogHelper method createErrorLog.
@NonNull
public static ManagedErrorLog createErrorLog(@NonNull Context context, @NonNull final java.lang.Thread thread, @NonNull final Exception exception, @NonNull final Map<java.lang.Thread, StackTraceElement[]> allStackTraces, final long initializeTimestamp, boolean fatal) {
/* Build error log with a unique identifier. */
ManagedErrorLog errorLog = new ManagedErrorLog();
errorLog.setId(UUIDUtils.randomUUID());
/* Set current time. Will be correlated to session after restart. */
errorLog.setTimestamp(new Date());
/* Snapshot device properties. */
try {
errorLog.setDevice(DeviceInfoHelper.getDeviceInfo(context));
} catch (DeviceInfoHelper.DeviceInfoException e) {
AppCenterLog.error(Crashes.LOG_TAG, "Could not attach device properties snapshot to error log, will attach at sending time", e);
}
/* Process information. Parent one is not available on Android. */
errorLog.setProcessId(Process.myPid());
ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if (activityManager != null) {
for (ActivityManager.RunningAppProcessInfo info : activityManager.getRunningAppProcesses()) {
if (info.pid == Process.myPid()) {
errorLog.setProcessName(info.processName);
}
}
}
/* CPU architecture. */
errorLog.setArchitecture(getArchitecture());
/* Thread in error information. */
errorLog.setErrorThreadId(thread.getId());
errorLog.setErrorThreadName(thread.getName());
/* Uncaught exception or managed exception. */
errorLog.setFatal(fatal);
/* Application launch time. */
errorLog.setAppLaunchTimestamp(new Date(initializeTimestamp));
/* Attach exceptions. */
errorLog.setException(exception);
/* Attach thread states. */
List<Thread> threads = new ArrayList<>(allStackTraces.size());
for (Map.Entry<java.lang.Thread, StackTraceElement[]> entry : allStackTraces.entrySet()) {
Thread javaThread = new Thread();
javaThread.setId(entry.getKey().getId());
javaThread.setName(entry.getKey().getName());
javaThread.setFrames(getModelFramesFromStackTrace(entry.getValue()));
threads.add(javaThread);
}
errorLog.setThreads(threads);
return errorLog;
}
use of com.microsoft.appcenter.crashes.ingestion.models.ManagedErrorLog in project mobile-center-sdk-android by Microsoft.
the class CrashesTest method manualProcessing.
@Test
public void manualProcessing() throws Exception {
/* Setup mock for a crash in disk. */
Context mockContext = mock(Context.class);
Channel mockChannel = mock(Channel.class);
ErrorReport report1 = new ErrorReport();
report1.setId(UUIDUtils.randomUUID().toString());
ErrorReport report2 = new ErrorReport();
mockStatic(ErrorLogHelper.class);
when(ErrorLogHelper.getStoredErrorLogFiles()).thenReturn(new File[] { mock(File.class), mock(File.class) });
when(ErrorLogHelper.getNewMinidumpFiles()).thenReturn(new File[0]);
when(ErrorLogHelper.getStoredThrowableFile(any(UUID.class))).thenReturn(mock(File.class));
when(ErrorLogHelper.getErrorReportFromErrorLog(any(ManagedErrorLog.class), any(Throwable.class))).thenReturn(report1).thenReturn(report2);
when(StorageHelper.InternalStorage.read(any(File.class))).thenReturn("");
when(StorageHelper.InternalStorage.readObject(any(File.class))).thenReturn(new RuntimeException());
LogSerializer logSerializer = mock(LogSerializer.class);
when(logSerializer.deserializeLog(anyString())).thenAnswer(new Answer<ManagedErrorLog>() {
@Override
public ManagedErrorLog answer(InvocationOnMock invocation) throws Throwable {
ManagedErrorLog log = mock(ManagedErrorLog.class);
when(log.getId()).thenReturn(UUID.randomUUID());
return log;
}
});
Crashes crashes = Crashes.getInstance();
crashes.setLogSerializer(logSerializer);
/* Create listener for user confirmation. */
CrashesListener listener = mock(CrashesListener.class);
Crashes.setListener(listener);
/* Set manual processing. */
WrapperSdkExceptionManager.setAutomaticProcessing(false);
/* Start crashes. */
crashes.onStarting(mAppCenterHandler);
crashes.onStarted(mockContext, "", mockChannel);
/* No log queued. */
verify(mockChannel, never()).enqueue(any(Log.class), eq(crashes.getGroupName()));
/* Get crash reports. */
Collection<ErrorReport> reports = WrapperSdkExceptionManager.getUnprocessedErrorReports().get();
assertNotNull(reports);
assertEquals(2, reports.size());
Iterator<ErrorReport> iterator = reports.iterator();
assertEquals(report1, iterator.next());
assertEquals(report2, iterator.next());
/* Listener not called yet on anything on manual processing. */
verifyZeroInteractions(listener);
/* Send only the first. */
assertFalse(WrapperSdkExceptionManager.sendCrashReportsOrAwaitUserConfirmation(Collections.singletonList(report1.getId())).get());
/* We used manual process function, listener not called. */
verifyZeroInteractions(listener);
/* No log sent until manual user confirmation in that mode (we are not in always send). */
verify(mockChannel, never()).enqueue(any(ManagedErrorLog.class), eq(crashes.getGroupName()));
/* Confirm with always send. */
Crashes.notifyUserConfirmation(Crashes.ALWAYS_SEND);
verifyStatic();
StorageHelper.PreferencesStorage.putBoolean(Crashes.PREF_KEY_ALWAYS_SEND, true);
when(StorageHelper.PreferencesStorage.getBoolean(eq(Crashes.PREF_KEY_ALWAYS_SEND), anyBoolean())).thenReturn(true);
/* 1 log sent. Other one is filtered. */
verify(mockChannel).enqueue(any(ManagedErrorLog.class), eq(crashes.getGroupName()));
/* We can send attachments via wrapper instead of using listener (both work but irrelevant to test with listener). */
ErrorAttachmentLog mockAttachment = mock(ErrorAttachmentLog.class);
when(mockAttachment.getId()).thenReturn(UUID.randomUUID());
when(mockAttachment.getData()).thenReturn(new byte[0]);
when(mockAttachment.isValid()).thenReturn(true);
WrapperSdkExceptionManager.sendErrorAttachments(report1.getId(), Collections.singletonList(mockAttachment));
verify(mockChannel).enqueue(eq(mockAttachment), eq(crashes.getGroupName()));
/* Send attachment with invalid UUID format for report identifier. */
mockAttachment = mock(ErrorAttachmentLog.class);
when(mockAttachment.getId()).thenReturn(UUID.randomUUID());
when(mockAttachment.getData()).thenReturn(new byte[0]);
when(mockAttachment.isValid()).thenReturn(true);
WrapperSdkExceptionManager.sendErrorAttachments("not-a-uuid", Collections.singletonList(mockAttachment));
verify(mockChannel, never()).enqueue(eq(mockAttachment), eq(crashes.getGroupName()));
/* We used manual process function, listener not called and our mock channel does not send events. */
verifyZeroInteractions(listener);
/* Reset instance to test another tine with always send. */
Crashes.unsetInstance();
crashes = Crashes.getInstance();
when(ErrorLogHelper.getErrorReportFromErrorLog(any(ManagedErrorLog.class), any(Throwable.class))).thenReturn(report1).thenReturn(report2);
WrapperSdkExceptionManager.setAutomaticProcessing(false);
crashes.setLogSerializer(logSerializer);
crashes.onStarting(mAppCenterHandler);
mockChannel = mock(Channel.class);
crashes.onStarted(mockContext, "", mockChannel);
assertTrue(Crashes.isEnabled().get());
verify(mockChannel, never()).enqueue(any(ManagedErrorLog.class), eq(crashes.getGroupName()));
/* Get crash reports, check always sent was returned and sent without confirmation. */
assertTrue(WrapperSdkExceptionManager.sendCrashReportsOrAwaitUserConfirmation(Collections.singletonList(report2.getId())).get());
verify(mockChannel).enqueue(any(ManagedErrorLog.class), eq(crashes.getGroupName()));
}
use of com.microsoft.appcenter.crashes.ingestion.models.ManagedErrorLog in project mobile-center-sdk-android by Microsoft.
the class CrashesTest method manuallyReportNullList.
@Test
public void manuallyReportNullList() throws Exception {
/* Setup mock for a crash in disk. */
Context mockContext = mock(Context.class);
Channel mockChannel = mock(Channel.class);
ErrorReport report1 = new ErrorReport();
report1.setId(UUIDUtils.randomUUID().toString());
ErrorReport report2 = new ErrorReport();
mockStatic(ErrorLogHelper.class);
when(ErrorLogHelper.getStoredErrorLogFiles()).thenReturn(new File[] { mock(File.class), mock(File.class) });
when(ErrorLogHelper.getNewMinidumpFiles()).thenReturn(new File[0]);
when(ErrorLogHelper.getStoredThrowableFile(any(UUID.class))).thenReturn(mock(File.class));
when(ErrorLogHelper.getErrorReportFromErrorLog(any(ManagedErrorLog.class), any(Throwable.class))).thenReturn(report1).thenReturn(report2);
when(StorageHelper.InternalStorage.read(any(File.class))).thenReturn("");
when(StorageHelper.InternalStorage.readObject(any(File.class))).thenReturn(new RuntimeException());
LogSerializer logSerializer = mock(LogSerializer.class);
when(logSerializer.deserializeLog(anyString())).thenAnswer(new Answer<ManagedErrorLog>() {
@Override
public ManagedErrorLog answer(InvocationOnMock invocation) throws Throwable {
ManagedErrorLog log = mock(ManagedErrorLog.class);
when(log.getId()).thenReturn(UUID.randomUUID());
return log;
}
});
Crashes crashes = Crashes.getInstance();
crashes.setLogSerializer(logSerializer);
/* Set manual processing. */
WrapperSdkExceptionManager.setAutomaticProcessing(false);
/* Start crashes. */
crashes.onStarting(mAppCenterHandler);
crashes.onStarted(mockContext, "", mockChannel);
/* No log queued. */
verify(mockChannel, never()).enqueue(any(Log.class), eq(crashes.getGroupName()));
/* Get crash reports. */
Collection<ErrorReport> reports = WrapperSdkExceptionManager.getUnprocessedErrorReports().get();
assertNotNull(reports);
assertEquals(2, reports.size());
Iterator<ErrorReport> iterator = reports.iterator();
assertEquals(report1, iterator.next());
assertEquals(report2, iterator.next());
/* Send nothing using null. */
assertFalse(WrapperSdkExceptionManager.sendCrashReportsOrAwaitUserConfirmation(null).get());
/* No log sent. */
verify(mockChannel, never()).enqueue(any(ManagedErrorLog.class), eq(crashes.getGroupName()));
}
Aggregations