Skip to content
This repository has been archived by the owner on Aug 30, 2023. It is now read-only.

Commit

Permalink
fix: initing SDK on AttachBaseContext (#409)
Browse files Browse the repository at this point in the history
  • Loading branch information
marandaneto authored May 14, 2020
1 parent a543634 commit 07d9eaa
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@ static void init(
@NotNull Context context,
final @NotNull ILogger logger) {
Objects.requireNonNull(context, "The context is required.");
context =
Objects.requireNonNull(
context.getApplicationContext(), "The application context is required.");

// it returns null if ContextImpl, so let's check for nullability
if (context.getApplicationContext() != null) {
context = context.getApplicationContext();
}

Objects.requireNonNull(options, "The options object is required.");
Objects.requireNonNull(logger, "The ILogger object is required.");

Expand Down Expand Up @@ -113,7 +116,9 @@ private static void installDefaultIntegrations(

options.addIntegration(new AnrIntegration());
options.addIntegration(new AppLifecycleIntegration());
if (context instanceof Application) { // just a guard check, it should be an Application

// registerActivityLifecycleCallbacks is only available if Context is an AppContext
if (context instanceof Application) {
options.addIntegration(new ActivityBreadcrumbsIntegration((Application) context));
} else {
options
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,26 @@ public void register(final @NotNull IHub hub, final @NotNull SentryOptions optio
this.options.isEnableAppComponentBreadcrumbs());

if (this.options.isEnableAppComponentBreadcrumbs()) {
context.registerComponentCallbacks(this);
options.getLogger().log(SentryLevel.DEBUG, "AppComponentsBreadcrumbsIntegration installed.");
try {
// if its a ContextImpl, registerComponentCallbacks can't be used
context.registerComponentCallbacks(this);
options
.getLogger()
.log(SentryLevel.DEBUG, "AppComponentsBreadcrumbsIntegration installed.");
} catch (Exception e) {
this.options.setEnableAppComponentBreadcrumbs(false);
options.getLogger().log(SentryLevel.INFO, e, "ComponentCallbacks2 is not available.");
}
}
}

@Override
public void close() throws IOException {
context.unregisterComponentCallbacks(this);
try {
// if its a ContextImpl, unregisterComponentCallbacks can't be used
context.unregisterComponentCallbacks(this);
} catch (Exception ignored) {
}

if (options != null) {
options.getLogger().log(SentryLevel.DEBUG, "AppComponentsBreadcrumbsIntegration removed.");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package io.sentry.android.core

import android.app.Application
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.whenever
import io.sentry.core.MainEventProcessor
import io.sentry.core.SentryOptions
Expand All @@ -12,6 +14,7 @@ import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import kotlin.test.assertTrue
import org.junit.runner.RunWith

Expand Down Expand Up @@ -207,6 +210,38 @@ class AndroidOptionsInitializerTest {
assertNotNull(actual)
}

@Test
fun `When given Context returns a non null ApplicationContext, uses it`() {
val sentryOptions = SentryAndroidOptions()
val mockApp = mock<Application>()
val mockContext = mock<Context>()
whenever(mockContext.applicationContext).thenReturn(mockApp)

AndroidOptionsInitializer.init(sentryOptions, mockContext)
assertNotNull(mockContext)
}

@Test
fun `When given Context returns a null ApplicationContext is null, keep given Context`() {
val sentryOptions = SentryAndroidOptions()
val mockContext = mock<Context>()
whenever(mockContext.applicationContext).thenReturn(null)

AndroidOptionsInitializer.init(sentryOptions, mockContext)
assertNotNull(mockContext)
}

@Test
fun `When given Context is not an Application class, do not add ActivityBreadcrumbsIntegration`() {
val sentryOptions = SentryAndroidOptions()
val mockContext = mock<Context>()
whenever(mockContext.applicationContext).thenReturn(null)

AndroidOptionsInitializer.init(sentryOptions, mockContext)
val actual = sentryOptions.integrations.firstOrNull { it is ActivityBreadcrumbsIntegration }
assertNull(actual)
}

private fun createMockContext(): Context {
val mockContext = ContextUtilsTest.createMockContext()
whenever(mockContext.cacheDir).thenReturn(file)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ import com.nhaarman.mockitokotlin2.check
import com.nhaarman.mockitokotlin2.mock
import com.nhaarman.mockitokotlin2.never
import com.nhaarman.mockitokotlin2.verify
import com.nhaarman.mockitokotlin2.whenever
import io.sentry.core.Breadcrumb
import io.sentry.core.IHub
import io.sentry.core.SentryLevel
import java.lang.NullPointerException
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
Expand All @@ -38,6 +41,17 @@ class AppComponentsBreadcrumbsIntegrationTest {
verify(fixture.context).registerComponentCallbacks(any())
}

@Test
fun `When app components breadcrumb is enabled, but ComponentCallbacks is not ready, do not throw`() {
val sut = fixture.getSut()
val options = SentryAndroidOptions()
val hub = mock<IHub>()
sut.register(hub, options)
whenever(fixture.context.registerComponentCallbacks(any())).thenThrow(NullPointerException())
sut.register(hub, options)
assertFalse(options.isEnableAppComponentBreadcrumbs)
}

@Test
fun `When app components breadcrumb is disabled, it doesn't register callback`() {
val sut = fixture.getSut()
Expand All @@ -59,6 +73,17 @@ class AppComponentsBreadcrumbsIntegrationTest {
verify(fixture.context).unregisterComponentCallbacks(any())
}

@Test
fun `When app components breadcrumb is closed, but ComponentCallbacks is not ready, do not throw`() {
val sut = fixture.getSut()
val options = SentryAndroidOptions()
val hub = mock<IHub>()
whenever(fixture.context.registerComponentCallbacks(any())).thenThrow(NullPointerException())
whenever(fixture.context.unregisterComponentCallbacks(any())).thenThrow(NullPointerException())
sut.register(hub, options)
sut.close()
}

@Test
fun `When low memory event, a breadcrumb with type, category and level should be set`() {
val sut = fixture.getSut()
Expand Down

0 comments on commit 07d9eaa

Please sign in to comment.