diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0ef78853f7..cb67a0fd59 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -50,6 +50,7 @@ espresso = "3.5.1" assertJ = "3.18.1" elmyr = "1.3.1" mockitoKotlin = "5.1.0" +mockitoAndroid = "5.12.0" kover = "0.7.6" kspTesting = "1.5.0" @@ -175,6 +176,7 @@ elmyrInject = { module = "com.github.xgouchet.Elmyr:inject", version.ref = "elmy elmyrJUnit4 = { module = "com.github.xgouchet.Elmyr:junit4", version.ref = "elmyr" } elmyrJUnit5 = { module = "com.github.xgouchet.Elmyr:junit5", version.ref = "elmyr" } elmyrJVM = { module = "com.github.xgouchet.Elmyr:jvm", version.ref = "elmyr" } +mockitoAndroid = { module = "org.mockito:mockito-android", version.ref = "mockitoAndroid" } mockitoKotlin = { module = "org.mockito.kotlin:mockito-kotlin", version.ref = "mockitoKotlin" } kotlinReflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } kover = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kover" } diff --git a/reliability/core-it/build.gradle.kts b/reliability/core-it/build.gradle.kts index 8c0b6ea5f7..5eac051db1 100644 --- a/reliability/core-it/build.gradle.kts +++ b/reliability/core-it/build.gradle.kts @@ -4,8 +4,10 @@ * Copyright 2016-Present Datadog, Inc. */ +import com.datadog.gradle.config.AndroidConfig import com.datadog.gradle.config.androidLibraryConfig import com.datadog.gradle.config.dependencyUpdateConfig +import com.datadog.gradle.config.java17 import com.datadog.gradle.config.javadocConfig import com.datadog.gradle.config.junitConfig import com.datadog.gradle.config.kotlinConfig @@ -26,10 +28,43 @@ plugins { android { namespace = "com.datadog.android.core.integration" + defaultConfig { + minSdk = AndroidConfig.MIN_SDK + multiDexEnabled = true + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + compileOptions { + java17() + } + + packaging { + resources { + excludes += listOf( + "META-INF/jvm.kotlin_module", + "META-INF/LICENSE.md", + "META-INF/LICENSE-notice.md" + ) + } + } - sourceSets.named("test") { - // Required because AGP doesn't support kotlin test fixtures :/ - java.srcDir("${project.rootDir.path}/dd-sdk-android-core/src/testFixtures/kotlin") + buildTypes { + getByName("release") { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + testProguardFile("test-proguard-rules.pro") + } + getByName("debug") { + isMinifyEnabled = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + testProguardFile("test-proguard-rules.pro") + } } } @@ -38,20 +73,27 @@ dependencies { implementation(libs.kotlin) // Testing - testImplementation(project(":tools:unit")) { + androidTestImplementation(project(":tools:unit")) { attributes { attribute( com.android.build.api.attributes.ProductFlavorAttr.of("platform"), - objects.named("jvm") + objects.named("art") ) } } - testImplementation(testFixtures(project(":dd-sdk-android-core"))) - testImplementation(libs.bundles.jUnit5) - testImplementation(libs.bundles.testTools) - testImplementation(libs.okHttp) - testImplementation(libs.gson) + androidTestImplementation(project(":reliability:stub-feature")) + androidTestImplementation(libs.assertJ) + androidTestImplementation(libs.mockitoAndroid) + androidTestImplementation(libs.bundles.integrationTests) + androidTestImplementation(libs.elmyrJVM) + androidTestImplementation(libs.okHttp) + androidTestImplementation(libs.okHttpMock) + androidTestImplementation(libs.gson) unmock(libs.robolectric) + if (project.hasProperty(com.datadog.gradle.Properties.USE_API21_JAVA_BACKPORT)) { + // this is needed to make AssertJ working on APIs <24 + androidTestImplementation(project(":tools:javabackport")) + } } unMock { diff --git a/reliability/core-it/proguard-rules.pro b/reliability/core-it/proguard-rules.pro new file mode 100644 index 0000000000..e3edb4ca58 --- /dev/null +++ b/reliability/core-it/proguard-rules.pro @@ -0,0 +1,7 @@ +# Needed to make sure we don't remove any test code +-dontshrink +#-dontoptimize +#-keepattributes *Annotation* + +-dontwarn kotlin.Experimental$Level +-dontwarn kotlin.Experimental diff --git a/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/SdkCoreTest.kt b/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/SdkCoreTest.kt new file mode 100644 index 0000000000..286194021d --- /dev/null +++ b/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/SdkCoreTest.kt @@ -0,0 +1,157 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.core.integration + +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.datadog.android.Datadog +import com.datadog.android.api.context.UserInfo +import com.datadog.android.api.feature.FeatureSdkCore +import com.datadog.android.api.feature.StorageBackedFeature +import com.datadog.android.api.feature.stub.StubStorageBackedFeature +import com.datadog.android.core.configuration.Configuration +import com.datadog.android.core.integration.tests.MockServerTest +import com.datadog.android.core.integration.tests.forge.factories.ConfigurationCoreForgeryFactory +import com.datadog.android.privacy.TrackingConsent +import com.datadog.tools.unit.ConditionWatcher +import com.datadog.tools.unit.forge.exhaustiveAttributes +import com.datadog.tools.unit.forge.useToolsFactories +import fr.xgouchet.elmyr.junit4.ForgeRule +import fr.xgouchet.elmyr.jvm.useJvmFactories +import org.assertj.core.api.Assertions.assertThat +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class SdkCoreTest : MockServerTest() { + + @get:Rule + var forge = ForgeRule() + + private var fakeUserId: String? = null + private var fakeUserName: String? = null + private var fakeUserEmail: String? = null + private var fakeUserAdditionalProperties: Map = emptyMap() + private lateinit var stubFeature: StorageBackedFeature + private lateinit var fakeFeatureName: String + + @Before + fun setUp() { + forge = forge.useJvmFactories().useToolsFactories().withFactory(ConfigurationCoreForgeryFactory()) + fakeFeatureName = forge.anAlphabeticalString() + stubFeature = StubStorageBackedFeature( + forge, + fakeFeatureName, + getMockServerWrapper().getServerUrl() + ) + fakeUserId = forge.aNullable { anHexadecimalString() } + fakeUserName = forge.aNullable { forge.aStringMatching("[A-Z][a-z]+ [A-Z]\\. [A-Z][a-z]+") } + fakeUserEmail = forge.aNullable { forge.aStringMatching("[a-z]+\\.[a-z]+@[a-z]+\\.[a-z]{3}") } + fakeUserAdditionalProperties = forge.exhaustiveAttributes(excludedKeys = setOf("id", "name", "email")) + } + + // region set UserInfo + + @Test + fun must_addUserInformationIntoEvents_when_setUserInformation() { + // Given + val configuration: Configuration = forge.getForgery() + val sdkCore = Datadog.initialize( + ApplicationProvider.getApplicationContext(), + configuration, + forge.aValueFrom(TrackingConsent::class.java) + ) + val featureSdkCore = sdkCore as? FeatureSdkCore + featureSdkCore?.registerFeature(stubFeature) + + // When + sdkCore?.setUserInfo(fakeUserId, fakeUserName, fakeUserEmail, fakeUserAdditionalProperties) + + // Then + ConditionWatcher { + var readUserInfo: UserInfo? = null + featureSdkCore?.getFeature(stubFeature.name)?.withWriteContext { datadogContext, _ -> + readUserInfo = datadogContext.userInfo + } + assertThat(readUserInfo?.id).isEqualTo(fakeUserId) + assertThat(readUserInfo?.name).isEqualTo(fakeUserName) + assertThat(readUserInfo?.email).isEqualTo(fakeUserEmail) + assertThat(readUserInfo?.additionalProperties) + .containsExactlyInAnyOrderEntriesOf(fakeUserAdditionalProperties) + true + }.doWait(timeoutMs = FINAL_WAIT_MS) + } + + // endregion + + // region add User Properties + + @Test + fun must_addUserExtraProperties_when_addUserProperties() { + // Given + val configuration: Configuration = forge.getForgery() + val sdkCore = Datadog.initialize( + ApplicationProvider.getApplicationContext(), + configuration, + forge.aValueFrom(TrackingConsent::class.java) + ) + val featureSdkCore = sdkCore as? FeatureSdkCore + featureSdkCore?.registerFeature(stubFeature) + sdkCore?.setUserInfo(fakeUserId, fakeUserName, fakeUserEmail, fakeUserAdditionalProperties) + val expectedUserExtraProperties = forge.exhaustiveAttributes() + + // When + sdkCore?.addUserProperties(expectedUserExtraProperties) + + // Then + ConditionWatcher { + var readUserInfo: UserInfo? = null + featureSdkCore?.getFeature(stubFeature.name)?.withWriteContext { datadogContext, _ -> + readUserInfo = datadogContext.userInfo + } + assertThat(readUserInfo?.id).isEqualTo(fakeUserId) + assertThat(readUserInfo?.name).isEqualTo(fakeUserName) + assertThat(readUserInfo?.email).isEqualTo(fakeUserEmail) + assertThat(readUserInfo?.additionalProperties) + .containsExactlyInAnyOrderEntriesOf(fakeUserAdditionalProperties + expectedUserExtraProperties) + true + }.doWait(timeoutMs = FINAL_WAIT_MS) + } + + // endregion + + // region set Tracking Consent + + @Test + fun must_updateTrackingConsent_when_setTrackingConsent() { + // Given + val configuration: Configuration = forge.getForgery() + val expectedTrackingConsent = forge.aValueFrom(TrackingConsent::class.java) + val sdkCore = Datadog.initialize( + ApplicationProvider.getApplicationContext(), + configuration, + forge.aValueFrom(TrackingConsent::class.java) + ) + val featureSdkCore = sdkCore as? FeatureSdkCore + featureSdkCore?.registerFeature(stubFeature) + + // When + sdkCore?.setTrackingConsent(expectedTrackingConsent) + + // Then + ConditionWatcher { + featureSdkCore?.getFeature(stubFeature.name)?.withWriteContext { datadogContext, _ -> + assertThat(datadogContext.trackingConsent).isEqualTo(expectedTrackingConsent) + } + true + }.doWait(timeoutMs = FINAL_WAIT_MS) + } + + // endregion +} diff --git a/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/BaseTest.kt b/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/BaseTest.kt new file mode 100644 index 0000000000..d697718e43 --- /dev/null +++ b/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/BaseTest.kt @@ -0,0 +1,17 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.core.integration.tests + +import java.util.concurrent.TimeUnit + +@Suppress("UtilityClassWithPublicConstructor") +abstract class BaseTest { + + companion object { + internal val FINAL_WAIT_MS = TimeUnit.SECONDS.toMillis(30) + } +} diff --git a/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/MockServerTest.kt b/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/MockServerTest.kt new file mode 100644 index 0000000000..85a4c3c5f9 --- /dev/null +++ b/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/MockServerTest.kt @@ -0,0 +1,40 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.core.integration.tests + +import com.datadog.android.core.integration.tests.utils.MockWebServerWrapper +import org.junit.AfterClass +import org.junit.BeforeClass +import java.util.concurrent.atomic.AtomicBoolean + +abstract class MockServerTest : BaseTest() { + + fun getMockServerWrapper(): MockWebServerWrapper { + return mockServerWrapper + } + + companion object { + private val mockServerStarted = AtomicBoolean(false) + protected val mockServerWrapper: MockWebServerWrapper = MockWebServerWrapper() + + @BeforeClass + @JvmStatic + fun setupTestSuite() { + if (mockServerStarted.compareAndSet(false, true)) { + mockServerWrapper.start() + } + } + + @AfterClass + @JvmStatic + fun tearDown() { + if (mockServerStarted.compareAndSet(true, false)) { + mockServerWrapper.shutdown() + } + } + } +} diff --git a/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/forge/factories/ConfigurationCoreForgeryFactory.kt b/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/forge/factories/ConfigurationCoreForgeryFactory.kt new file mode 100644 index 0000000000..200703f80a --- /dev/null +++ b/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/forge/factories/ConfigurationCoreForgeryFactory.kt @@ -0,0 +1,47 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.core.integration.tests.forge.factories + +import com.datadog.android.DatadogSite +import com.datadog.android._InternalProxy +import com.datadog.android.core.configuration.Configuration +import com.datadog.android.trace.TracingHeaderType +import fr.xgouchet.elmyr.Forge +import fr.xgouchet.elmyr.ForgeryFactory +import java.util.UUID + +internal class ConfigurationCoreForgeryFactory : + ForgeryFactory { + override fun getForgery(forge: Forge): Configuration { + return Configuration.Builder( + UUID.randomUUID().toString(), + forge.anHexadecimalString(), + forge.anHexadecimalString(), + forge.aNullable { + anAlphaNumericalString() + } + ) + .setUseDeveloperModeWhenDebuggable(forge.aBool()) + .setFirstPartyHostsWithHeaderType( + forge.aMap { + val fakeUrl = forge.aStringMatching("https://[a-z0-9]+\\.com") + fakeUrl to aList { + aValueFrom( + TracingHeaderType::class.java + ) + }.toSet() + } + ) + .apply { + _InternalProxy.allowClearTextHttp(this) + } + .setBatchSize(forge.getForgery()) + .setUploadFrequency(forge.getForgery()) + .useSite(forge.aValueFrom(DatadogSite::class.java)) + .build() + } +} diff --git a/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/utils/MockWebServerWrapper.kt b/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/utils/MockWebServerWrapper.kt new file mode 100644 index 0000000000..3f0f64a8d8 --- /dev/null +++ b/reliability/core-it/src/androidTest/kotlin/com/datadog/android/core/integration/tests/utils/MockWebServerWrapper.kt @@ -0,0 +1,29 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.core.integration.tests.utils + +import okhttp3.mockwebserver.MockWebServer + +class MockWebServerWrapper { + private val mockWebServer = MockWebServer() + + fun start() { + mockWebServer.start() + } + + fun shutdown() { + mockWebServer.shutdown() + } + + fun getMockWebServer(): MockWebServer { + return mockWebServer + } + + fun getServerUrl(path: String = "/"): String { + return mockWebServer.url(path).toString() + } +} diff --git a/reliability/core-it/test-proguard-rules.pro b/reliability/core-it/test-proguard-rules.pro new file mode 100644 index 0000000000..6f99486e43 --- /dev/null +++ b/reliability/core-it/test-proguard-rules.pro @@ -0,0 +1,45 @@ +-dontwarn com.sun.jna.FunctionMapper +-dontwarn com.sun.jna.JNIEnv +-dontwarn com.sun.jna.LastErrorException +-dontwarn com.sun.jna.Library +-dontwarn com.sun.jna.Memory +-dontwarn com.sun.jna.Native +-dontwarn com.sun.jna.NativeLibrary +-dontwarn com.sun.jna.Platform +-dontwarn com.sun.jna.Pointer +-dontwarn com.sun.jna.Structure +-dontwarn com.sun.jna.platform.win32.Advapi32 +-dontwarn com.sun.jna.platform.win32.Kernel32 +-dontwarn com.sun.jna.platform.win32.Win32Exception +-dontwarn com.sun.jna.platform.win32.WinBase$OVERLAPPED +-dontwarn com.sun.jna.platform.win32.WinBase$SECURITY_ATTRIBUTES +-dontwarn com.sun.jna.platform.win32.WinDef$DWORD +-dontwarn com.sun.jna.platform.win32.WinDef$LPVOID +-dontwarn com.sun.jna.platform.win32.WinNT$ACL +-dontwarn com.sun.jna.platform.win32.WinNT$HANDLE +-dontwarn com.sun.jna.platform.win32.WinNT$SECURITY_DESCRIPTOR +-dontwarn com.sun.jna.ptr.IntByReference +-dontwarn com.sun.jna.win32.StdCallLibrary +-dontwarn com.sun.jna.win32.W32APIOptions +-dontwarn java.lang.management.RuntimeMXBean +-dontwarn org.mockito.internal.creation.bytebuddy.inject.MockMethodDispatcher +-dontwarn com.google.errorprone.annotations.InlineMe +-dontwarn edu.umd.cs.findbugs.annotations.SuppressFBWarnings +-dontwarn java.lang.ClassValue +-dontwarn java.lang.instrument.ClassDefinition +-dontwarn java.lang.instrument.ClassFileTransformer +-dontwarn java.lang.instrument.IllegalClassFormatException +-dontwarn java.lang.instrument.Instrumentation +-dontwarn java.lang.instrument.UnmodifiableClassException +-dontwarn java.lang.management.ManagementFactory +-dontwarn java.lang.management.ThreadInfo +-dontwarn java.lang.management.ThreadMXBean +-dontwarn javax.lang.model.element.Modifier +-dontwarn org.w3c.dom.bootstrap.DOMImplementationRegistry +-dontwarn java.lang.StackWalker$Option +-dontwarn java.lang.StackWalker$StackFrame +-dontwarn java.lang.StackWalker +-dontwarn org.apiguardian.api.API$Status +-dontwarn org.apiguardian.api.API +-dontwarn kotlinx.coroutines.BuildersKt +-dontwarn kotlinx.coroutines.CoroutineScope diff --git a/reliability/stub-feature/build.gradle.kts b/reliability/stub-feature/build.gradle.kts index ff49e42259..0e9ae0b562 100644 --- a/reliability/stub-feature/build.gradle.kts +++ b/reliability/stub-feature/build.gradle.kts @@ -31,14 +31,6 @@ dependencies { implementation(libs.kotlin) // Testing - implementation(project(":tools:unit")) { - attributes { - attribute( - com.android.build.api.attributes.ProductFlavorAttr.of("platform"), - objects.named("jvm") - ) - } - } implementation(libs.bundles.jUnit5) implementation(libs.bundles.testTools) implementation(libs.okHttp) diff --git a/reliability/stub-feature/src/main/kotlin/com/datadog/android/api/feature/stub/StubRequestFactory.kt b/reliability/stub-feature/src/main/kotlin/com/datadog/android/api/feature/stub/StubRequestFactory.kt new file mode 100644 index 0000000000..11f7acb003 --- /dev/null +++ b/reliability/stub-feature/src/main/kotlin/com/datadog/android/api/feature/stub/StubRequestFactory.kt @@ -0,0 +1,69 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.api.feature.stub + +import com.datadog.android.api.context.DatadogContext +import com.datadog.android.api.net.Request +import com.datadog.android.api.net.RequestFactory +import com.datadog.android.api.storage.RawBatchEvent +import com.datadog.android.core.internal.utils.join +import fr.xgouchet.elmyr.Forge +import org.mockito.kotlin.mock +import java.util.UUID + +internal class StubRequestFactory( + private val forge: Forge, + private val customEndpointUrl: String +) : RequestFactory { + + override fun create( + context: DatadogContext, + batchData: List, + batchMetadata: ByteArray? + ): Request { + val requestId = UUID.randomUUID().toString() + return Request( + id = requestId, + description = forge.anAlphabeticalString(), + url = customEndpointUrl, + headers = buildHeaders( + requestId, + context.clientToken, + context.source, + context.sdkVersion + ), + body = batchData.map { it.data } + .join( + separator = PAYLOAD_SEPARATOR, + prefix = PAYLOAD_PREFIX, + suffix = PAYLOAD_SUFFIX, + internalLogger = mock() + ), + contentType = RequestFactory.CONTENT_TYPE_JSON + ) + } + + private fun buildHeaders( + requestId: String, + clientToken: String, + source: String, + sdkVersion: String + ): Map { + return mapOf( + RequestFactory.HEADER_API_KEY to clientToken, + RequestFactory.HEADER_EVP_ORIGIN to source, + RequestFactory.HEADER_EVP_ORIGIN_VERSION to sdkVersion, + RequestFactory.HEADER_REQUEST_ID to requestId + ) + } + + companion object { + private val PAYLOAD_SEPARATOR = ",".toByteArray(Charsets.UTF_8) + private val PAYLOAD_PREFIX = "[".toByteArray(Charsets.UTF_8) + private val PAYLOAD_SUFFIX = "]".toByteArray(Charsets.UTF_8) + } +} diff --git a/reliability/stub-feature/src/main/kotlin/com/datadog/android/api/feature/stub/StubStorageBackedFeature.kt b/reliability/stub-feature/src/main/kotlin/com/datadog/android/api/feature/stub/StubStorageBackedFeature.kt new file mode 100644 index 0000000000..df6eb56291 --- /dev/null +++ b/reliability/stub-feature/src/main/kotlin/com/datadog/android/api/feature/stub/StubStorageBackedFeature.kt @@ -0,0 +1,54 @@ +/* + * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. + * This product includes software developed at Datadog (https://www.datadoghq.com/). + * Copyright 2016-Present Datadog, Inc. + */ + +package com.datadog.android.api.feature.stub + +import android.content.Context +import com.datadog.android.api.feature.StorageBackedFeature +import com.datadog.android.api.net.RequestFactory +import com.datadog.android.api.storage.FeatureStorageConfiguration +import fr.xgouchet.elmyr.Forge + +/** + * A stub implementation of a [StorageBackedFeature] that can be used for testing. + + */ +class StubStorageBackedFeature( + private val forge: Forge, + private val featureName: String, + private val endpointUrl: String +) : StorageBackedFeature { + private var wasInitialized: Boolean = false + private var wasStopped: Boolean = false + + override val name: String get() = featureName + override val requestFactory: RequestFactory + get() = StubRequestFactory(forge, endpointUrl) + override val storageConfiguration: FeatureStorageConfiguration + get() = FeatureStorageConfiguration.DEFAULT + + override fun onInitialize(appContext: Context) { + wasInitialized = true + } + + override fun onStop() { + wasStopped = true + } + + /** + * Checks if the feature was initialized. + */ + fun wasInitialized(): Boolean { + return wasInitialized + } + + /** + * Checks if the feature was stopped. + */ + fun wasStopped(): Boolean { + return wasStopped + } +} diff --git a/tools/unit/src/main/kotlin/com/datadog/tools/unit/forge/ForgeExt.kt b/tools/unit/src/main/kotlin/com/datadog/tools/unit/forge/ForgeExt.kt index cadde5b726..42a94e7b30 100644 --- a/tools/unit/src/main/kotlin/com/datadog/tools/unit/forge/ForgeExt.kt +++ b/tools/unit/src/main/kotlin/com/datadog/tools/unit/forge/ForgeExt.kt @@ -110,3 +110,18 @@ private fun generateMapWithExhaustiveValues(forge: Forge): MutableMap T.useToolsFactories(): T { + addFactory(GsonJsonObjectForgeryFactory()) + addFactory(GsonJsonArrayForgeryFactory()) + addFactory(OrgJSONArrayForgeryFactory()) + addFactory(OrgJSONObjectForgeryFactory()) + addFactory(ThrowableForgeryFactory()) + addFactory(ExceptionForgeryFactory()) + addFactory(ErrorForgeryFactory()) + addFactory(GsonJsonPrimitiveForgeryFactory()) + return this +}