use of com.microsoft.appcenter.ingestion.models.Log in project mobile-center-sdk-android by Microsoft.
the class SessionTrackerTest method pastSessions.
@Test
public void pastSessions() {
/* Get a current session. */
UUID firstSid, currentSid;
long firstSessionTime = mMockTime;
{
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
assertNotNull(log.getSid());
currentSid = firstSid = log.getSid();
}
/* Verify session reused for second log. */
{
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
assertEquals(currentSid, log.getSid());
}
/* Past log: correlation will fail and thus use no session. */
{
Log log = newEvent();
log.setTimestamp(new Date(123L));
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
assertNull(log.getSid());
}
/* No usage from background for a long time, should produce a new session but we'll correlate, correlation does not trigger a new session. */
{
spendTime(30000);
Log log = newEvent();
log.setTimestamp(new Date(firstSessionTime + 1));
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
assertEquals(currentSid, log.getSid());
Set<String> sessions = StorageHelper.PreferencesStorage.getStringSet("sessions");
assertNotNull(sessions);
assertEquals(1, sessions.size());
}
/* Trigger a second session. */
{
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
assertNotEquals(currentSid, log.getSid());
Set<String> sessions = StorageHelper.PreferencesStorage.getStringSet("sessions");
assertNotNull(sessions);
assertEquals(2, sessions.size());
}
/* Correlate log to previous. */
{
spendTime(30000);
Log log = newEvent();
log.setTimestamp(new Date(firstSessionTime + 1));
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
assertEquals(firstSid, log.getSid());
Set<String> sessions = StorageHelper.PreferencesStorage.getStringSet("sessions");
assertNotNull(sessions);
assertEquals(2, sessions.size());
}
/* Re-test with persistence now, no current session but same correlation will work and no session will be triggered on the new instance. */
mSessionTracker = new SessionTracker(mChannel, TEST_GROUP);
{
Log log = newEvent();
log.setTimestamp(new Date(firstSessionTime + 1));
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
assertEquals(firstSid, log.getSid());
Set<String> sessions = StorageHelper.PreferencesStorage.getStringSet("sessions");
assertNotNull(sessions);
assertEquals(2, sessions.size());
}
/* Failed correlation without an active session will not start a new session. */
{
Log log = newEvent();
log.setTimestamp(new Date(1));
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
assertNull(log.getSid());
Set<String> sessions = StorageHelper.PreferencesStorage.getStringSet("sessions");
assertNotNull(sessions);
assertEquals(2, sessions.size());
}
/* Clear sessions. */
mSessionTracker.clearSessions();
verifyStatic();
StorageHelper.PreferencesStorage.remove("sessions");
}
use of com.microsoft.appcenter.ingestion.models.Log in project mobile-center-sdk-android by Microsoft.
the class SessionTrackerTest method sdkConfiguredBetweenPauseAndResume.
@Test
public void sdkConfiguredBetweenPauseAndResume() {
/* Pause application before we saw the first resume event (integration problem). We are handling that gracefully though. */
mSessionTracker.onActivityPaused();
/* Application is in background, send a log, verify decoration. */
UUID expectedSid;
StartSessionLog expectedStartSessionLog = new StartSessionLog();
{
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertNotNull(log.getSid());
expectedSid = log.getSid();
expectedStartSessionLog.setSid(expectedSid);
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* Verify session reused for second log. */
{
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertEquals(expectedSid, log.getSid());
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* No usage from background for a long time: new session. */
{
spendTime(30000);
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertNotEquals(expectedSid, log.getSid());
expectedSid = log.getSid();
expectedStartSessionLog.setSid(expectedSid);
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* App comes to foreground and sends a log, we were in background for a long time but we sent a log recently, still session. */
{
mSessionTracker.onActivityResumed();
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertEquals(expectedSid, log.getSid());
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* We are in foreground, even after timeout a log is still in session. */
{
spendTime(30000);
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertEquals(expectedSid, log.getSid());
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
}
use of com.microsoft.appcenter.ingestion.models.Log in project mobile-center-sdk-android by Microsoft.
the class SessionTrackerTest method longSessionStartingFromBackground.
@Test
public void longSessionStartingFromBackground() {
/* Application is in background, send a log, verify decoration. */
UUID firstSid;
long firstSessionTime = mMockTime;
UUID expectedSid;
StartSessionLog expectedStartSessionLog = new StartSessionLog();
{
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertNotNull(log.getSid());
firstSid = expectedSid = log.getSid();
expectedStartSessionLog.setSid(expectedSid);
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* Verify session reused for second log. */
{
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertEquals(expectedSid, log.getSid());
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* No usage from background for a long time: new session. */
{
spendTime(30000);
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertNotEquals(expectedSid, log.getSid());
expectedSid = log.getSid();
expectedStartSessionLog.setSid(expectedSid);
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* App comes to foreground and sends a log, still session. */
{
mSessionTracker.onActivityResumed();
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertEquals(expectedSid, log.getSid());
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* We are in foreground, even after timeout a log is still in session. */
{
spendTime(30000);
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertEquals(expectedSid, log.getSid());
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* Switch to another activity and send a log, still session. */
{
spendTime(2);
mSessionTracker.onActivityPaused();
spendTime(2);
mSessionTracker.onActivityResumed();
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertEquals(expectedSid, log.getSid());
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* We are in foreground, even after timeout a log is still in session. */
{
spendTime(30000);
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertEquals(expectedSid, log.getSid());
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* Background for a short time and send log: still in session. */
{
spendTime(2);
mSessionTracker.onActivityPaused();
spendTime(2);
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertEquals(expectedSid, log.getSid());
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* Background for a long time but correlating a log to first session: should not trigger new session. */
{
Log log = newEvent();
log.setTimestamp(new Date(firstSessionTime + 20));
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertEquals(firstSid, log.getSid());
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* Background for a long time and coming back to foreground: new session. */
{
spendTime(30000);
mSessionTracker.onActivityResumed();
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertNotEquals(expectedSid, log.getSid());
expectedSid = log.getSid();
expectedStartSessionLog.setSid(expectedSid);
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
/* Background for a long time sending a log: new session. */
{
mSessionTracker.onActivityPaused();
spendTime(30000);
Log log = newEvent();
mSessionTracker.onEnqueuingLog(log, TEST_GROUP);
mSessionTracker.onEnqueuingLog(expectedStartSessionLog, TEST_GROUP);
assertNotEquals(expectedSid, log.getSid());
expectedSid = log.getSid();
expectedStartSessionLog.setSid(expectedSid);
verify(mChannel).enqueue(expectedStartSessionLog, TEST_GROUP);
}
}
use of com.microsoft.appcenter.ingestion.models.Log in project mobile-center-sdk-android by Microsoft.
the class SessionTrackerTest method ignoreStartService.
@Test
public void ignoreStartService() {
Log startServiceLog = spy(new StartServiceLog());
mSessionTracker.onEnqueuingLog(startServiceLog, TEST_GROUP);
verify(mChannel, never()).enqueue(any(Log.class), anyString());
verify(startServiceLog, never()).setSid(any(UUID.class));
}
use of com.microsoft.appcenter.ingestion.models.Log in project mobile-center-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());
}
Aggregations