Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: enforce test coverage #178

Merged
merged 3 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Confidence/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ plugins {
id("signing")
kotlin("plugin.serialization").version("1.8.10").apply(true)
id("org.jetbrains.kotlinx.binary-compatibility-validator")
id("org.jetbrains.kotlinx.kover")
}

val providerVersion = project.extra["version"].toString()
Expand Down Expand Up @@ -120,4 +121,14 @@ publishing {

signing {
sign(publishing.publications["release"])
}

kover {
reports {
verify {
rule {
minBound(78)
}
}
}
}
11 changes: 11 additions & 0 deletions Provider/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ plugins {
kotlin("plugin.serialization")
id("signing")
id("org.jetbrains.kotlinx.binary-compatibility-validator")
id("org.jetbrains.kotlinx.kover")
}

object Versions {
Expand Down Expand Up @@ -122,4 +123,14 @@ publishing {

signing {
sign(publishing.publications["release"])
}

kover {
reports {
verify {
rule {
minBound(80)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package com.spotify.confidence.openfeature

import com.spotify.confidence.ConfidenceValue
import dev.openfeature.sdk.Value
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test

class ConfidenceValueMappingsTest {

@Test
fun confidenceStringToValueString() {
val confidenceValue = ConfidenceValue.String("test")
val value = confidenceValue.toValue()
assertEquals("test", value.asString())
assertNull(value.asInteger())
assertNull(value.asDate())
assertNull(value.asBoolean())
assertNull(value.asStructure())
}

@Test
fun confidenceDoubleToValueDouble() {
val confidenceValue = ConfidenceValue.Double(1.23)
val value = confidenceValue.toValue()
assertEquals(1.23, value.asDouble()!!, 0.001)
assertNull(value.asString())
assertNull(value.asInteger())
assertNull(value.asDate())
assertNull(value.asBoolean())
assertNull(value.asStructure())
}

@Test
fun confidenceBooleanToValueBoolean() {
val confidenceValue = ConfidenceValue.Boolean(true)
val value = confidenceValue.toValue()
assertEquals(true, value.asBoolean())
assertNull(value.asString())
assertNull(value.asDouble())
assertNull(value.asDate())
assertNull(value.asInteger())
assertNull(value.asStructure())
}

@Test
fun confidenceIntegerToValueInteger() {
val confidenceValue = ConfidenceValue.Integer(42)
val value = confidenceValue.toValue()
assertEquals(42, value.asInteger())
assertNull(value.asString())
assertNull(value.asDouble())
assertNull(value.asDate())
assertNull(value.asBoolean())
assertNull(value.asStructure())
}

@Test
fun confidenceStructToValueStructure() {
val confidenceValue = ConfidenceValue.Struct(mapOf("key" to ConfidenceValue.String("value")))
val value = confidenceValue.toValue()
assertEquals(mapOf("key" to dev.openfeature.sdk.Value.String("value")), value.asStructure())
assertNull(value.asString())
assertNull(value.asDouble())
assertNull(value.asDate())
assertNull(value.asBoolean())
assertNull(value.asList())
}

@Test
fun confidenceListToValueList() {
val confidenceValue = ConfidenceValue.List(listOf(ConfidenceValue.String("item")))
val value = confidenceValue.toValue()
assertEquals(listOf(dev.openfeature.sdk.Value.String("item")), value.asList())
assertNull(value.asString())
assertNull(value.asDouble())
assertNull(value.asDate())
assertNull(value.asBoolean())
assertNull(value.asStructure())
}

@Test
fun confidenceDateToValueDate() {
val date = java.util.Date()
val confidenceValue = ConfidenceValue.Date(date)
val value = confidenceValue.toValue()
assertEquals(date, value.asDate())
assertNull(value.asString())
assertNull(value.asDouble())
assertNull(value.asBoolean())
assertNull(value.asInteger())
assertNull(value.asStructure())
}

@Test
fun confidenceTimestampToValueTimestamp() {
val timestamp = java.util.Date()
val confidenceValue = ConfidenceValue.Timestamp(timestamp)
val value = confidenceValue.toValue()
assertEquals(timestamp.time, value.asDate()!!.time)
assertNull(value.asString())
assertNull(value.asDouble())
assertNull(value.asBoolean())
assertNull(value.asInteger())
assertNull(value.asStructure())
}

@Test
fun confidenceNullToValueNull() {
val confidenceValue = ConfidenceValue.Null
val value = confidenceValue.toValue()
assertEquals(Value.Null, value)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import dev.openfeature.sdk.Reason
import dev.openfeature.sdk.Value
import dev.openfeature.sdk.events.EventHandler
import dev.openfeature.sdk.events.OpenFeatureEvents
import dev.openfeature.sdk.exceptions.ErrorCode
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import org.junit.Assert.assertEquals
Expand All @@ -28,7 +29,7 @@ import java.util.UUID
private const val clientSecret = "21wxcxXpU6tKBRFtEFTXYiH7nDqL86Mm"
private val mockContext: Context = mock()

class ConfidenceIntegrationTests {
class ProviderIntegrationTest {

@get:Rule
var tmpFile = TemporaryFolder()
Expand Down Expand Up @@ -85,7 +86,7 @@ class ConfidenceIntegrationTests {
val eventsHandler = EventHandler(Dispatchers.IO).apply {
publish(OpenFeatureEvents.ProviderStale)
}
val cacheFile = File(mockContext.filesDir, FLAGS_FILE_NAME)
val cacheFile = File(mockContext.filesDir, flagsFileName)
assertEquals(0L, cacheFile.length())
val mockConfidence = ConfidenceFactory.create(mockContext, clientSecret)
OpenFeatureAPI.setProvider(
Expand Down Expand Up @@ -118,5 +119,62 @@ class ConfidenceIntegrationTests {
assertEquals(Reason.TARGETING_MATCH.name, intDetails.reason)
assertNotNull(intDetails.variant)
}
}
internal const val FLAGS_FILE_NAME = "confidence_flags_cache.json"

@Test
fun testSimpleResolveWithFetchAndActivateInMemoryCache() {
val eventsHandler = EventHandler(Dispatchers.IO).apply {
publish(OpenFeatureEvents.ProviderStale)
}
val mockConfidence = ConfidenceFactory.create(mockContext, clientSecret)

OpenFeatureAPI.setProvider(
ConfidenceFeatureProvider.create(
confidence = mockConfidence,
initialisationStrategy = InitialisationStrategy.ActivateAndFetchAsync,
eventHandler = eventsHandler
),
ImmutableContext(
targetingKey = UUID.randomUUID().toString(),
attributes = mutableMapOf(
"user" to Value.Structure(
mapOf(
"country" to Value.String("SE")
)
)
)
)
)
runBlocking {
awaitProviderReady(eventsHandler = eventsHandler)
}

val flagNotFoundDetails = OpenFeatureAPI.getClient()
.getObjectDetails(
"kotlin-test-flag",
Value.Structure(emptyMap())
)
assertEquals(ErrorCode.FLAG_NOT_FOUND, flagNotFoundDetails.errorCode)
assertNull(flagNotFoundDetails.errorMessage)
assertEquals(Value.Structure(emptyMap()), flagNotFoundDetails.value)
assertEquals(Reason.ERROR.name, flagNotFoundDetails.reason)
assertNull(flagNotFoundDetails.variant)

runBlocking {
mockConfidence.fetchAndActivate()
}

val evaluationDetails = OpenFeatureAPI.getClient()
.getObjectDetails(
"kotlin-test-flag",
Value.Structure(emptyMap())
)
assertNull(evaluationDetails.errorCode)
assertNull(evaluationDetails.errorMessage)
assertNotNull(evaluationDetails.value)
assertEquals(Reason.TARGETING_MATCH.name, evaluationDetails.reason)
assertNotNull(evaluationDetails.variant)

assertEquals(4, evaluationDetails.value.asStructure()?.getOrDefault("my-integer", Value.Integer(-1))?.asInteger())
}
private val flagsFileName = "confidence_flags_cache.json"
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ suspend fun awaitProviderReady(
dispatcher: CoroutineDispatcher = Dispatchers.IO
) = suspendCancellableCoroutine { continuation ->
fun observeProviderReady() = eventsHandler
.observe<OpenFeatureEvents.ProviderReady>()
.observe<OpenFeatureEvents>()
.onStart {
if (eventsHandler.getProviderStatus() == OpenFeatureEvents.ProviderReady) {
this.emit(OpenFeatureEvents.ProviderReady)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.spotify.confidence.openfeature

import com.spotify.confidence.ConfidenceValue
import dev.openfeature.sdk.Value
import org.junit.Assert.assertEquals
import org.junit.Test

class ValueMappingsTest {

@Test
fun openFeatureStringValueToConfidenceValueString() {
val value = Value.String("test")
val confidenceValue: ConfidenceValue = value.toConfidenceValue()
assertEquals("test", confidenceValue.asString()?.string)
}

@Test
fun openFeatureDoubleValueToConfidenceValueDouble() {
val value = Value.Double(1.23)
val confidenceValue: ConfidenceValue = value.toConfidenceValue()
assertEquals(1.23, confidenceValue.asDouble()?.double!!, 0.001)
}

@Test
fun openFeatureBooleanValueToConfidenceValueBoolean() {
val value = Value.Boolean(true)
val confidenceValue: ConfidenceValue = value.toConfidenceValue()
assertEquals(true, confidenceValue.asBoolean()?.boolean)
}

@Test
fun openFeatureIntegerValueToConfidenceValueInteger() {
val value = Value.Integer(42)
val confidenceValue: ConfidenceValue = value.toConfidenceValue()
assertEquals(42, confidenceValue.asInteger()?.integer)
}

@Test
fun openFeatureStructureValueToConfidenceValueStruct() {
val value = Value.Structure(mapOf("key" to Value.String("value")))
val confidenceValue: ConfidenceValue = value.toConfidenceValue()
assertEquals("value", confidenceValue.asStructure()?.map?.get("key")?.asString()?.string)
}

@Test
fun openFeatureListValueToConfidenceValueList() {
val value = Value.List(listOf(Value.String("value")))
val confidenceValue: ConfidenceValue = value.toConfidenceValue()
assertEquals("value", confidenceValue.asList()?.list?.get(0)?.asString()?.string)
}

@Test
fun mixedListShouldReturnEmptyConfidenceList() {
val value = Value.List(listOf(Value.String("value"), Value.Integer(42)))
val confidenceValue: ConfidenceValue = value.toConfidenceValue()
assertEquals(0, confidenceValue.asList()?.list?.size)
}

private fun ConfidenceValue.asString(): ConfidenceValue.String? {
return this as? ConfidenceValue.String
}

private fun ConfidenceValue.asDouble(): ConfidenceValue.Double? {
return this as? ConfidenceValue.Double
}

private fun ConfidenceValue.asBoolean(): ConfidenceValue.Boolean? {
return this as? ConfidenceValue.Boolean
}

private fun ConfidenceValue.asInteger(): ConfidenceValue.Integer? {
return this as? ConfidenceValue.Integer
}

private fun ConfidenceValue.asStructure(): ConfidenceValue.Struct? {
return this as? ConfidenceValue.Struct
}

private fun ConfidenceValue.asList(): ConfidenceValue.List? {
return this as? ConfidenceValue.List
}
}
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ plugins {
id("com.android.application") version "7.4.2" apply false
id("io.github.gradle-nexus.publish-plugin").version("1.3.0").apply(true)
id("org.jetbrains.kotlinx.binary-compatibility-validator").version("0.15.0-Beta.3").apply(false)
id("org.jetbrains.kotlinx.kover").version("0.8.2").apply(true)
}

allprojects {
Expand Down
Loading