package com.amazonaws.mobileconnectors.pinpoint.analytics;
import static com.amazonaws.mobileconnectors.pinpoint.analytics.SessionClient.*;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.amazonaws.mobileconnectors.pinpoint.PinpointConfiguration;
import com.amazonaws.mobileconnectors.pinpoint.PinpointManager;
import com.amazonaws.mobileconnectors.pinpoint.internal.core.PinpointContext;
import com.amazonaws.mobileconnectors.pinpoint.internal.core.configuration.AndroidPreferencesConfiguration;
import com.amazonaws.mobileconnectors.pinpoint.internal.core.system.MockSystem;
import com.amazonaws.mobileconnectors.pinpoint.analytics.utils.AnalyticsContextBuilder;
import com.amazonaws.mobileconnectors.pinpoint.targeting.TargetingClient;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class SessionClientTest extends MobileAnalyticsTestBase {
private static final String UNIQUE_ID = "deadbeef-DEADBEEF-deadbeef-DEADBEEF";
private static final String SDK_NAME = "AppIntelligenceSDK-Analytics";
private static final String SDK_VERSION = "test";
private PinpointContext mockPinpointContext;
@Mock
private AnalyticsClient mockAnalyticsClient;
@Mock
private TargetingClient mockTargetingClient;
@Mock
private AndroidPreferencesConfiguration mockConfiguration;
@Mock
private PinpointConfiguration mockPinpointConfiguration;
private SessionClient target;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
when(mockConfiguration.optLong(eq(RESTART_DELAY_CONFIG_KEY),
eq(DEFAULT_RESTART_DELAY))).thenReturn(300l);
when(mockConfiguration.optLong(eq(RESUME_DELAY_CONFIG_KEY),
eq(DEFAULT_RESUME_DELAY))).thenReturn(100l);
this.mockPinpointContext = new AnalyticsContextBuilder()
.withSdkInfo(SDK_NAME, SDK_VERSION)
.withUniqueIdValue(UNIQUE_ID)
.withConfiguration(mockConfiguration)
.withContext(Robolectric.application.getApplicationContext())
.withSystem(new MockSystem("SESSION_CLIENT.test"))
.build();
when(mockPinpointContext.getAnalyticsClient()).thenReturn(mockAnalyticsClient);
when(mockPinpointContext.getTargetingClient()).thenReturn(mockTargetingClient);
when(mockPinpointContext.getConfiguration()).thenReturn(mockConfiguration);
when(mockPinpointContext.getPinpointConfiguration()).thenReturn(mockPinpointConfiguration);
target = new SessionClient(mockPinpointContext);
System.out.print(target.toString());
}
@After
public void teardown() {
target.stopSession();
}
@Test(expected = NullPointerException.class)
public void constructor_NullContext_ThrowsNullPointer() {
target = new SessionClient(null);
}
// ~ START SESSION
// =========================================================================
// ~\\
//
@Test
public void startSession_sessionIsActive_SetsNewSession() {
target.startSession();
String firstSessionId = target.getSession().getSessionID();
long firstStartTime = target.getSession().getStartTime();
verify(mockAnalyticsClient, times(1)).setSessionId(firstSessionId);
verify(mockAnalyticsClient, times(1)).setSessionStartTime(firstStartTime);
try {
Thread.sleep(target.getRestartDelay() + 50l);
long pTime = target.getSession().getStartTime();
target.startSession();
System.out.print(target.getRestartDelay() + "");
assertTrue(System.currentTimeMillis() - pTime > target.getRestartDelay());
String secondSessionId = target.getSession().getSessionID();
long secondStartTime = target.getSession().getStartTime();
assertNotEquals(firstSessionId, secondSessionId);
assertNotEquals(firstStartTime, secondStartTime);
verify(mockAnalyticsClient, times(1)).setSessionId(secondSessionId);
verify(mockAnalyticsClient, times(1)).setSessionStartTime(secondStartTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test
public void
startSession_sessionIsActive_startsNewSession() {
target = new SessionClient(mockPinpointContext);
target.startSession();
try {
Session session = target.getSession();
assertThat(session.isPaused(), is(false));
Thread.sleep(target.getRestartDelay() + 50l);
target.startSession();
// assert the old session was paused and the a new session is now
// active
assertThat(session.isPaused(), is(true));
assertThat(target.getSession(), is(not(session)));
verify(mockAnalyticsClient, times(2)).createEvent(
eq(SESSION_START_EVENT_TYPE));
verify(mockAnalyticsClient, times(1)).createEvent(
eq(SESSION_STOP_EVENT_TYPE), any(Long.class),
any(Long.class), any(Long.class));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Test
public void startSession_firesStartEvent() {
target.startSession();
verify(mockAnalyticsClient, times(1)).createEvent(
eq(SESSION_START_EVENT_TYPE));
}
@Test
public void startSession_stateChangedToActive() {
target.startSession();
assertEquals(target.getSessionState(),
SessionState.ACTIVE);
}
@Test
public void startSession_sessionIsPaused_firesStopEvent_firesStartEvent()
throws InterruptedException {
target.startSession();
Thread.sleep(50);
target.pauseSession();
target.startSession();
verify(mockAnalyticsClient, times(1)).createEvent(
eq(SESSION_PAUSE_EVENT_TYPE), any(Long.class),
any(Long.class),
any(Long.class));
verify(mockAnalyticsClient, times(1)).createEvent(
eq(SESSION_STOP_EVENT_TYPE), any(Long.class), any(Long.class),
any(Long.class));
verify(mockAnalyticsClient, times(2)).createEvent(
eq(SESSION_START_EVENT_TYPE));
}
@Test
public void startSession_sessionIsPaused_stateChangedToActive() {
target.startSession();
target.pauseSession();
target.startSession();
assertEquals(target.getSessionState(),
SessionState.ACTIVE);
}
@Test
public void
startSession_previousPausedSessionColdStart_fireStopEvent_firesStartEvent()
throws InterruptedException {
Session mockSession = new Session("BEEFY_MKBEEF_CAKES", "0", "12345");
// initialize session client with a pending session that needs to be closed
//Save session to user defaults
mockPinpointContext.getSystem().getPreferences().putString(SHARED_PREFS_SESSION_KEY, mockSession.toString());
SessionClient coldStartTarget = new
SessionClient(mockPinpointContext);
assertThat(coldStartTarget.getSession(), is(notNullValue()));
assertThat(coldStartTarget.getSessionState(), is(SessionState.PAUSED));
// starting a session should close the pending one
coldStartTarget.startSession();
verify(mockAnalyticsClient, times(1)).createEvent(
SESSION_STOP_EVENT_TYPE, mockSession.getStartTime(),
mockSession.getStopTime(), mockSession.getSessionDuration().longValue());
verify(mockAnalyticsClient, times(1)).createEvent(
eq(SESSION_STOP_EVENT_TYPE), any(Long.class), any(Long.class),
any(Long.class));
}
@Test
public void stopSession_sessionIsInactive_doesNotFireStopEvent() {
target.stopSession();
target.startSession();
target.stopSession();
target.stopSession();
target.stopSession();
verify(mockAnalyticsClient, times(1)).createEvent(
eq(SESSION_STOP_EVENT_TYPE), any(Long.class), any(Long.class),
any(Long.class));
}
@Test
public void stopSession_getStopTime() {
target.startSession();
Session originalSession = target.getSession();
target.stopSession();
assertTrue(System.currentTimeMillis() - originalSession.getStopTime() < 100);
}
@Test
public void stopSession_multipleStops_stopTimeNotChanged() throws
InterruptedException {
target.startSession();
Session originalSession = target.getSession();
target.stopSession();
long originalStopTime = originalSession.getStopTime();
Thread.sleep(500);
target.stopSession();
assertTrue(originalStopTime == originalSession.getStopTime());
}
@Test
public void stopSession_sessionIsActive_firesStopEvent() throws
InterruptedException {
target.startSession();
Thread.sleep(50);
long startTime = target.getSession().getStartTime();
target.stopSession();
// After this call session is null, so we cannot get the stop/duration
// time
verify(mockAnalyticsClient, times(1)).createEvent(
eq(SESSION_STOP_EVENT_TYPE), eq(startTime), any(Long.class),
any(Long.class));
assertTrue(target.getSessionState().equals(SessionState.INACTIVE));
}
@Test
public void stopSession_sessionIsActive_pausesOldSession() {
target.startSession();
Session session = target.getSession();
assertThat(session.isPaused(), is(false));
target.stopSession();
assertThat(session.isPaused(), is(true));
assertThat(target.getSession(), is(nullValue()));
}
@Test
public void stopSession_sessionIsActive_stateChangedToInactive() {
target.startSession();
target.stopSession();
assertEquals(target.getSessionState(),
SessionState.INACTIVE);
}
@Test
public void stopSession_sessionIsPaused_firesStopEvent() throws
InterruptedException {
target.startSession();
Thread.sleep(50);
target.pauseSession();
Session originalSession = target.getSession();
target.stopSession();
verify(mockAnalyticsClient, times(1)).createEvent(
SESSION_STOP_EVENT_TYPE, originalSession.getStartTime(),
originalSession.getStopTime(),
originalSession.getSessionDuration().longValue());
}
@Test
public void stopSession_sessionIsPaused_stateChangedToInactive() {
target.startSession();
target.pauseSession();
target.stopSession();
assertEquals(target.getSessionState(),
SessionState.INACTIVE);
}
@Test
public void pauseSession_sessionIsActive_firesPauseEvent() {
target.startSession();
target.pauseSession();
verify(mockAnalyticsClient, times(1)).createEvent(
eq(SESSION_PAUSE_EVENT_TYPE), any(Long.class),
any(Long.class),
any(Long.class));
}
@Test
public void pauseSession_sessionIsActive_stateChangedToPaused() {
target.startSession();
target.pauseSession();
assertEquals(target.getSessionState(),
SessionState.PAUSED);
}
@Test
public void pauseSession_sessionIsInactive_firesNoEvent() {
target.pauseSession();
target.pauseSession();
target.pauseSession();
verify(mockAnalyticsClient, times(0)).createEvent(any(String.class));
verify(mockAnalyticsClient, times(0)).createEvent(
any(String.class), any(Long.class),
any(Long.class),
any(Long.class));
}
@Test
public void pauseSession_sessionIsInactive_stateIsNotChanged() {
target.pauseSession();
target.pauseSession();
target.pauseSession();
assertEquals(target.getSessionState(),
SessionState.INACTIVE);
}
@Test
public void pauseSession_sessionIsPaused_doesNotFirePauseEvent() {
target.startSession();
target.pauseSession();
target.pauseSession();
target.pauseSession();
verify(mockAnalyticsClient, times(1)).createEvent(
eq(SESSION_PAUSE_EVENT_TYPE), any(Long.class),
any(Long.class),
any(Long.class));
}
@Test
public void resumeSession_sessionIsActive_doesNotFireResumeEvent() {
target.startSession();
target.resumeSession();
target.resumeSession();
target.resumeSession();
verify(mockAnalyticsClient, times(0)).createEvent(
eq(SESSION_RESUME_EVENT_TYPE), any(Long.class),
any(Long.class),
any(Long.class));
}
@Test
public void resumeSession_sessionIsInactive_firesBlankResumeEvent() {
target.resumeSession();
target.resumeSession();
target.resumeSession();
verify(mockAnalyticsClient, times(3)).createEvent(
eq(SESSION_RESUME_EVENT_TYPE));
}
@Test
public void resumeSession_sessionIsInactive_stateIsNotChanged() {
target.resumeSession();
assertEquals(target.getSessionState(),
SessionState.INACTIVE);
}
@Test
public void
resumeSession_sessionIsPaused_firesResumeEvent_ifWithinTimeInterval() {
target.startSession();
target.pauseSession();
long pTime = target.getSession().getStopTime();
target.resumeSession();
assertTrue(System.currentTimeMillis() - pTime < target.getResumeDelay());
verify(mockAnalyticsClient, times(1)).createEvent(
SESSION_RESUME_EVENT_TYPE);
}
@Test
public void
resumeSession_sessionIsPaused_stateIsChanged_ifWithinTimeInterval() {
target.startSession();
target.pauseSession();
long pTime = target.getSession().getStopTime();
target.resumeSession();
assertTrue(System.currentTimeMillis() - pTime < target.getResumeDelay());
assertEquals(target.getSessionState(),
SessionState.ACTIVE);
}
@Test
public void
resumeSession_sessionIsPaused_doesNotStartNewSession_ifWithinTimeInterval() {
target.startSession();
target.pauseSession();
long pTime = target.getSession().getStopTime();
target.resumeSession();
assertTrue(System.currentTimeMillis() - pTime < target.getResumeDelay());
verify(mockAnalyticsClient, times(1)).createEvent(
eq(SESSION_START_EVENT_TYPE));
}
}