use of com.microsoft.appcenter.crashes.ingestion.models.ErrorAttachmentLog in project mobile-center-sdk-android by Microsoft.
the class CrashesTest method queuePendingCrashesShouldProcess.
@Test
public void queuePendingCrashesShouldProcess() throws IOException, ClassNotFoundException, JSONException {
/* Setup mock. */
Context mockContext = mock(Context.class);
Channel mockChannel = mock(Channel.class);
ErrorReport report = new ErrorReport();
mockStatic(ErrorLogHelper.class);
when(ErrorLogHelper.getStoredErrorLogFiles()).thenReturn(new File[] { 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(report);
when(StorageHelper.InternalStorage.read(any(File.class))).thenReturn("");
when(StorageHelper.InternalStorage.readObject(any(File.class))).thenReturn(new RuntimeException());
CrashesListener mockListener = mock(CrashesListener.class);
when(mockListener.shouldProcess(report)).thenReturn(true);
when(mockListener.shouldAwaitUserConfirmation()).thenReturn(false);
ErrorAttachmentLog mockAttachment = mock(ErrorAttachmentLog.class);
when(mockAttachment.getId()).thenReturn(UUID.randomUUID());
when(mockAttachment.getErrorId()).thenReturn(UUID.randomUUID());
when(mockAttachment.getContentType()).thenReturn("");
when(mockAttachment.getFileName()).thenReturn("");
when(mockAttachment.getData()).thenReturn(new byte[0]);
when(mockAttachment.isValid()).thenReturn(true);
ErrorAttachmentLog mockEmptyAttachment = mock(ErrorAttachmentLog.class);
final int skipAttachmentLogsCount = 2;
List<ErrorAttachmentLog> errorAttachmentLogList = Arrays.asList(mockAttachment, mockAttachment, mockEmptyAttachment, null);
when(mockListener.getErrorAttachments(report)).thenReturn(errorAttachmentLogList);
LogSerializer logSerializer = mock(LogSerializer.class);
when(logSerializer.deserializeLog(anyString())).thenReturn(mErrorLog);
Crashes crashes = Crashes.getInstance();
crashes.setLogSerializer(logSerializer);
crashes.setInstanceListener(mockListener);
crashes.onStarting(mAppCenterHandler);
crashes.onStarted(mockContext, "", mockChannel);
/* Test. */
verify(mockListener).shouldProcess(report);
verify(mockListener).shouldAwaitUserConfirmation();
verify(mockListener).getErrorAttachments(report);
verify(mockChannel).enqueue(argThat(new ArgumentMatcher<Log>() {
@Override
public boolean matches(Object log) {
return log.equals(mErrorLog);
}
}), eq(crashes.getGroupName()));
verify(mockChannel, times(errorAttachmentLogList.size() - skipAttachmentLogsCount)).enqueue(mockAttachment, crashes.getGroupName());
}
use of com.microsoft.appcenter.crashes.ingestion.models.ErrorAttachmentLog in project mobile-center-sdk-android by Microsoft.
the class SasquatchCrashesListener method getErrorAttachments.
@Override
public Iterable<ErrorAttachmentLog> getErrorAttachments(ErrorReport report) {
List<ErrorAttachmentLog> attachments = new LinkedList<>();
/* Attach app icon to test binary. */
if (mFileAttachment != null) {
try {
byte[] data = getFileAttachmentData();
String name = getFileAttachmentDisplayName();
String mime = getFileAttachmentMimeType();
ErrorAttachmentLog binaryLog = ErrorAttachmentLog.attachmentWithBinary(data, name, mime);
attachments.add(binaryLog);
} catch (SecurityException e) {
Log.e(LOG_TAG, "Couldn't get file attachment data.", e);
/* Reset file attachment. */
MainActivity.setFileAttachment(null);
}
}
/* Attach some text. */
if (!TextUtils.isEmpty(mTextAttachment)) {
ErrorAttachmentLog textLog = ErrorAttachmentLog.attachmentWithText(mTextAttachment, "text.txt");
attachments.add(textLog);
}
/* Return attachments as list. */
return attachments.size() > 0 ? attachments : null;
}
use of com.microsoft.appcenter.crashes.ingestion.models.ErrorAttachmentLog 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.ErrorAttachmentLog in project mobile-center-sdk-android by Microsoft.
the class Crashes method sendErrorAttachment.
/**
* Send error attachment logs through channel.
*/
private void sendErrorAttachment(UUID errorId, Iterable<ErrorAttachmentLog> attachments) {
if (attachments == null) {
AppCenterLog.debug(LOG_TAG, "CrashesListener.getErrorAttachments returned null, no additional information will be attached to log: " + errorId.toString());
} else {
int totalErrorAttachments = 0;
for (ErrorAttachmentLog attachment : attachments) {
if (attachment != null) {
attachment.setId(UUID.randomUUID());
attachment.setErrorId(errorId);
if (attachment.isValid()) {
++totalErrorAttachments;
mChannel.enqueue(attachment, ERROR_GROUP);
} else {
AppCenterLog.error(LOG_TAG, "Not all required fields are present in ErrorAttachmentLog.");
}
} else {
AppCenterLog.warn(LOG_TAG, "Skipping null ErrorAttachmentLog in CrashesListener.getErrorAttachments.");
}
}
if (totalErrorAttachments > MAX_ATTACHMENT_PER_CRASH) {
AppCenterLog.warn(LOG_TAG, "A limit of " + MAX_ATTACHMENT_PER_CRASH + " attachments per error report might be enforced by server.");
}
}
}
use of com.microsoft.appcenter.crashes.ingestion.models.ErrorAttachmentLog 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()));
}
Aggregations