use of com.microsoft.azure.mobile.crashes.ingestion.models.ManagedErrorLog in project mobile-center-sdk-android by Microsoft.
the class CrashesAndroidTest method testNoDuplicateCallbacksOrSending.
@Test
public void testNoDuplicateCallbacksOrSending() throws InterruptedException {
/* Crash on 1st process. */
assertFalse(Crashes.hasCrashedInLastSession());
android.util.Log.i(TAG, "Process 1");
Thread.UncaughtExceptionHandler uncaughtExceptionHandler = mock(Thread.UncaughtExceptionHandler.class);
Thread.setDefaultUncaughtExceptionHandler(uncaughtExceptionHandler);
Channel channel = mock(Channel.class);
Crashes.getInstance().onStarted(sContext, "", channel);
CrashesListener crashesListener = mock(CrashesListener.class);
when(crashesListener.shouldProcess(any(ErrorReport.class))).thenReturn(true);
when(crashesListener.shouldAwaitUserConfirmation()).thenReturn(true);
Crashes.setListener(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().length);
verifyZeroInteractions(crashesListener);
/* Second process: enqueue log but network is down... */
android.util.Log.i(TAG, "Process 2");
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(channel).enqueue(any(Log.class), anyString());
Crashes.unsetInstance();
Crashes.setListener(crashesListener);
Crashes.getInstance().onStarted(sContext, "", channel);
waitForCrashesHandlerTasksToComplete();
/* Check last session error report. */
assertTrue(Crashes.hasCrashedInLastSession());
Crashes.getLastSessionCrashReport(new ResultCallback<ErrorReport>() {
@Override
public void onResult(ErrorReport errorReport) {
assertNotNull(errorReport);
Throwable lastThrowable = errorReport.getThrowable();
assertTrue(lastThrowable instanceof StackOverflowError);
assertEquals(ErrorLogHelper.FRAME_LIMIT, lastThrowable.getStackTrace().length);
}
});
/* Waiting user confirmation so no log sent yet. */
verify(channel, never()).enqueue(any(Log.class), anyString());
assertEquals(2, ErrorLogHelper.getErrorStorageDirectory().listFiles().length);
verify(crashesListener).shouldProcess(any(ErrorReport.class));
verify(crashesListener).shouldAwaitUserConfirmation();
verifyNoMoreInteractions(crashesListener);
/* Confirm to resume processing. */
Crashes.notifyUserConfirmation(Crashes.ALWAYS_SEND);
verify(channel).enqueue(any(Log.class), anyString());
assertNotNull(log.get());
assertEquals(1, ErrorLogHelper.getErrorStorageDirectory().listFiles().length);
verify(crashesListener).getErrorAttachments(any(ErrorReport.class));
verifyNoMoreInteractions(crashesListener);
/* Third process: sending succeeds. */
android.util.Log.i(TAG, "Process 3");
final AtomicReference<Channel.GroupListener> groupListener = new AtomicReference<>();
channel = mock(Channel.class);
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
Channel.GroupListener listener = (Channel.GroupListener) invocationOnMock.getArguments()[4];
groupListener.set(listener);
listener.onBeforeSending(log.get());
return null;
}
}).when(channel).addGroup(anyString(), anyInt(), anyInt(), anyInt(), any(Channel.GroupListener.class));
Crashes.unsetInstance();
Crashes.setListener(crashesListener);
Crashes.getInstance().onStarted(sContext, "", channel);
waitForCrashesHandlerTasksToComplete();
assertFalse(Crashes.hasCrashedInLastSession());
Crashes.getLastSessionCrashReport(new ResultCallback<ErrorReport>() {
@Override
public void onResult(ErrorReport errorReport) {
assertNull(errorReport);
}
});
assertNotNull(groupListener.get());
groupListener.get().onSuccess(log.get());
waitForCrashesHandlerTasksToComplete();
assertEquals(0, ErrorLogHelper.getErrorStorageDirectory().listFiles().length);
verify(channel, never()).enqueue(any(Log.class), 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.azure.mobile.crashes.ingestion.models.ManagedErrorLog in project mobile-center-sdk-android by Microsoft.
the class CrashesTest method disabledDuringHandleUserConfirmation.
@Test
public void disabledDuringHandleUserConfirmation() throws IOException, ClassNotFoundException, JSONException {
ManagedErrorLog errorLog = ErrorLogHelper.createErrorLog(mock(Context.class), Thread.currentThread(), new RuntimeException(), Thread.getAllStackTraces(), 0, true);
ErrorReport errorReport1 = ErrorLogHelper.getErrorReportFromErrorLog(mErrorLog, EXCEPTION);
ErrorReport errorReport2 = ErrorLogHelper.getErrorReportFromErrorLog(errorLog, EXCEPTION);
File errorStorageDirectory = mock(File.class);
when(errorStorageDirectory.listFiles()).thenReturn(new File[0]);
CrashesListener listener = mock(CrashesListener.class);
when(listener.shouldProcess(any(ErrorReport.class))).thenReturn(true);
LogSerializer logSerializer = mock(LogSerializer.class);
when(logSerializer.deserializeLog(anyString())).thenReturn(mErrorLog).thenReturn(errorLog);
Channel channel = mock(Channel.class);
doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
Crashes.setEnabled(false);
return null;
}
}).when(channel).enqueue(any(Log.class), anyString());
mockStatic(ErrorLogHelper.class);
when(ErrorLogHelper.getStoredErrorLogFiles()).thenReturn(new File[] { mock(File.class), mock(File.class) });
when(ErrorLogHelper.getErrorStorageDirectory()).thenReturn(errorStorageDirectory);
when(ErrorLogHelper.getStoredThrowableFile(any(UUID.class))).thenReturn(mock(File.class));
when(ErrorLogHelper.getErrorReportFromErrorLog(mErrorLog, EXCEPTION)).thenReturn(errorReport1);
when(ErrorLogHelper.getErrorReportFromErrorLog(errorLog, EXCEPTION)).thenReturn(errorReport2);
when(StorageHelper.InternalStorage.readObject(any(File.class))).thenReturn(EXCEPTION);
when(StorageHelper.InternalStorage.read(any(File.class))).thenReturn("");
Crashes crashes = Crashes.getInstance();
crashes.setLogSerializer(logSerializer);
crashes.setInstanceListener(listener);
crashes.onStarted(mock(Context.class), "", channel);
verify(mMockLooper).quit();
verify(listener, times(2)).shouldProcess(any(ErrorReport.class));
verify(listener).shouldAwaitUserConfirmation();
verify(channel).enqueue(any(Log.class), anyString());
verify(listener).getErrorAttachments(any(ErrorReport.class));
verifyNoMoreInteractions(listener);
}
use of com.microsoft.azure.mobile.crashes.ingestion.models.ManagedErrorLog in project mobile-center-sdk-android by Microsoft.
the class UncaughtExceptionHandlerTest method setUp.
@Before
public void setUp() {
Crashes.unsetInstance();
mockStatic(MobileCenterLog.class);
mockStatic(SystemClock.class);
mockStatic(StorageHelper.PreferencesStorage.class);
mockStatic(StorageHelper.InternalStorage.class);
mockStatic(ErrorLogHelper.class);
mockStatic(DeviceInfoHelper.class);
mockStatic(System.class);
when(StorageHelper.PreferencesStorage.getBoolean(KEY_ENABLED, true)).thenReturn(true);
when(StorageHelper.PreferencesStorage.getBoolean(CRASHES_ENABLED_KEY, true)).thenReturn(true);
/* Then simulate further changes to state. */
PowerMockito.doAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Throwable {
/* Whenever the new state is persisted, make further calls return the new state. */
boolean enabled = (Boolean) invocation.getArguments()[1];
Mockito.when(StorageHelper.PreferencesStorage.getBoolean(CRASHES_ENABLED_KEY, true)).thenReturn(enabled);
return null;
}
}).when(StorageHelper.PreferencesStorage.class);
StorageHelper.PreferencesStorage.putBoolean(eq(CRASHES_ENABLED_KEY), anyBoolean());
ManagedErrorLog errorLogMock = mock(ManagedErrorLog.class);
when(ErrorLogHelper.getErrorStorageDirectory()).thenReturn(new File("."));
when(ErrorLogHelper.createErrorLog(any(Context.class), any(Thread.class), any(Throwable.class), Matchers.<Map<Thread, StackTraceElement[]>>any(), anyLong(), anyBoolean())).thenReturn(errorLogMock);
when(errorLogMock.getId()).thenReturn(UUID.randomUUID());
mDefaultExceptionHandler = mock(Thread.UncaughtExceptionHandler.class);
Thread.setDefaultUncaughtExceptionHandler(mDefaultExceptionHandler);
mExceptionHandler = new UncaughtExceptionHandler();
MobileCenter.configure(mock(Application.class), "dummy");
}
use of com.microsoft.azure.mobile.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 absolute current time. Will be correlated to session and converted to relative later. */
errorLog.setToffset(System.currentTimeMillis());
/* Snapshot device properties. */
try {
errorLog.setDevice(DeviceInfoHelper.getDeviceInfo(context));
} catch (DeviceInfoHelper.DeviceInfoException e) {
MobileCenterLog.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);
/* Relative application launch time to error time. */
errorLog.setAppLaunchTOffset(SystemClock.elapsedRealtime() - 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.azure.mobile.crashes.ingestion.models.ManagedErrorLog in project mobile-center-sdk-android by Microsoft.
the class CrashesTest method crashInLastSession.
@Test
public void crashInLastSession() throws JSONException, IOException, ClassNotFoundException {
final int tOffset = 10;
final long appLaunchTOffset = 100L;
final ManagedErrorLog errorLog = new ManagedErrorLog();
errorLog.setId(UUIDUtils.randomUUID());
errorLog.setErrorThreadName(Thread.currentThread().getName());
errorLog.setToffset(tOffset);
errorLog.setAppLaunchTOffset(appLaunchTOffset);
errorLog.setDevice(mock(Device.class));
LogSerializer logSerializer = mock(LogSerializer.class);
when(logSerializer.deserializeLog(anyString())).thenReturn(errorLog);
final Throwable throwable = mock(Throwable.class);
final ErrorReport errorReport = ErrorLogHelper.getErrorReportFromErrorLog(errorLog, throwable);
/* This callback will be called after Crashes service is initialized. */
final ResultCallback<ErrorReport> callback = new ResultCallback<ErrorReport>() {
@Override
public void onResult(ErrorReport data) {
assertNotNull(data);
assertEquals(errorReport, data);
}
};
mockStatic(ErrorLogHelper.class);
File lastErrorLogFile = errorStorageDirectory.newFile("last-error-log.json");
when(ErrorLogHelper.getLastErrorLogFile()).thenReturn(lastErrorLogFile);
when(ErrorLogHelper.getStoredThrowableFile(any(UUID.class))).thenReturn(errorStorageDirectory.newFile());
when(ErrorLogHelper.getErrorReportFromErrorLog(errorLog, throwable)).thenReturn(errorReport);
when(ErrorLogHelper.getStoredErrorLogFiles()).thenReturn(new File[] { lastErrorLogFile });
when(StorageHelper.InternalStorage.read(any(File.class))).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
/* Call twice for multiple listeners during initialize. */
Crashes.getLastSessionCrashReport(callback);
Crashes.getLastSessionCrashReport(callback);
return "";
}
});
when(StorageHelper.InternalStorage.readObject(any(File.class))).thenReturn(throwable);
Crashes.getInstance().setLogSerializer(logSerializer);
assertFalse(Crashes.hasCrashedInLastSession());
/*
* Last session error is only fetched upon initialization: enabled and channel ready.
* Here the service is enabled by default but we are waiting channel to be ready, simulate that.
*/
assertTrue(Crashes.isEnabled());
Crashes.getInstance().onStarted(mock(Context.class), "", mock(Channel.class));
assertTrue(Crashes.hasCrashedInLastSession());
Crashes.getLastSessionCrashReport(new ResultCallback<ErrorReport>() {
@Override
public void onResult(ErrorReport errorReport) {
assertNotNull(errorReport);
assertEquals(errorLog.getId().toString(), errorReport.getId());
assertEquals(errorLog.getErrorThreadName(), errorReport.getThreadName());
assertEquals(new Date(tOffset - appLaunchTOffset), errorReport.getAppStartTime());
assertEquals(new Date(tOffset), errorReport.getAppErrorTime());
assertNotNull(errorReport.getDevice());
assertEquals(throwable, errorReport.getThrowable());
}
});
}
Aggregations