From 34440c2ecfe57168c6167f12529b4b706f6f75bd Mon Sep 17 00:00:00 2001 From: Nicklas Lundin Date: Sun, 17 Nov 2024 07:56:03 +0100 Subject: [PATCH 1/4] feat: FlagEvalMetadata - add class Signed-off-by: Nicklas Lundin --- .../openfeature/sdk/FlagEvaluationMetadata.kt | 61 +++++++++++++++++++ .../openfeature/sdk/EvaluationMetadataTest.kt | 41 +++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 android/src/main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt create mode 100644 android/src/test/java/dev/openfeature/sdk/EvaluationMetadataTest.kt diff --git a/android/src/main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt b/android/src/main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt new file mode 100644 index 0000000..1790a9c --- /dev/null +++ b/android/src/main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt @@ -0,0 +1,61 @@ +package dev.openfeature.sdk + +class EvaluationMetadata internal constructor(private val values: Map) { + + fun getString(key: String): String? = values[key] as? String + + fun getBoolean(key: String): Boolean? = values[key] as? Boolean + + fun getInt(key: String): Int? = values[key] as? Int + + fun getDouble(key: String): Double? = values[key] as? Double + + fun getAny(key: String): Any? = values[key] + + companion object { + fun builder(): Builder { + return Builder() + } + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as EvaluationMetadata + + return values == other.values + } + + override fun hashCode(): Int { + return values.hashCode() + } +} + +class Builder { + private val values: MutableMap = mutableMapOf() + + fun putString(key: String, value: String): Builder { + values[key] = value + return this + } + + fun putInt(key: String, value: Int): Builder { + values[key] = value + return this + } + + fun putDouble(key: String, value: Double): Builder { + values[key] = value + return this + } + + fun putBoolean(key: String, value: Boolean): Builder { + values[key] = value + return this + } + + fun build(): EvaluationMetadata { + return EvaluationMetadata(values.toMap()) + } +} \ No newline at end of file diff --git a/android/src/test/java/dev/openfeature/sdk/EvaluationMetadataTest.kt b/android/src/test/java/dev/openfeature/sdk/EvaluationMetadataTest.kt new file mode 100644 index 0000000..0320015 --- /dev/null +++ b/android/src/test/java/dev/openfeature/sdk/EvaluationMetadataTest.kt @@ -0,0 +1,41 @@ +package dev.openfeature.sdk + +import org.junit.Assert +import org.junit.Test + +class EvaluationMetadataTest { + + private val metadata = EvaluationMetadata.builder() + .putString("key1", "value1") + .putInt("key2", 42) + .putBoolean("key3", true) + .putDouble("key4", 2.71828) + .build() + + @Test + fun testAddAndGet() { + Assert.assertEquals("value1", metadata.getString("key1")) + Assert.assertEquals(42, metadata.getInt("key2")) + Assert.assertEquals(true, metadata.getBoolean("key3")) + Assert.assertEquals(2.71828, metadata.getDouble("key4")) + } + + @Test + fun testGetNonExistentKey() { + Assert.assertNull(metadata.getString("key5")) + } + + @Test + fun testInvalidType() { + Assert.assertNull(metadata.getString("key2")) + Assert.assertNull(metadata.getInt("key3")) + Assert.assertNull(metadata.getBoolean("key4")) + Assert.assertNull(metadata.getDouble("key1")) + } + + @Test + fun testGetAny() { + val any: Any? = metadata.getAny("key1") + Assert.assertEquals("value1", any as? String) + } +} \ No newline at end of file From f7a5e3dc592fc0d204a4d9a151287c9494bae873 Mon Sep 17 00:00:00 2001 From: Nicklas Lundin Date: Sun, 17 Nov 2024 08:07:22 +0100 Subject: [PATCH 2/4] refactor: remove unecessary interface Signed-off-by: Nicklas Lundin --- .../dev/openfeature/sdk/FlagEvaluationDetails.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/android/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.kt b/android/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.kt index 4851f3e..f664ec2 100644 --- a/android/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.kt +++ b/android/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.kt @@ -4,12 +4,12 @@ import dev.openfeature.sdk.exceptions.ErrorCode data class FlagEvaluationDetails( val flagKey: String, - override val value: T, - override val variant: String? = null, - override val reason: String? = null, - override val errorCode: ErrorCode? = null, - override val errorMessage: String? = null -) : BaseEvaluation { + val value: T, + val variant: String? = null, + val reason: String? = null, + val errorCode: ErrorCode? = null, + val errorMessage: String? = null +) { companion object } From 3e755def326b1516850249938067577cb96d644d Mon Sep 17 00:00:00 2001 From: Nicklas Lundin Date: Sun, 17 Nov 2024 08:25:22 +0100 Subject: [PATCH 3/4] feat: add evaluation metadata to evaluation details Signed-off-by: Nicklas Lundin --- .../dev/openfeature/sdk/FlagEvaluationDetails.kt | 16 +++++++++------- .../openfeature/sdk/FlagEvaluationMetadata.kt | 2 ++ .../dev/openfeature/sdk/ProviderEvaluation.kt | 3 ++- .../dev/openfeature/sdk/FlagEvaluationsTests.kt | 15 ++++++++++++++- .../sdk/helpers/DoSomethingProvider.kt | 12 +++++++++++- 5 files changed, 38 insertions(+), 10 deletions(-) diff --git a/android/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.kt b/android/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.kt index f664ec2..ddea059 100644 --- a/android/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.kt +++ b/android/src/main/java/dev/openfeature/sdk/FlagEvaluationDetails.kt @@ -8,7 +8,8 @@ data class FlagEvaluationDetails( val variant: String? = null, val reason: String? = null, val errorCode: ErrorCode? = null, - val errorMessage: String? = null + val errorMessage: String? = null, + val metadata: EvaluationMetadata = EvaluationMetadata.EMPTY ) { companion object } @@ -18,11 +19,12 @@ fun FlagEvaluationDetails.Companion.from( flagKey: String ): FlagEvaluationDetails { return FlagEvaluationDetails( - flagKey, - providerEval.value, - providerEval.variant, - providerEval.reason, - providerEval.errorCode, - providerEval.errorMessage + flagKey = flagKey, + value = providerEval.value, + variant = providerEval.variant, + reason = providerEval.reason, + errorCode = providerEval.errorCode, + errorMessage = providerEval.errorMessage, + metadata = providerEval.metadata ) } \ No newline at end of file diff --git a/android/src/main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt b/android/src/main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt index 1790a9c..f97745a 100644 --- a/android/src/main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt +++ b/android/src/main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt @@ -16,6 +16,8 @@ class EvaluationMetadata internal constructor(private val values: Map( val variant: String? = null, val reason: String? = null, val errorCode: ErrorCode? = null, - val errorMessage: String? = null + val errorMessage: String? = null, + val metadata: EvaluationMetadata = EvaluationMetadata.EMPTY ) \ No newline at end of file diff --git a/android/src/test/java/dev/openfeature/sdk/FlagEvaluationsTests.kt b/android/src/test/java/dev/openfeature/sdk/FlagEvaluationsTests.kt index 9b3991b..be661f6 100644 --- a/android/src/test/java/dev/openfeature/sdk/FlagEvaluationsTests.kt +++ b/android/src/test/java/dev/openfeature/sdk/FlagEvaluationsTests.kt @@ -76,7 +76,8 @@ class FlagEvaluationsTests { Assert.assertEquals(booleanDetails, client.getBooleanDetails(key, false)) Assert.assertEquals(booleanDetails, client.getBooleanDetails(key, false, FlagEvaluationOptions())) - val stringDetails = FlagEvaluationDetails(key, "tset") + // in DoSomethingProvider, the string evaluation is special since it contains some metadata values + val stringDetails = FlagEvaluationDetails(key, "tset", metadata = DoSomethingProvider.evaluationMetadata) Assert.assertEquals(stringDetails, client.getStringDetails(key, "test")) Assert.assertEquals(stringDetails, client.getStringDetails(key, "test", FlagEvaluationOptions())) @@ -93,6 +94,18 @@ class FlagEvaluationsTests { Assert.assertEquals(objectDetails, client.getObjectDetails(key, Value.Structure(mapOf()), FlagEvaluationOptions())) } + @Test + fun testMetadataFlagEvaluation() = runTest { + OpenFeatureAPI.setProvider(DoSomethingProvider()) + val client = OpenFeatureAPI.getClient() + val key = "key" + + val details = client.getStringDetails(key, "default") + val metadata: EvaluationMetadata = details.metadata + Assert.assertEquals("value1", metadata.getString("key1")) + Assert.assertEquals(42, metadata.getInt("key2")) + } + @Test fun testHooksAreFired() = runTest { OpenFeatureAPI.setProvider(NoOpProvider()) diff --git a/android/src/test/java/dev/openfeature/sdk/helpers/DoSomethingProvider.kt b/android/src/test/java/dev/openfeature/sdk/helpers/DoSomethingProvider.kt index 44c1c1a..71d4ca6 100644 --- a/android/src/test/java/dev/openfeature/sdk/helpers/DoSomethingProvider.kt +++ b/android/src/test/java/dev/openfeature/sdk/helpers/DoSomethingProvider.kt @@ -1,6 +1,7 @@ package dev.openfeature.sdk.helpers import dev.openfeature.sdk.EvaluationContext +import dev.openfeature.sdk.EvaluationMetadata import dev.openfeature.sdk.FeatureProvider import dev.openfeature.sdk.Hook import dev.openfeature.sdk.ProviderEvaluation @@ -19,6 +20,12 @@ class DoSomethingProvider( override val metadata: ProviderMetadata = DoSomethingProviderMetadata(), private var dispatcher: CoroutineDispatcher = Dispatchers.IO ) : FeatureProvider { + companion object { + val evaluationMetadata = EvaluationMetadata.builder() + .putString("key1", "value1") + .putInt("key2", 42) + .build() + } private var eventHandler = EventHandler(dispatcher) override fun initialize(initialContext: EvaluationContext?) { @@ -51,7 +58,10 @@ class DoSomethingProvider( defaultValue: String, context: EvaluationContext? ): ProviderEvaluation { - return ProviderEvaluation(defaultValue.reversed()) + return ProviderEvaluation( + value = defaultValue.reversed(), + metadata = evaluationMetadata + ) } override fun getIntegerEvaluation( From 586fc20afed48527cb4974d4a1931bbd6a03db20 Mon Sep 17 00:00:00 2001 From: Nicklas Lundin Date: Mon, 18 Nov 2024 15:37:53 +0100 Subject: [PATCH 4/4] fixup! feat: FlagEvalMetadata - add class Signed-off-by: Nicklas Lundin --- .../main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt | 2 -- .../test/java/dev/openfeature/sdk/EvaluationMetadataTest.kt | 6 ------ 2 files changed, 8 deletions(-) diff --git a/android/src/main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt b/android/src/main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt index f97745a..011b8cb 100644 --- a/android/src/main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt +++ b/android/src/main/java/dev/openfeature/sdk/FlagEvaluationMetadata.kt @@ -10,8 +10,6 @@ class EvaluationMetadata internal constructor(private val values: Map