diff --git a/.github/workflows/kong.yml b/.github/workflows/kong.yml index 6c28426..9dfc780 100644 --- a/.github/workflows/kong.yml +++ b/.github/workflows/kong.yml @@ -2,6 +2,11 @@ name: KONG on: workflow_dispatch: + inputs: + kong-branch: + description: "Kong branch name" + type: string + required: false pull_request: branches: [main] push: @@ -19,7 +24,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Get KONG - run: git clone https://oauth2:$repo_pat@github.com/statsig-io/kong.git . + run: | + if [[ ${{ github.event_name }} == "workflow_dispatch" ]]; then + git clone -b ${{ inputs.kong-branch }} https://oauth2:$repo_pat@github.com/statsig-io/kong.git . + else + git clone https://oauth2:$repo_pat@github.com/statsig-io/kong.git . + fi - name: Install Deps run: npm install diff --git a/build.gradle.kts b/build.gradle.kts index 25660ec..1a758fa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -21,6 +21,7 @@ repositories { configure { verbose.set(true) + disabledRules.set(setOf("no-wildcard-imports")) } dependencies { diff --git a/gradle.properties b/gradle.properties index f21d1c9..eaaddaf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ RELEASE_SIGNING_ENABLED=true GROUP=com.statsig.serversdk POM_ARTIFACT_ID=serversdk -VERSION_NAME=1.6.1 +VERSION_NAME=1.6.2 POM_NAME=Statsig Server SDK POM_DESCRIPTION=A feature gating and a/b testing library for statsig diff --git a/src/main/kotlin/com/statsig/sdk/ClientInitializeFormatter.kt b/src/main/kotlin/com/statsig/sdk/ClientInitializeFormatter.kt index 8667af2..ba8d2a9 100644 --- a/src/main/kotlin/com/statsig/sdk/ClientInitializeFormatter.kt +++ b/src/main/kotlin/com/statsig/sdk/ClientInitializeFormatter.kt @@ -18,11 +18,7 @@ internal data class ClientInitializeResponse( fun toMap(): Map { val gson = Gson() val json = gson.toJson(this) - return try { - return gson.fromJson(json, object : TypeToken>() {}.type) - } catch (e: Exception) { - emptyMap() - } + return gson.fromJson(json, object : TypeToken>() {}.type) } } diff --git a/src/main/kotlin/com/statsig/sdk/ErrorBoundary.kt b/src/main/kotlin/com/statsig/sdk/ErrorBoundary.kt index 9366ea0..b56fc2e 100644 --- a/src/main/kotlin/com/statsig/sdk/ErrorBoundary.kt +++ b/src/main/kotlin/com/statsig/sdk/ErrorBoundary.kt @@ -8,7 +8,7 @@ import java.net.URI import java.net.URLEncoder import java.nio.charset.StandardCharsets -internal class ErrorBoundary(private val apiKey: String, private val options: StatsigOptions) { +internal class ErrorBoundary(private val apiKey: String, private val options: StatsigOptions, private val statsigMetadata: StatsigMetadata) { internal var uri = URI("https://statsigapi.net/v1/sdk_exception") private val seen = HashSet() private val maxInfoLength = 3000 @@ -68,7 +68,7 @@ internal class ErrorBoundary(private val apiKey: String, private val options: St "tag": "$tag", "exception": "${ex.javaClass.name}", "info": "$safeInfo", - "statsigMetadata": ${StatsigMetadata.asJson()} + "statsigMetadata": ${statsigMetadata.asJson()} } """.trimIndent() val req = diff --git a/src/main/kotlin/com/statsig/sdk/Evaluator.kt b/src/main/kotlin/com/statsig/sdk/Evaluator.kt index bb5669f..e5891fb 100644 --- a/src/main/kotlin/com/statsig/sdk/Evaluator.kt +++ b/src/main/kotlin/com/statsig/sdk/Evaluator.kt @@ -36,6 +36,7 @@ internal class Evaluator( private val statsigScope: CoroutineScope, private val errorBoundary: ErrorBoundary, private val diagnostics: Diagnostics, + private val statsigMetadata: StatsigMetadata, ) { private var specStore: SpecStore private val uaParser: Parser by lazy { @@ -55,7 +56,7 @@ internal class Evaluator( init { CountryLookup.initialize() - specStore = SpecStore(this.network, this.options, StatsigMetadata(), statsigScope, errorBoundary, diagnostics) + specStore = SpecStore(this.network, this.options, statsigMetadata, statsigScope, errorBoundary, diagnostics) network.setDiagnostics(diagnostics) statsigScope.launch { diff --git a/src/main/kotlin/com/statsig/sdk/SpecStore.kt b/src/main/kotlin/com/statsig/sdk/SpecStore.kt index 36dfc0f..bc97b9b 100644 --- a/src/main/kotlin/com/statsig/sdk/SpecStore.kt +++ b/src/main/kotlin/com/statsig/sdk/SpecStore.kt @@ -263,9 +263,8 @@ internal class SpecStore constructor( this.layerConfigs = newLayerConfigs this.experimentToLayer = newExperimentToLayer this.lastUpdateTime = downloadedConfig.time - if (downloadedConfig.sdkKeysToAppIDs != null) { - this.sdkKeysToAppIDs = downloadedConfig.sdkKeysToAppIDs - } + this.sdkKeysToAppIDs = downloadedConfig.sdkKeysToAppIDs ?: mapOf() + if (downloadedConfig.diagnostics != null) { diagnostics.setSamplingRate(downloadedConfig.diagnostics) } @@ -329,7 +328,7 @@ internal class SpecStore constructor( } fun getAppIDFromKey(clientSDKKey: String): String? { - return this.sdkKeysToAppIDs.get(clientSDKKey) + return this.sdkKeysToAppIDs[clientSDKKey] } private suspend fun initializeSpecs() { diff --git a/src/main/kotlin/com/statsig/sdk/Statsig.kt b/src/main/kotlin/com/statsig/sdk/Statsig.kt index e7eb37f..ef06731 100644 --- a/src/main/kotlin/com/statsig/sdk/Statsig.kt +++ b/src/main/kotlin/com/statsig/sdk/Statsig.kt @@ -18,14 +18,14 @@ class Statsig { serverSecret: String, options: StatsigOptions, ) { - if (!::statsigServer.isInitialized) { // Quick check without synchronization + if (!isInitialized()) { // Quick check without synchronization synchronized(this) { - if (!::statsigServer.isInitialized + if (!isInitialized() ) { // Secondary check in case another thread already created the default server - statsigServer = StatsigServer.create(serverSecret, options) + statsigServer = StatsigServer.create() } } - statsigServer.initialize() + statsigServer.initialize(serverSecret, options) } } @@ -241,7 +241,7 @@ class Statsig { /** * Sets a value to be returned for the given dynamic config/experiment instead of the actual evaluated value. * - * @param configName The name of the dynamic config or experiment to be overriden + * @param configName The name of the dynamic config or experiment to be overridden * @param configValue The value that will be returned */ @JvmStatic @@ -359,14 +359,14 @@ class Statsig { serverSecret: String, options: StatsigOptions = StatsigOptions(), ): CompletableFuture { - if (!::statsigServer.isInitialized) { // Quick check without synchronization + if (!isInitialized()) { // Quick check without synchronization synchronized(this) { - if (!::statsigServer.isInitialized + if (!isInitialized() ) { // Secondary check in case another thread already created the default server - statsigServer = StatsigServer.create(serverSecret, options) + statsigServer = StatsigServer.create() } } - return statsigServer.initializeAsync() + return statsigServer.initializeAsync(serverSecret, options) } return CompletableFuture.completedFuture(null) } @@ -631,12 +631,17 @@ class Statsig { runBlocking { statsigServer.shutdown() } } + @JvmStatic + fun isInitialized(): Boolean { + return ::statsigServer.isInitialized && statsigServer.initialized + } + private fun checkInitialized(): Boolean { - if (!::statsigServer.isInitialized) { + val initialized = isInitialized() + if (!initialized) { println("Call and wait for initialize to complete before calling SDK methods.") - return false } - return true + return initialized } } } diff --git a/src/main/kotlin/com/statsig/sdk/StatsigEvent.kt b/src/main/kotlin/com/statsig/sdk/StatsigEvent.kt index d56289b..6830b79 100644 --- a/src/main/kotlin/com/statsig/sdk/StatsigEvent.kt +++ b/src/main/kotlin/com/statsig/sdk/StatsigEvent.kt @@ -8,7 +8,7 @@ internal data class StatsigEvent( @SerializedName("value") val eventValue: Any? = null, @SerializedName("metadata") var eventMetadata: Map? = null, @SerializedName("user") var user: StatsigUser? = null, - @SerializedName("statsigMetadata") val statsigMetadata: Map? = null, + @SerializedName("statsigMetadata") val statsigMetadata: StatsigMetadata? = null, @SerializedName("secondaryExposures") val secondaryExposures: ArrayList>? = arrayListOf(), @SerializedName("time") val time: Long? = Utils.getTimeInMillis(), ) { diff --git a/src/main/kotlin/com/statsig/sdk/StatsigLogger.kt b/src/main/kotlin/com/statsig/sdk/StatsigLogger.kt index 939a3d7..22f3771 100644 --- a/src/main/kotlin/com/statsig/sdk/StatsigLogger.kt +++ b/src/main/kotlin/com/statsig/sdk/StatsigLogger.kt @@ -33,7 +33,7 @@ internal fun safeAddEvaluationToEvent(evaluationDetails: EvaluationDetails?, met internal class StatsigLogger( private val coroutineScope: CoroutineScope, private val network: StatsigNetwork, - private val statsigMetadata: Map, + private val statsigMetadata: StatsigMetadata, ) { private val executor = Executors.newSingleThreadExecutor() diff --git a/src/main/kotlin/com/statsig/sdk/StatsigMetadata.kt b/src/main/kotlin/com/statsig/sdk/StatsigMetadata.kt index 08761d6..9d2a8ae 100644 --- a/src/main/kotlin/com/statsig/sdk/StatsigMetadata.kt +++ b/src/main/kotlin/com/statsig/sdk/StatsigMetadata.kt @@ -1,30 +1,26 @@ package com.statsig.sdk +import com.google.gson.GsonBuilder +import com.google.gson.ToNumberPolicy +import com.google.gson.annotations.SerializedName import java.util.Properties +import java.util.UUID -private const val VERSION = "1.6.1" +private const val VERSION = "1.6.2" -internal class StatsigMetadata { - companion object { - private val version = - try { - val properties = Properties() - properties.load( - StatsigMetadata::class.java.getResourceAsStream("/statsigsdk.properties"), - ) - properties.getProperty("version") - } catch (e: Exception) { - VERSION - } - - fun asMap(): Map { - return mapOf("sdkType" to "java-server", "sdkVersion" to version) - } - - fun asJson(): String { - val map = asMap() - val values = map.map { "\"${it.key}\":\"${it.value}\"" } - return "{${values.joinToString(",")}}" - } +internal data class StatsigMetadata(@SerializedName("sdkType") var sdkType: String = "java-server", @SerializedName("sessionID") var sessionID: String = UUID.randomUUID().toString(), @SerializedName("languageVersion") var languageVersion: String = System.getProperty("java.version"), @SerializedName("exposureLoggingDisabled") var exposureLoggingDisabled: Boolean? = null) { + @SerializedName("sdkVersion") + var sdkVersion: String = try { + val properties = Properties() + properties.load( + StatsigMetadata::class.java.getResourceAsStream("/statsigsdk.properties"), + ) + properties.getProperty("version") + } catch (e: Exception) { + VERSION + } + fun asJson(): String { + val gson = GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create() + return gson.toJson(this) } } diff --git a/src/main/kotlin/com/statsig/sdk/StatsigNetwork.kt b/src/main/kotlin/com/statsig/sdk/StatsigNetwork.kt index 0cd87bb..b6c5cf3 100644 --- a/src/main/kotlin/com/statsig/sdk/StatsigNetwork.kt +++ b/src/main/kotlin/com/statsig/sdk/StatsigNetwork.kt @@ -27,7 +27,7 @@ private const val MS_IN_S: Long = 1000 internal class StatsigNetwork( private val sdkKey: String, private val options: StatsigOptions, - private val statsigMetadata: Map, + private val statsigMetadata: StatsigMetadata, private val errorBoundary: ErrorBoundary, private val backoffMultiplier: Int = BACKOFF_MULTIPLIER, ) { @@ -60,8 +60,8 @@ internal class StatsigNetwork( .addHeader("STATSIG-API-KEY", sdkKey) .addHeader("STATSIG-CLIENT-TIME", System.currentTimeMillis().toString()) .addHeader("STATSIG-SERVER-SESSION-ID", serverSessionID) - .addHeader("STATSIG-SDK-TYPE", statsigMetadata["sdkType"] ?: "") - .addHeader("STATSIG-SDK-VERSION", statsigMetadata["sdkVersion"] ?: "") + .addHeader("STATSIG-SDK-TYPE", statsigMetadata.sdkType) + .addHeader("STATSIG-SDK-VERSION", statsigMetadata.sdkVersion) .method(original.method, original.body) .build() it.proceed(request) @@ -91,12 +91,12 @@ internal class StatsigNetwork( } suspend fun checkGate(user: StatsigUser?, gateName: String, disableExposureLogging: Boolean): ConfigEvaluation { - val exposureLoggingMap = mapOf("exposureLoggingDisabled" to disableExposureLogging) + statsigMetadata.exposureLoggingDisabled = disableExposureLogging val bodyJson = gson.toJson( mapOf( "gateName" to gateName, "user" to user, - "statsigMetadata" to statsigMetadata + exposureLoggingMap, + "statsigMetadata" to statsigMetadata, ), ) val requestBody: RequestBody = bodyJson.toRequestBody(json) @@ -117,14 +117,15 @@ internal class StatsigNetwork( } suspend fun getConfig(user: StatsigUser?, configName: String, disableExposureLogging: Boolean): ConfigEvaluation { - val exposureLoggingMap = mapOf("exposureLoggingDisabled" to disableExposureLogging) + statsigMetadata.exposureLoggingDisabled = disableExposureLogging val bodyJson = gson.toJson( mapOf( "configName" to configName, "user" to user, - "statsigMetadata" to statsigMetadata + exposureLoggingMap, + "statsigMetadata" to statsigMetadata, ), ) + statsigMetadata.exposureLoggingDisabled = null val requestBody: RequestBody = bodyJson.toRequestBody(json) val request: Request = Request.Builder() @@ -196,13 +197,13 @@ internal class StatsigNetwork( } } - suspend fun postLogs(events: List, statsigMetadata: Map) { + suspend fun postLogs(events: List, statsigMetadata: StatsigMetadata) { retryPostLogs(events, statsigMetadata, 5, 1) } suspend fun retryPostLogs( events: List, - statsigMetadata: Map, + statsigMetadata: StatsigMetadata, retries: Int, backoff: Int, ) { diff --git a/src/main/kotlin/com/statsig/sdk/StatsigServer.kt b/src/main/kotlin/com/statsig/sdk/StatsigServer.kt index feffe2f..4b86343 100644 --- a/src/main/kotlin/com/statsig/sdk/StatsigServer.kt +++ b/src/main/kotlin/com/statsig/sdk/StatsigServer.kt @@ -1,24 +1,27 @@ package com.statsig.sdk -import com.google.gson.Gson import com.google.gson.GsonBuilder import com.google.gson.ToNumberPolicy -import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.cancel -import kotlinx.coroutines.cancelAndJoin +import kotlinx.coroutines.* import kotlinx.coroutines.future.future -import kotlinx.coroutines.runBlocking import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import java.util.Collections.emptyMap import java.util.concurrent.CompletableFuture sealed class StatsigServer { - internal abstract val errorBoundary: ErrorBoundary + internal abstract var errorBoundary: ErrorBoundary + abstract var initialized: Boolean - @JvmSynthetic abstract suspend fun initialize() + @JvmSynthetic abstract fun setup( + serverSecret: String, + options: StatsigOptions, + ) + + @JvmSynthetic abstract suspend fun initialize( + serverSecret: String, + options: StatsigOptions, + ) @JvmSynthetic abstract suspend fun checkGate(user: StatsigUser, gateName: String): Boolean @@ -105,7 +108,7 @@ sealed class StatsigServer { metadata: Map? = null, ) - abstract fun initializeAsync(): CompletableFuture + abstract fun initializeAsync(serverSecret: String, options: StatsigOptions): CompletableFuture abstract fun checkGateAsync(user: StatsigUser, gateName: String): CompletableFuture abstract fun checkGateWithExposureLoggingDisabledAsync(user: StatsigUser, gateName: String): CompletableFuture @@ -169,42 +172,43 @@ sealed class StatsigServer { @JvmStatic @JvmOverloads - fun create( - serverSecret: String, - options: StatsigOptions = StatsigOptions(), - ): StatsigServer = StatsigServerImpl(serverSecret, options) + fun create(): StatsigServer = StatsigServerImpl() } } -private class StatsigServerImpl(serverSecret: String, private val options: StatsigOptions) : +private class StatsigServerImpl() : StatsigServer() { - init { - if (serverSecret.isEmpty() || !serverSecret.startsWith("secret-")) { - throw StatsigUninitializedException( - "Statsig Server SDKs must be initialized with a secret key", - ) - } - } - private val gson = GsonBuilder().setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE).create() - override val errorBoundary = ErrorBoundary(serverSecret, options) - private val coroutineExceptionHandler = - CoroutineExceptionHandler { _, ex -> + override lateinit var errorBoundary: ErrorBoundary + private lateinit var coroutineExceptionHandler: CoroutineExceptionHandler + private lateinit var statsigJob: CompletableJob + private lateinit var statsigScope: CoroutineScope + private lateinit var network: StatsigNetwork + private lateinit var logger: StatsigLogger + private lateinit var configEvaluator: Evaluator + private lateinit var diagnostics: Diagnostics + private var options: StatsigOptions = StatsigOptions() + private val mutex = Mutex() + private val statsigMetadata = StatsigMetadata() + override var initialized = false + + override fun setup(serverSecret: String, options: StatsigOptions) { + errorBoundary = ErrorBoundary(serverSecret, options, statsigMetadata) + coroutineExceptionHandler = CoroutineExceptionHandler { _, ex -> // no-op - supervisor job should not throw when a child fails errorBoundary.logException("coroutineExceptionHandler", ex) } - private val statsigJob = SupervisorJob() - private val statsigScope = CoroutineScope(statsigJob + coroutineExceptionHandler) - private val mutex = Mutex() - private val statsigMetadata = StatsigMetadata.asMap() - private val network = StatsigNetwork(serverSecret, options, statsigMetadata, errorBoundary) - private var logger: StatsigLogger = StatsigLogger(statsigScope, network, statsigMetadata) - private lateinit var configEvaluator: Evaluator - private lateinit var diagnostics: Diagnostics + statsigJob = SupervisorJob() + statsigScope = CoroutineScope(statsigJob + coroutineExceptionHandler) + network = StatsigNetwork(serverSecret, options, statsigMetadata, errorBoundary) + logger = StatsigLogger(statsigScope, network, statsigMetadata) + this.options = options + } - override suspend fun initialize() { + override suspend fun initialize(serverSecret: String, options: StatsigOptions) { + setup(serverSecret, options) errorBoundary.capture( "initialize", { @@ -216,8 +220,9 @@ private class StatsigServerImpl(serverSecret: String, private val options: Stats } setupAndStartDiagnostics() configEvaluator = - Evaluator(network, options, statsigScope, errorBoundary, diagnostics) + Evaluator(network, options, statsigScope, errorBoundary, diagnostics, statsigMetadata) configEvaluator.initialize() + initialized = true endInitDiagnostics(isSDKInitialized()) } }, @@ -472,6 +477,7 @@ private class StatsigServerImpl(serverSecret: String, private val options: Stats configEvaluator.shutdown() statsigJob.cancelAndJoin() statsigScope.cancel() + initialized = false } } @@ -503,9 +509,10 @@ private class StatsigServerImpl(serverSecret: String, private val options: Stats }, { return@captureSync }) } - override fun initializeAsync(): CompletableFuture { + override fun initializeAsync(serverSecret: String, options: StatsigOptions): CompletableFuture { + setup(serverSecret, options) return statsigScope.future { - initialize() + initialize(serverSecret, options) null } } @@ -678,7 +685,7 @@ private class StatsigServerImpl(serverSecret: String, private val options: Stats normalizedUser, layer, paramName, - Gson().toJson(metadata), + gson.toJson(metadata), ), ) } else { diff --git a/src/test/java/com/statsig/sdk/ConcurrencyTest.kt b/src/test/java/com/statsig/sdk/ConcurrencyTest.kt index 53507d4..30628ea 100644 --- a/src/test/java/com/statsig/sdk/ConcurrencyTest.kt +++ b/src/test/java/com/statsig/sdk/ConcurrencyTest.kt @@ -90,7 +90,7 @@ class ConcurrencyTest { } } - val options = StatsigOptions().apply { + options = StatsigOptions().apply { api = server.url("/v1").toString() disableDiagnostics = true @@ -98,12 +98,12 @@ class ConcurrencyTest { rulesetsSyncIntervalMs = 10 idListsSyncIntervalMs = 10 } - driver = StatsigServer.create("secret-testcase", options) + driver = StatsigServer.create() } @Test fun testCallingAPIsFromDifferentThreads() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) val threads = arrayListOf() for (i in 1..20) { val t = diff --git a/src/test/java/com/statsig/sdk/DataStoreTest.kt b/src/test/java/com/statsig/sdk/DataStoreTest.kt index 9f81617..7f84ae1 100644 --- a/src/test/java/com/statsig/sdk/DataStoreTest.kt +++ b/src/test/java/com/statsig/sdk/DataStoreTest.kt @@ -90,8 +90,8 @@ class DataStoreTest { @Test fun dataStoreIsLoaded() { - driver = StatsigServer.create("secret-local", networkOptions) - driver.initializeAsync().get() + driver = StatsigServer.create() + driver.initializeAsync("secret-local", networkOptions).get() val res = driver.checkGateAsync(user, "gate_from_adapter_always_on").get() Assert.assertTrue(res) @@ -105,8 +105,8 @@ class DataStoreTest { bootstrapValues = downloadConfigSpecsResponse, disableDiagnostics = true, ) - driver = StatsigServer.create("secret-local", networkOptions) - driver.initializeAsync().get() + driver = StatsigServer.create() + driver.initializeAsync("secret-local", networkOptions).get() val dataStoreGateRes = driver.checkGateAsync(user, "gate_from_adapter_always_on").get() val bootstrapGateRes = driver.checkGateAsync(user, "always_on").get() driver.shutdown() @@ -131,8 +131,8 @@ class DataStoreTest { bootstrapValues = downloadConfigSpecsResponse, disableDiagnostics = true, ) - driver = StatsigServer.create("secret-local", networkOptions) - driver.initializeAsync().get() + driver = StatsigServer.create() + driver.initializeAsync("secret-local", networkOptions).get() val bootstrapGateRes = driver.checkGateAsync(user, "always_on").get() driver.shutdown() @@ -147,16 +147,16 @@ class DataStoreTest { val networkOptions = StatsigOptions( api = server.url("/v1").toString(), ) - driver = StatsigServer.create("secret-local", networkOptions) - driver.initializeAsync().get() + driver = StatsigServer.create() + driver.initializeAsync("secret-local", networkOptions).get() Assert.assertTrue(didCallDownloadConfig) } @Test fun testNetworkNotCalledWhenAdapterIsPresent() { - driver = StatsigServer.create("secret-local", networkOptions) - driver.initializeAsync().get() + driver = StatsigServer.create() + driver.initializeAsync("secret-local", networkOptions).get() Assert.assertFalse(didCallDownloadConfig) } @@ -167,8 +167,8 @@ class DataStoreTest { api = server.url("/v1").toString(), bootstrapValues = downloadConfigSpecsResponse, ) - driver = StatsigServer.create("secret-local", networkOptions) - driver.initializeAsync().get() + driver = StatsigServer.create() + driver.initializeAsync("secret-local", networkOptions).get() Assert.assertFalse(didCallDownloadConfig) } @@ -179,8 +179,8 @@ class DataStoreTest { api = server.url("/v1").toString(), bootstrapValues = "invalid bootstrap values", ) - driver = StatsigServer.create("secret-local", networkOptions) - driver.initializeAsync().get() + driver = StatsigServer.create() + driver.initializeAsync("secret-local", networkOptions).get() Assert.assertTrue(didCallDownloadConfig) } diff --git a/src/test/java/com/statsig/sdk/DiagnosticsTest.kt b/src/test/java/com/statsig/sdk/DiagnosticsTest.kt index a493178..6a2e6ee 100644 --- a/src/test/java/com/statsig/sdk/DiagnosticsTest.kt +++ b/src/test/java/com/statsig/sdk/DiagnosticsTest.kt @@ -41,7 +41,7 @@ class DiagnosticsTest { @Test fun testInitialize() = runBlocking { setupWebServer(downloadConfigSpecsResponse) - driver.initializeAsync().get() + driver.initializeAsync("secret-testcase", options).get() driver.shutdown() val events = TestUtil.captureEvents(eventLogInputCompletable) val diagnosticsEvent = events.find { it.eventName == "statsig::diagnostics" } @@ -61,7 +61,7 @@ class DiagnosticsTest { fun testSamping() = runBlocking { val downloadConfigSpecsResponseWithSampling = StringBuilder(downloadConfigSpecsResponse).insert(downloadConfigSpecsResponse.length - 2, ",\n \"diagnostics\": {\"initialize\": \"0\"}").toString() setupWebServer(downloadConfigSpecsResponseWithSampling) - driver.initializeAsync().get() + driver.initializeAsync("secret-testcase", options).get() driver.shutdown() Assert.assertFalse( "should not have called log_event endpoint", @@ -91,7 +91,7 @@ class DiagnosticsTest { options = StatsigOptions().apply { api = server.url("/v1").toString() } - driver = StatsigServer.create("secret-testcase", options) + driver = StatsigServer.create() } } diff --git a/src/test/java/com/statsig/sdk/ErrorBoundaryTest.kt b/src/test/java/com/statsig/sdk/ErrorBoundaryTest.kt index f051ad4..b8d45ea 100644 --- a/src/test/java/com/statsig/sdk/ErrorBoundaryTest.kt +++ b/src/test/java/com/statsig/sdk/ErrorBoundaryTest.kt @@ -20,6 +20,7 @@ import java.nio.charset.StandardCharsets class ErrorBoundaryTest { private lateinit var boundary: ErrorBoundary private lateinit var server: MockWebServer + private lateinit var statsigMetadata: StatsigMetadata @Before internal fun setup() { @@ -31,8 +32,8 @@ class ErrorBoundaryTest { } } } - - boundary = ErrorBoundary("secret-key", StatsigOptions()) + statsigMetadata = StatsigMetadata() + boundary = ErrorBoundary("secret-key", StatsigOptions(), statsigMetadata) boundary.uri = server.url("/v1/sdk_exception").toUri() } @@ -75,7 +76,7 @@ class ErrorBoundaryTest { boundary.swallow("") { throw IOException() } val body = Gson().fromJson(server.takeRequest().body.readUtf8(), Map::class.java) - assertEquals(body["statsigMetadata"], StatsigMetadata.asMap()) + assertEquals(body["statsigMetadata"], Gson().fromJson(statsigMetadata.asJson(), Map::class.java)) } @Test diff --git a/src/test/java/com/statsig/sdk/EvaluationDetailsTest.kt b/src/test/java/com/statsig/sdk/EvaluationDetailsTest.kt index 8e61a2a..2aae231 100644 --- a/src/test/java/com/statsig/sdk/EvaluationDetailsTest.kt +++ b/src/test/java/com/statsig/sdk/EvaluationDetailsTest.kt @@ -69,8 +69,8 @@ class EvaluationDetailsTest { disableDiagnostics = true } - driver = StatsigServer.create("secret-local", options) - driver.initialize() + driver = StatsigServer.create() + driver.initialize("secret-local", options) } @Test @@ -160,8 +160,8 @@ class EvaluationDetailsTest { @Test fun bootstrapTest() = runBlocking { val options = StatsigOptions(bootstrapValues = configSpecsResponse, api = server.url("/v1").toString(), disableDiagnostics = true) - val bootstrapServer = StatsigServer.create("secret-key", options) - bootstrapServer.initialize() + val bootstrapServer = StatsigServer.create() + bootstrapServer.initialize("secret-key", options) bootstrapServer.checkGate(user, "always_on_gate") bootstrapServer.getConfig(user, "test_config") diff --git a/src/test/java/com/statsig/sdk/EvaluatorTest.java b/src/test/java/com/statsig/sdk/EvaluatorTest.java index 2db4a2f..b91c78e 100644 --- a/src/test/java/com/statsig/sdk/EvaluatorTest.java +++ b/src/test/java/com/statsig/sdk/EvaluatorTest.java @@ -21,8 +21,8 @@ public class EvaluatorTest { @Test public void testIP3Country() throws NoSuchFieldException, IllegalAccessException, ExecutionException, InterruptedException { - StatsigServer driver = StatsigServer.create("secret-local", new StatsigOptions()); - driver.initializeAsync().get(); + StatsigServer driver = StatsigServer.create(); + driver.initializeAsync("secret-local", new StatsigOptions()).get(); SpecStore specStore = TestUtilJava.getSpecStoreFromStatsigServer(driver); Evaluator eval = TestUtilJava.getEvaluatorFromStatsigServer(driver); @@ -75,8 +75,8 @@ public CaseSensitiveTestCase (String name, Object one, String two, boolean ignor @Test public void testCaseSensitivity() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException, ExecutionException, InterruptedException { - StatsigServer driver = StatsigServer.create("secret-local", new StatsigOptions()); - driver.initializeAsync().get(); + StatsigServer driver = StatsigServer.create(); + driver.initializeAsync("secret-local", new StatsigOptions()).get(); Evaluator eval = TestUtilJava.getEvaluatorFromStatsigServer(driver); diff --git a/src/test/java/com/statsig/sdk/ExposureLoggingTest.kt b/src/test/java/com/statsig/sdk/ExposureLoggingTest.kt index 3bb8b12..57ab8cc 100644 --- a/src/test/java/com/statsig/sdk/ExposureLoggingTest.kt +++ b/src/test/java/com/statsig/sdk/ExposureLoggingTest.kt @@ -21,6 +21,7 @@ class ExposureLoggingTest { private lateinit var evaluator: Evaluator private lateinit var driver: StatsigServer private lateinit var user: StatsigUser + private lateinit var options: StatsigOptions @Before fun setUp() { @@ -57,17 +58,17 @@ class ExposureLoggingTest { } } - val options = StatsigOptions().apply { + options = StatsigOptions().apply { api = server.url("/v1").toString() disableDiagnostics = true } - driver = StatsigServer.create("secret-local", options) + driver = StatsigServer.create() } @Test fun testManualLogLayerParameterExposure() = runBlocking { - driver.initialize() + driver.initialize("secret-local", options) driver.manuallyLogLayerParameterExposure(user, "a_layer", "a_param") driver.shutdown() @@ -78,7 +79,7 @@ class ExposureLoggingTest { @Test fun testCheckGateWithExposureLoggingDisabled() = runBlocking { - driver.initialize() + driver.initialize("secret-local", options) driver.checkGateWithExposureLoggingDisabled(user, "a_gate") driver.shutdown() @@ -87,7 +88,7 @@ class ExposureLoggingTest { @Test fun testManuallyLogGateExposure() = runBlocking { - driver.initialize() + driver.initialize("secret-local", options) driver.manuallyLogGateExposure(user, "a_gate") driver.shutdown() @@ -98,7 +99,7 @@ class ExposureLoggingTest { @Test fun testCheckGateWithExposureLoggingEnabled() = runBlocking { - driver.initialize() + driver.initialize("secret-local", options) driver.checkGate(user, "always_on_gate") driver.shutdown() @@ -108,7 +109,7 @@ class ExposureLoggingTest { @Test fun testGetConfigWithExposureLoggingDisabled() = runBlocking { - driver.initialize() + driver.initialize("secret-local", options) driver.getConfigWithExposureLoggingDisabled(user, "a_config") driver.shutdown() @@ -117,7 +118,7 @@ class ExposureLoggingTest { @Test fun testGetConfigWithExposureLoggingEnabled() = runBlocking { - driver.initialize() + driver.initialize("secret-local", options) driver.getConfig(user, "a_config") driver.shutdown() @@ -127,7 +128,7 @@ class ExposureLoggingTest { @Test fun testManualLogConfigExposure() = runBlocking { - driver.initialize() + driver.initialize("secret-local", options) driver.manuallyLogConfigExposure(user, "a_config") driver.shutdown() @@ -138,7 +139,7 @@ class ExposureLoggingTest { @Test fun testGetExperimentWithExposureLoggingDisabled() = runBlocking { - driver.initialize() + driver.initialize("secret-local", options) driver.getExperimentWithExposureLoggingDisabled(user, "a_config") driver.shutdown() @@ -147,7 +148,7 @@ class ExposureLoggingTest { @Test fun testGetExperimentWithExposureLoggingEnabled() = runBlocking { - driver.initialize() + driver.initialize("secret-local", options) driver.getExperiment(user, "a_config") driver.shutdown() @@ -157,7 +158,7 @@ class ExposureLoggingTest { @Test fun testGetLayerWithExposureLoggingDisabled() = runBlocking { - driver.initialize() + driver.initialize("secret-local", options) val layer = driver.getLayerWithExposureLoggingDisabled(user, "explicit_vs_implicit_parameter_layer") layer.getInt("an_int", 0) driver.shutdown() @@ -167,7 +168,7 @@ class ExposureLoggingTest { @Test fun testGetLayerWithExposureLoggingEnabled() = runBlocking { - driver.initialize() + driver.initialize("secret-local", options) val layer = driver.getLayer(user, "explicit_vs_implicit_parameter_layer") layer.getInt("an_int", 0) driver.shutdown() diff --git a/src/test/java/com/statsig/sdk/ExposureLoggingTestJava.java b/src/test/java/com/statsig/sdk/ExposureLoggingTestJava.java index 373cee3..44bea5e 100644 --- a/src/test/java/com/statsig/sdk/ExposureLoggingTestJava.java +++ b/src/test/java/com/statsig/sdk/ExposureLoggingTestJava.java @@ -23,6 +23,7 @@ public class ExposureLoggingTestJava { private CompletableFuture eventLogInputCompletable; private StatsigServer driver; private StatsigUser user; + private StatsigOptions options; @Before public void setUp() { @@ -61,16 +62,16 @@ public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) throws In MockWebServer server = new MockWebServer(); server.setDispatcher(dispatcher); - StatsigOptions options = new StatsigOptions(); + options = new StatsigOptions(); options.setDisableDiagnostics(true); options.setApi(server.url("/v1").toString()); - driver = StatsigServer.create("secret-local", options); + driver = StatsigServer.create(); } @Test public void testManualLogLayerParameterExposureAsync() throws ExecutionException, InterruptedException { - driver.initializeAsync().get(); + driver.initializeAsync("secret-local", options).get(); driver.manuallyLogLayerParameterExposureAsync(user, "a_layer", "a_param").get(); driver.shutdown(); @@ -81,7 +82,7 @@ public void testManualLogLayerParameterExposureAsync() throws ExecutionException @Test public void testManuallyLogGateExposureAsync() throws ExecutionException, InterruptedException { - driver.initializeAsync().get(); + driver.initializeAsync("secret-local", options).get(); driver.manuallyLogGateExposureAsync(user, "a_gate").get(); driver.shutdown(); @@ -92,7 +93,7 @@ public void testManuallyLogGateExposureAsync() throws ExecutionException, Interr @Test public void testManuallyLogConfigExposureAsync() throws ExecutionException, InterruptedException { - driver.initializeAsync().get(); + driver.initializeAsync("secret-local", options).get(); driver.manuallyLogConfigExposureAsync(user, "a_config").get(); driver.shutdown(); @@ -104,7 +105,7 @@ public void testManuallyLogConfigExposureAsync() throws ExecutionException, Inte // TODO: call manuallyExperimentExposureAsync from top level. @Test public void testManuallyLogExperimentExposureAsync() throws ExecutionException, InterruptedException { - driver.initializeAsync().get(); + driver.initializeAsync("secret-local", options).get(); driver.manuallyLogConfigExposureAsync(user, "an_experiment").get(); driver.shutdown(); diff --git a/src/test/java/com/statsig/sdk/LayerExposureTest.kt b/src/test/java/com/statsig/sdk/LayerExposureTest.kt index b608de3..c52d67b 100644 --- a/src/test/java/com/statsig/sdk/LayerExposureTest.kt +++ b/src/test/java/com/statsig/sdk/LayerExposureTest.kt @@ -68,16 +68,16 @@ class LayerExposureTest { } } - val options = StatsigOptions().apply { + options = StatsigOptions().apply { api = server.url("/v1").toString() disableDiagnostics = true } - driver = StatsigServer.create("secret-testcase", options) + driver = StatsigServer.create() } @Test fun testDoesNotLogOnGetLayer() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) driver.getLayer(user, "unallocated_layer") driver.shutdown() @@ -86,7 +86,7 @@ class LayerExposureTest { @Test fun testDoesNotLogOnInvalidType() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) val layer = driver.getLayer(user, "unallocated_layer") layer.getString("an_int", "err") driver.shutdown() @@ -96,7 +96,7 @@ class LayerExposureTest { @Test fun testDoesNotLogNonExistentKeys() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) val layer = driver.getLayer(user, "unallocated_layer") layer.getString("a_string", "err") driver.shutdown() @@ -106,7 +106,7 @@ class LayerExposureTest { @Test fun testUnallocatedLayerLogging() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) val layer = driver.getLayer(user, "unallocated_layer") layer.getInt("an_int", 0) driver.shutdown() @@ -140,7 +140,7 @@ class LayerExposureTest { @Test fun testExplicitVsImplicitParameterLogging() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) val layer = driver.getLayer(user, "explicit_vs_implicit_parameter_layer") stutter { layer.getInt("an_int", 0) } stutter { layer.getString("a_string", "err") } @@ -200,7 +200,7 @@ class LayerExposureTest { @Test fun testDifferentObjectTypeLogging() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) val layer = driver.getLayer(user, "different_object_type_logging_layer") stutter { layer.getBoolean("a_bool", false) } stutter { layer.getInt("an_int", 0) } @@ -230,7 +230,7 @@ class LayerExposureTest { val user = StatsigUser("dloomb") user.email = "dan@statsigly.com" - driver.initialize() + driver.initialize("secret-testcase", options) val layer = driver.getLayer(user, "unallocated_layer") layer.getInt("an_int", 0) driver.shutdown() diff --git a/src/test/java/com/statsig/sdk/LayerInJavaTest.java b/src/test/java/com/statsig/sdk/LayerInJavaTest.java index db78d6f..b8ac7ae 100644 --- a/src/test/java/com/statsig/sdk/LayerInJavaTest.java +++ b/src/test/java/com/statsig/sdk/LayerInJavaTest.java @@ -28,8 +28,8 @@ public void setUp() throws Exception { assertEquals(configs.getDynamicConfigs().length, 0); assertEquals(configs.getLayerConfigs().length, 0); }); - driver = StatsigServer.create("secret-test", options); - Future initFuture = driver.initializeAsync(); + driver = StatsigServer.create(); + Future initFuture = driver.initializeAsync("secret-test", options); initFuture.get(); } diff --git a/src/test/java/com/statsig/sdk/LocalOverridesTestJava.java b/src/test/java/com/statsig/sdk/LocalOverridesTestJava.java index dcab076..7215107 100644 --- a/src/test/java/com/statsig/sdk/LocalOverridesTestJava.java +++ b/src/test/java/com/statsig/sdk/LocalOverridesTestJava.java @@ -24,8 +24,8 @@ public void setUp() throws Exception { StatsigOptions options = new StatsigOptions(); options.setLocalMode(true); - driver = StatsigServer.create("secret-local", options); - Future initFuture = driver.initializeAsync(); + driver = StatsigServer.create(); + Future initFuture = driver.initializeAsync("secret-local", options); initFuture.get(); evaluator = TestUtilJava.getEvaluatorFromStatsigServer(driver); diff --git a/src/test/java/com/statsig/sdk/NetworkTest.kt b/src/test/java/com/statsig/sdk/NetworkTest.kt index c2d1201..54b8d4a 100644 --- a/src/test/java/com/statsig/sdk/NetworkTest.kt +++ b/src/test/java/com/statsig/sdk/NetworkTest.kt @@ -32,12 +32,11 @@ class NetworkTest { successResponse.setBody("{}") server.enqueue(successResponse) - val metadata: MutableMap = HashMap() - metadata["sdkType"] = "test" + val metadata = StatsigMetadata() val options = StatsigOptions() options.api = server.url("/v1").toString() - val eb = ErrorBoundary("", options) + val eb = ErrorBoundary("", options, metadata) val net = spyk(StatsigNetwork("secret-123", options, metadata, eb, 1)) net.postLogs(listOf(StatsigEvent("TestEvent")), metadata) diff --git a/src/test/java/com/statsig/sdk/ReInitializeTest.kt b/src/test/java/com/statsig/sdk/ReInitializeTest.kt new file mode 100644 index 0000000..57348fd --- /dev/null +++ b/src/test/java/com/statsig/sdk/ReInitializeTest.kt @@ -0,0 +1,58 @@ +package com.statsig.sdk + +import kotlinx.coroutines.runBlocking +import okhttp3.mockwebserver.Dispatcher +import okhttp3.mockwebserver.MockResponse +import okhttp3.mockwebserver.MockWebServer +import okhttp3.mockwebserver.RecordedRequest +import org.junit.Assert +import org.junit.BeforeClass +import org.junit.Test + +class ReInitializeTest { + companion object { + private lateinit var server: MockWebServer + private lateinit var options: StatsigOptions + private val dcs = arrayListOf() + private val logEvent = arrayListOf() + + @BeforeClass + @JvmStatic + internal fun beforeAll() = runBlocking { + server = MockWebServer() + server.dispatcher = + object : Dispatcher() { + override fun dispatch(request: RecordedRequest): MockResponse { + when (request.path) { + "/v1/download_config_specs" -> { + val downloadConfigSpecsResponse = + StatsigE2ETest::class.java.getResource("/download_config_specs.json")?.readText() ?: "" + dcs.add(request) + return MockResponse().setResponseCode(200).setBody(downloadConfigSpecsResponse) + } + "/v1/log_event" -> { + logEvent.add(request) + } + } + return MockResponse().setResponseCode(202) + } + } + options = StatsigOptions(api = server.url("/v1").toString()) + } + } + + @Test + fun testReinitializeAfterShutdown() = runBlocking { + Statsig.initialize("secret-1", StatsigOptions()) + Statsig.shutdown() + Statsig.initialize("secret-2", options) + Assert.assertEquals(1, dcs.size) + } + + @Test + fun testReinitializeBeforeShutdown() = runBlocking { + Statsig.initialize("secret-1", StatsigOptions()) + Statsig.initialize("secret-2", options) + Assert.assertEquals(0, dcs.size) + } +} diff --git a/src/test/java/com/statsig/sdk/ServerSDKConsistencyTest.java b/src/test/java/com/statsig/sdk/ServerSDKConsistencyTest.java index 260647f..0a3909c 100644 --- a/src/test/java/com/statsig/sdk/ServerSDKConsistencyTest.java +++ b/src/test/java/com/statsig/sdk/ServerSDKConsistencyTest.java @@ -59,8 +59,8 @@ public void testConsistency(String api) throws Exception { System.out.println("Testing for " + api); String response = this.postRequestRulesetsTest(api); APITestDataSet[] data = gson.fromJson(response, APIEvaluationConsistencyTestData.class).getData(); - StatsigServer driver = StatsigServer.create(secret, new StatsigOptions(api)); - Future initFuture = driver.initializeAsync(); + StatsigServer driver = StatsigServer.create(); + Future initFuture = driver.initializeAsync(secret, new StatsigOptions(api)); initFuture.get(); Evaluator evaluator = TestUtilJava.getEvaluatorFromStatsigServer(driver); diff --git a/src/test/java/com/statsig/sdk/SpecStoreTests.kt b/src/test/java/com/statsig/sdk/SpecStoreTests.kt index 2aae2a1..58bca67 100644 --- a/src/test/java/com/statsig/sdk/SpecStoreTests.kt +++ b/src/test/java/com/statsig/sdk/SpecStoreTests.kt @@ -13,8 +13,8 @@ class SpecStoreTests { @Before fun setup() { - driver = create("secret-local", StatsigOptions()) - driver.initializeAsync().get() + driver = create() + driver.initializeAsync("secret-local", StatsigOptions()).get() } @Test diff --git a/src/test/java/com/statsig/sdk/StatsigE2ETest.kt b/src/test/java/com/statsig/sdk/StatsigE2ETest.kt index 399a649..472e200 100644 --- a/src/test/java/com/statsig/sdk/StatsigE2ETest.kt +++ b/src/test/java/com/statsig/sdk/StatsigE2ETest.kt @@ -205,7 +205,7 @@ class StatsigE2ETest { } randomUser = StatsigUser("random") - driver = StatsigServer.create("secret-testcase", options) + driver = StatsigServer.create() } @After @@ -225,7 +225,7 @@ class StatsigE2ETest { } private fun featureGateHelper() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) val now = System.currentTimeMillis() assert(driver.checkGate(statsigUser, "always_on_gate")) assert(driver.checkGate(statsigUser, "on_for_statsig_email")) @@ -235,7 +235,6 @@ class StatsigE2ETest { val eventLogInput = withTimeout(TEST_TIMEOUT) { eventLogInputCompletable.await() } - assert(eventLogInput.events.size == 3) assert(eventLogInput.events[0].eventName == "statsig::gate_exposure") assert(eventLogInput.events[0].eventMetadata!!["gate"].equals("always_on_gate")) @@ -268,7 +267,7 @@ class StatsigE2ETest { } private fun dynamicConfigHelper() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) val now = System.currentTimeMillis() var config = driver.getConfig(statsigUser, "test_config") assert(config.getInt("number", 0) == 7) @@ -292,6 +291,12 @@ class StatsigE2ETest { assert(eventLogInput.events[0].eventMetadata!!["config"].equals("test_config")) assert(eventLogInput.events[0].eventMetadata!!["ruleID"].equals("1kNmlB23wylPFZi1M0Divl")) assert(eventLogInput.events[0].time!! / 1000 == now / 1000) + val statsigMetadata = eventLogInput.events[0].statsigMetadata!! + assert(statsigMetadata != null) + assert(statsigMetadata.languageVersion != null) + assert(statsigMetadata.sdkType == "java-server") + assert(statsigMetadata.sessionID != null) + assert(statsigMetadata.exposureLoggingDisabled == null) assert(eventLogInput.events[1].eventName == "statsig::config_exposure") assert(eventLogInput.events[1].eventMetadata!!["config"].equals("test_config")) @@ -311,7 +316,7 @@ class StatsigE2ETest { } private fun experimentHelper() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) val now = System.currentTimeMillis() var config = driver.getExperiment(statsigUser, "sample_experiment") assert(config.getString("experiment_param", "") == "test") @@ -348,7 +353,7 @@ class StatsigE2ETest { } private fun logEventHelper() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) val now = System.currentTimeMillis() driver.logEvent(statsigUser, "purchase", 2.99, mapOf("item_name" to "remove_ads")) driver.shutdown() @@ -375,7 +380,7 @@ class StatsigE2ETest { disableDiagnostics = true } - driver = StatsigServer.create("secret-testcase", options) + driver = StatsigServer.create() backgroundSyncHelper() } @@ -408,7 +413,7 @@ class StatsigE2ETest { } } - driver = StatsigServer.create("secret-testcase", options) + driver = StatsigServer.create() } @Test @@ -439,7 +444,7 @@ class StatsigE2ETest { private fun backgroundSyncHelper(withBootstrap: Boolean = false) = runBlocking { download_list_1_count = 0 download_list_2_count = 0 - driver.initialize() + driver.initialize("secret-testcase", options) val specStore = TestUtil.getSpecStoreFromStatsigServer(driver) diff --git a/src/test/java/com/statsig/sdk/StatsigErrorBoundaryUsage.kt b/src/test/java/com/statsig/sdk/StatsigErrorBoundaryUsage.kt index 8db14ff..3b1f81b 100644 --- a/src/test/java/com/statsig/sdk/StatsigErrorBoundaryUsage.kt +++ b/src/test/java/com/statsig/sdk/StatsigErrorBoundaryUsage.kt @@ -1,9 +1,6 @@ package com.statsig.sdk -import io.mockk.coEvery -import io.mockk.every -import io.mockk.mockkConstructor -import io.mockk.unmockkAll +import io.mockk.* import kotlinx.coroutines.runBlocking import okhttp3.mockwebserver.Dispatcher import okhttp3.mockwebserver.MockResponse @@ -68,14 +65,20 @@ class StatsigErrorBoundaryUsage { } private fun getStatsigInstance(shouldInitialize: Boolean = true) = runBlocking { - val statsig = StatsigServer.create("secret-key", StatsigOptions(api = "http://localhost", disableDiagnostics = true)) + val statsig = spyk(StatsigServer.create()) + every { + statsig.setup(any(), any()) + } answers { + callOriginal() + statsig.errorBoundary.uri = server.url("/v1/sdk_exception").toUri() + } + if (shouldInitialize) { runBlocking { - statsig.initialize() + statsig.initialize("secret-key", StatsigOptions(disableDiagnostics = true)) } } - statsig.errorBoundary.uri = server.url("/v1/sdk_exception").toUri() return@runBlocking statsig } @@ -92,7 +95,7 @@ class StatsigErrorBoundaryUsage { throwOnDownloadConfigSpecs = true runBlocking { - statsig.initialize() + statsig.initialize("secret-key", StatsigOptions(disableDiagnostics = true)) } assertEquals(1, requests.size) diff --git a/src/test/java/com/statsig/sdk/StatsigTimeTest.kt b/src/test/java/com/statsig/sdk/StatsigTimeTest.kt index b521192..7881b7f 100644 --- a/src/test/java/com/statsig/sdk/StatsigTimeTest.kt +++ b/src/test/java/com/statsig/sdk/StatsigTimeTest.kt @@ -95,7 +95,7 @@ class StatsigTimeTest { api = server.url("/v1").toString() } - driver = StatsigServer.create("secret-testcase", options) + driver = StatsigServer.create() } @After @@ -105,7 +105,7 @@ class StatsigTimeTest { @Test fun testAfter() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) val isoUser = StatsigUser("123").apply { email = "testuser@statsig.com" custom = mapOf( @@ -127,7 +127,7 @@ class StatsigTimeTest { @Test fun testBefore() = runBlocking { - driver.initialize() + driver.initialize("secret-testcase", options) val isoUser = StatsigUser("123").apply { email = "testuser@statsig.com" custom = mapOf(