Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
romtsn committed Mar 21, 2024
1 parent f72e45f commit 545712c
Show file tree
Hide file tree
Showing 10 changed files with 76 additions and 41 deletions.
1 change: 1 addition & 0 deletions sentry-android-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ dependencies {
testImplementation(projects.sentryTestSupport)
testImplementation(projects.sentryAndroidFragment)
testImplementation(projects.sentryAndroidTimber)
testImplementation(projects.sentryAndroidReplay)
testImplementation(projects.sentryComposeHelper)
testImplementation(projects.sentryAndroidNdk)
testRuntimeOnly(Config.Libs.composeUi)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,44 +227,43 @@ private static void deduplicateIntegrations(
}

public static synchronized void startReplay() {
performReplayAction(
"starting",
(replay) -> {
replay.start();
});
if (!ensureReplayIntegration("starting")) {
return;
}
final @NotNull IHub hub = Sentry.getCurrentHub();
ReplayIntegrationKt.getReplayIntegration(hub).start();
}

public static synchronized void stopReplay() {
performReplayAction(
"stopping",
(replay) -> {
replay.stop();
});
if (!ensureReplayIntegration("stopping")) {
return;
}
final @NotNull IHub hub = Sentry.getCurrentHub();
ReplayIntegrationKt.getReplayIntegration(hub).stop();
}

public static synchronized void resumeReplay() {
performReplayAction(
"resuming",
(replay) -> {
replay.resume();
});
if (!ensureReplayIntegration("resuming")) {
return;
}
final @NotNull IHub hub = Sentry.getCurrentHub();
ReplayIntegrationKt.getReplayIntegration(hub).resume();
}

public static synchronized void pauseReplay() {
performReplayAction(
"pausing",
(replay) -> {
replay.pause();
});
if (!ensureReplayIntegration("pausing")) {
return;
}
final @NotNull IHub hub = Sentry.getCurrentHub();
ReplayIntegrationKt.getReplayIntegration(hub).pause();
}

private static void performReplayAction(
final @NotNull String actionName, final @NotNull ReplayCallable action) {
private static boolean ensureReplayIntegration(final @NotNull String actionName) {
final @NotNull IHub hub = Sentry.getCurrentHub();
if (isReplayAvailable) {
final ReplayIntegration replay = ReplayIntegrationKt.getReplayIntegration(hub);
if (replay != null) {
action.call(replay);
return true;
} else {
hub.getOptions()
.getLogger()
Expand All @@ -279,9 +278,6 @@ private static void performReplayAction(
SentryLevel.INFO,
"Session Replay wasn't found on classpath, not " + actionName + " the replay");
}
}

private interface ReplayCallable {
void call(final @NotNull ReplayIntegration replay);
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import io.sentry.android.core.internal.gestures.AndroidViewGestureTargetLocator
import io.sentry.android.core.internal.modules.AssetsModulesLoader
import io.sentry.android.core.internal.util.AndroidMainThreadChecker
import io.sentry.android.fragment.FragmentLifecycleIntegration
import io.sentry.android.replay.ReplayIntegration
import io.sentry.android.timber.SentryTimberIntegration
import io.sentry.cache.PersistingOptionsObserver
import io.sentry.cache.PersistingScopeObserver
Expand Down Expand Up @@ -83,6 +84,7 @@ class AndroidOptionsInitializerTest {
loadClass,
activityFramesTracker,
false,
false,
false
)

Expand All @@ -99,7 +101,8 @@ class AndroidOptionsInitializerTest {
minApi: Int = Build.VERSION_CODES.KITKAT,
classesToLoad: List<String> = emptyList(),
isFragmentAvailable: Boolean = false,
isTimberAvailable: Boolean = false
isTimberAvailable: Boolean = false,
isReplayAvailable: Boolean = false
) {
mockContext = ContextUtilsTestHelper.mockMetaData(
mockContext = ContextUtilsTestHelper.createMockContext(hasAppContext = true),
Expand All @@ -126,7 +129,8 @@ class AndroidOptionsInitializerTest {
loadClass,
activityFramesTracker,
isFragmentAvailable,
isTimberAvailable
isTimberAvailable,
isReplayAvailable
)

AndroidOptionsInitializer.initializeIntegrationsAndProcessors(
Expand Down Expand Up @@ -478,6 +482,24 @@ class AndroidOptionsInitializerTest {
assertNull(actual)
}

@Test
fun `ReplayIntegration added to the integration list if available on classpath`() {
fixture.initSutWithClassLoader(isReplayAvailable = true)

val actual =
fixture.sentryOptions.integrations.firstOrNull { it is ReplayIntegration }
assertNotNull(actual)
}

@Test
fun `ReplayIntegration won't be enabled, it throws class not found`() {
fixture.initSutWithClassLoader(isReplayAvailable = false)

val actual =
fixture.sentryOptions.integrations.firstOrNull { it is ReplayIntegration }
assertNull(actual)
}

@Test
fun `AndroidEnvelopeCache is set to options`() {
fixture.initSut()
Expand Down Expand Up @@ -634,6 +656,7 @@ class AndroidOptionsInitializerTest {
mock(),
mock(),
false,
false,
false
)
verify(mockOptions, never()).outboxPath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class AndroidProfilerTest {
loadClass,
activityFramesTracker,
false,
false,
false
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ class AndroidTransactionProfilerTest {
loadClass,
activityFramesTracker,
false,
false,
false
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ class LifecycleWatcherTest {
fun `When session tracking is disabled, do not end session`() {
val watcher = fixture.getSUT(enableAutoSessionTracking = false, enableAppLifecycleBreadcrumbs = false)
watcher.onStop(fixture.ownerMock)
assertNull(watcher.timerTask)
verify(fixture.hub, never()).endSession()
}

Expand Down Expand Up @@ -167,7 +166,6 @@ class LifecycleWatcherTest {
fun `When session tracking is disabled, do not add breadcrumb on stop`() {
val watcher = fixture.getSUT(enableAutoSessionTracking = false, enableAppLifecycleBreadcrumbs = false)
watcher.onStop(fixture.ownerMock)
assertNull(watcher.timerTask)
verify(fixture.hub, never()).addBreadcrumb(any<Breadcrumb>())
}

Expand Down Expand Up @@ -219,12 +217,6 @@ class LifecycleWatcherTest {
assertNotNull(watcher.timer)
}

@Test
fun `timer is not created if session tracking is disabled`() {
val watcher = fixture.getSUT(enableAutoSessionTracking = false, enableAppLifecycleBreadcrumbs = false)
assertNull(watcher.timer)
}

@Test
fun `if the hub has already a fresh session running, don't start new one`() {
val watcher = fixture.getSUT(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import io.sentry.UncaughtExceptionHandlerIntegration
import io.sentry.android.core.cache.AndroidEnvelopeCache
import io.sentry.android.core.performance.AppStartMetrics
import io.sentry.android.fragment.FragmentLifecycleIntegration
import io.sentry.android.replay.ReplayIntegration
import io.sentry.android.replay.getReplayIntegration
import io.sentry.android.timber.SentryTimberIntegration
import io.sentry.cache.IEnvelopeCache
import io.sentry.cache.PersistingOptionsObserver
Expand Down Expand Up @@ -313,12 +315,26 @@ class SentryAndroidTest {
}
}

@Test
@Config(sdk = [26])
fun `init starts session replay if app is in foreground`() {
initSentryWithForegroundImportance(true) { _ ->
assertTrue(Sentry.getCurrentHub().getReplayIntegration()!!.isRecording())
}
}

@Test
@Config(sdk = [26])
fun `init does not start session replay if the app is in background`() {
initSentryWithForegroundImportance(false) { _ ->
assertFalse(Sentry.getCurrentHub().getReplayIntegration()!!.isRecording())
}
}

private fun initSentryWithForegroundImportance(
inForeground: Boolean,
callback: (session: Session?) -> Unit
) {
val context = ContextUtilsTestHelper.createMockContext()

Mockito.mockStatic(ContextUtils::class.java).use { mockedContextUtils ->
mockedContextUtils.`when`<Any> { ContextUtils.isForegroundImportance() }
.thenReturn(inForeground)
Expand Down Expand Up @@ -412,7 +428,7 @@ class SentryAndroidTest {
fixture.initSut(context = mock<Application>()) { options ->
optionsRef = options
options.dsn = "https://key@sentry.io/123"
assertEquals(19, options.integrations.size)
assertEquals(20, options.integrations.size)
options.integrations.removeAll {
it is UncaughtExceptionHandlerIntegration ||
it is ShutdownHookIntegration ||
Expand All @@ -431,7 +447,8 @@ class SentryAndroidTest {
it is SystemEventsBreadcrumbsIntegration ||
it is NetworkBreadcrumbsIntegration ||
it is TempSensorBreadcrumbsIntegration ||
it is PhoneStateBreadcrumbsIntegration
it is PhoneStateBreadcrumbsIntegration ||
it is ReplayIntegration
}
}
assertEquals(0, optionsRef.integrations.size)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ class SentryInitProviderTest {
loadClass,
activityFramesTracker,
false,
false,
false
)

Expand Down
1 change: 1 addition & 0 deletions sentry-android-replay/api/sentry-android-replay.api
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public final class io/sentry/android/replay/ReplayIntegration : io/sentry/Integr
public static final field VIDEO_SEGMENT_DURATION J
public fun <init> (Landroid/content/Context;Lio/sentry/transport/ICurrentDateProvider;)V
public fun close ()V
public final fun isRecording ()Z
public fun onScreenshotRecorded (Landroid/graphics/Bitmap;)V
public final fun pause ()V
public fun register (Lio/sentry/IHub;Lio/sentry/SentryOptions;)V
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ class ReplayIntegration(
isEnabled.set(true)
}

fun isRecording() = isRecording.get()

fun start() {
if (!isEnabled.get()) {
options.logger.log(
Expand Down

0 comments on commit 545712c

Please sign in to comment.