use of com.microsoft.appcenter.crashes.model.ErrorReport in project AppCenter-SDK-Android by Microsoft.
the class CrashesTest method getChannelListener.
@Test
public void getChannelListener() throws IOException, ClassNotFoundException {
ErrorReport errorReport = ErrorLogHelper.getErrorReportFromErrorLog(mErrorLog, EXCEPTION);
mockStatic(ErrorLogHelper.class);
when(ErrorLogHelper.getStoredErrorLogFiles()).thenReturn(new File[] { mock(File.class) });
when(ErrorLogHelper.getNewMinidumpFiles()).thenReturn(new File[0]);
File throwableFile = mock(File.class);
when(throwableFile.length()).thenReturn(1L);
when(ErrorLogHelper.getStoredThrowableFile(any(UUID.class))).thenReturn(throwableFile);
when(ErrorLogHelper.getErrorReportFromErrorLog(mErrorLog, EXCEPTION)).thenReturn(errorReport);
when(StorageHelper.InternalStorage.readObject(any(File.class))).thenReturn(EXCEPTION);
CrashesListener crashesListener = mock(CrashesListener.class);
Crashes.setListener(crashesListener);
Crashes crashes = Crashes.getInstance();
crashes.onStarting(mAppCenterHandler);
crashes.onStarted(mock(Context.class), "", mock(Channel.class));
ArgumentCaptor<ErrorReport> errorReportCaptor = ArgumentCaptor.forClass(ErrorReport.class);
Channel.GroupListener channelListener = crashes.getChannelListener();
channelListener.onBeforeSending(mErrorLog);
verify(crashesListener).onBeforeSending(errorReportCaptor.capture());
assertErrorEquals(mErrorLog, errorReportCaptor.getValue());
channelListener.onSuccess(mErrorLog);
verify(crashesListener).onSendingSucceeded(errorReportCaptor.capture());
assertErrorEquals(mErrorLog, errorReportCaptor.getValue());
channelListener.onFailure(mErrorLog, EXCEPTION);
verify(crashesListener).onSendingFailed(errorReportCaptor.capture(), eq(EXCEPTION));
assertErrorEquals(mErrorLog, errorReportCaptor.getValue());
}
use of com.microsoft.appcenter.crashes.model.ErrorReport in project AppCenter-SDK-Android by Microsoft.
the class CrashesTest method handleUserConfirmationDoNotSend.
@Test
public void handleUserConfirmationDoNotSend() throws IOException, ClassNotFoundException, JSONException {
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(new ErrorReport());
when(StorageHelper.InternalStorage.read(any(File.class))).thenReturn("");
when(StorageHelper.InternalStorage.readObject(any(File.class))).thenReturn(null);
CrashesListener mockListener = mock(CrashesListener.class);
when(mockListener.shouldProcess(any(ErrorReport.class))).thenReturn(true);
when(mockListener.shouldAwaitUserConfirmation()).thenReturn(true);
Crashes crashes = Crashes.getInstance();
LogSerializer logSerializer = mock(LogSerializer.class);
when(logSerializer.deserializeLog(anyString())).thenReturn(mErrorLog);
crashes.setLogSerializer(logSerializer);
crashes.setInstanceListener(mockListener);
crashes.onStarting(mAppCenterHandler);
crashes.onStarted(mock(Context.class), "", mock(Channel.class));
Crashes.notifyUserConfirmation(Crashes.DONT_SEND);
verify(mockListener, never()).getErrorAttachments(any(ErrorReport.class));
verifyStatic();
ErrorLogHelper.removeStoredErrorLogFile(mErrorLog.getId());
verifyStatic();
ErrorLogHelper.removeStoredThrowableFile(mErrorLog.getId());
}
use of com.microsoft.appcenter.crashes.model.ErrorReport in project AppCenter-SDK-Android by Microsoft.
the class CrashesAndroidTest method testNoDuplicateCallbacksOrSending.
@Test
public void testNoDuplicateCallbacksOrSending() throws Exception {
/* Crash on 1st process. */
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) throws Throwable {
assertNotNull(AppCenter.getInstallId().get());
return AppCenter.isEnabled().get() && Crashes.isEnabled().get();
}
});
when(crashesListener.shouldAwaitUserConfirmation()).thenReturn(true);
startFresh(crashesListener);
final Error exception = generateStackOverflowError();
assertTrue(exception.getStackTrace().length > ErrorLogHelper.FRAME_LIMIT);
final Thread thread = new Thread() {
@Override
public void run() {
throw exception;
}
};
thread.start();
thread.join();
assertEquals(ErrorLogHelper.FRAME_LIMIT, exception.getStackTrace().length);
verify(uncaughtExceptionHandler).uncaughtException(thread, exception);
assertEquals(2, ErrorLogHelper.getErrorStorageDirectory().listFiles(mMinidumpFilter).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);
Throwable lastThrowable = errorReport.getThrowable();
assertTrue(lastThrowable instanceof StackOverflowError);
assertEquals(ErrorLogHelper.FRAME_LIMIT, lastThrowable.getStackTrace().length);
}
});
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.ALWAYS_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);
/* 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(), groupListener.capture());
groupListener.getValue().onBeforeSending(log.get());
groupListener.getValue().onSuccess(log.get());
/* 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();
assertEquals(0, ErrorLogHelper.getErrorStorageDirectory().listFiles(mMinidumpFilter).length);
verify(mChannel, never()).enqueue(argThat(matchCrashLog), anyString());
verify(crashesListener).onBeforeSending(any(ErrorReport.class));
verify(crashesListener).onSendingSucceeded(any(ErrorReport.class));
verifyNoMoreInteractions(crashesListener);
/* Verify log was truncated to 256 frames. */
assertTrue(log.get() instanceof ManagedErrorLog);
ManagedErrorLog errorLog = (ManagedErrorLog) log.get();
assertNotNull(errorLog.getException());
assertNotNull(errorLog.getException().getFrames());
assertEquals(ErrorLogHelper.FRAME_LIMIT, errorLog.getException().getFrames().size());
}
use of com.microsoft.appcenter.crashes.model.ErrorReport in project AppCenter-SDK-Android by Microsoft.
the class Crashes method buildErrorReport.
@VisibleForTesting
@Nullable
ErrorReport buildErrorReport(ManagedErrorLog log) {
UUID id = log.getId();
if (mErrorReportCache.containsKey(id)) {
return mErrorReportCache.get(id).report;
} else {
File file = ErrorLogHelper.getStoredThrowableFile(id);
if (file != null) {
try {
Throwable throwable = null;
if (file.length() > 0) {
throwable = StorageHelper.InternalStorage.readObject(file);
}
ErrorReport report = ErrorLogHelper.getErrorReportFromErrorLog(log, throwable);
mErrorReportCache.put(id, new ErrorLogReport(log, report));
return report;
} catch (ClassNotFoundException ignored) {
AppCenterLog.error(LOG_TAG, "Cannot read throwable file " + file.getName(), ignored);
} catch (IOException ignored) {
AppCenterLog.error(LOG_TAG, "Cannot access serialized throwable file " + file.getName(), ignored);
}
}
}
return null;
}
use of com.microsoft.appcenter.crashes.model.ErrorReport in project AppCenter-SDK-Android by Microsoft.
the class MainActivity method onCreate.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sSharedPreferences = getSharedPreferences("Sasquatch", Context.MODE_PRIVATE);
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().build());
/* Set custom log URL if one was configured in settings. */
String logUrl = sSharedPreferences.getString(LOG_URL_KEY, getString(R.string.log_url));
if (!TextUtils.isEmpty(logUrl)) {
AppCenter.setLogUrl(logUrl);
}
/* Set listeners. */
AnalyticsPrivateHelper.setListener(getAnalyticsListener());
Crashes.setListener(getCrashesListener());
Distribute.setListener(new SasquatchDistributeListener());
Push.setListener(getPushListener());
/* Set distribute urls. */
String installUrl = getString(R.string.install_url);
if (!TextUtils.isEmpty(installUrl)) {
Distribute.setInstallUrl(installUrl);
}
String apiUrl = getString(R.string.api_url);
if (!TextUtils.isEmpty(apiUrl)) {
Distribute.setApiUrl(apiUrl);
}
Push.setSenderId(SENDER_ID);
/* Set crash attachments. */
sCrashesListener.setTextAttachment(sSharedPreferences.getString(TEXT_ATTACHMENT_KEY, null));
String fileAttachment = sSharedPreferences.getString(FILE_ATTACHMENT_KEY, null);
if (fileAttachment != null) {
sCrashesListener.setFileAttachment(Uri.parse(fileAttachment));
}
/* Enable Firebase analytics if we enabled the setting previously. */
if (sSharedPreferences.getBoolean(FIREBASE_ENABLED_KEY, false)) {
Push.enableFirebaseAnalytics(this);
}
/* Start App Center. */
AppCenter.start(getApplication(), sSharedPreferences.getString(APP_SECRET_KEY, getString(R.string.app_secret)), Analytics.class, Crashes.class, Distribute.class, Push.class);
/* Attach NDK Crash Handler (if available) after SDK is initialized. */
CrashesPrivateHelper.getMinidumpDirectory().thenAccept(new AppCenterConsumer<String>() {
@Override
public void accept(String path) {
/* Path is null when Crashes is disabled. */
if (path != null) {
setupNativeCrashesListener(path);
}
}
});
/* Use some App Center getters. */
AppCenter.getInstallId().thenAccept(new AppCenterConsumer<UUID>() {
@Override
public void accept(UUID uuid) {
Log.i(LOG_TAG, "InstallId=" + uuid);
}
});
/* Print last crash. */
Crashes.hasCrashedInLastSession().thenAccept(new AppCenterConsumer<Boolean>() {
@Override
public void accept(Boolean crashed) {
Log.i(LOG_TAG, "Crashes.hasCrashedInLastSession=" + crashed);
}
});
Crashes.getLastSessionCrashReport().thenAccept(new AppCenterConsumer<ErrorReport>() {
@Override
public void accept(ErrorReport data) {
if (data != null) {
Log.i(LOG_TAG, "Crashes.getLastSessionCrashReport().getThrowable()=", data.getThrowable());
}
}
});
/* Populate UI. */
((TextView) findViewById(R.id.package_name)).setText(String.format(getString(R.string.sdk_source_format), getPackageName().substring(getPackageName().lastIndexOf(".") + 1)));
TestFeatures.initialize(this);
ListView listView = findViewById(R.id.list);
listView.setAdapter(new TestFeaturesListAdapter(TestFeatures.getAvailableControls()));
listView.setOnItemClickListener(TestFeatures.getOnItemClickListener());
}
Aggregations