From de0428a4196c68cc60fbae3bb302ecfcecf1dd73 Mon Sep 17 00:00:00 2001 From: ganfra Date: Mon, 17 Apr 2023 20:17:32 +0200 Subject: [PATCH] [FeatureFlag] add some unittest and fix one case! --- .../impl/DefaultFeatureFlagService.kt | 2 +- .../impl/DefaultFeatureFlagServiceTest.kt | 67 +++++++++++++++++++ .../impl/FakeRuntimeFeatureFlagProvider.kt | 34 ++++++++++ 3 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt create mode 100644 libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/FakeRuntimeFeatureFlagProvider.kt diff --git a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagService.kt b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagService.kt index 28db4f1e35..7298929aea 100644 --- a/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagService.kt +++ b/libraries/featureflag/impl/src/main/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagService.kt @@ -31,7 +31,7 @@ class DefaultFeatureFlagService @Inject constructor( override suspend fun isFeatureEnabled(feature: Feature): Boolean { return providers.filter { it.hasFeature(feature) } - .sortedBy(FeatureFlagProvider::priority) + .sortedByDescending(FeatureFlagProvider::priority) .firstOrNull() ?.isFeatureEnabled(feature) ?: feature.defaultValue diff --git a/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt b/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt new file mode 100644 index 0000000000..5f7f01423a --- /dev/null +++ b/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/DefaultFeatureFlagServiceTest.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.featureflag.impl + +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.featureflag.api.FeatureFlags +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class DefaultFeatureFlagServiceTest { + + @Test + fun `given service without provider when feature is checked then it returns the default value`() = runTest { + val featureFlagService = DefaultFeatureFlagService(emptySet()) + val isFeatureEnabled = featureFlagService.isFeatureEnabled(FeatureFlags.ShowStartChatFlow) + assertThat(isFeatureEnabled).isEqualTo(FeatureFlags.ShowStartChatFlow.defaultValue) + } + + @Test + fun `given service without provider when set enabled feature is called then it returns false`() = runTest { + val featureFlagService = DefaultFeatureFlagService(emptySet()) + val result = featureFlagService.setFeatureEnabled(FeatureFlags.ShowStartChatFlow, true) + assertThat(result).isEqualTo(false) + } + + @Test + fun `given service with a runtime provider when set enabled feature is called then it returns true`() = runTest { + val featureFlagProvider = FakeRuntimeFeatureFlagProvider(0) + val featureFlagService = DefaultFeatureFlagService(setOf(featureFlagProvider)) + val result = featureFlagService.setFeatureEnabled(FeatureFlags.ShowStartChatFlow, true) + assertThat(result).isEqualTo(true) + } + + @Test + fun `given service with a runtime provider and feature enabled when feature is checked then it returns the correct value`() = runTest { + val featureFlagProvider = FakeRuntimeFeatureFlagProvider(0) + val featureFlagService = DefaultFeatureFlagService(setOf(featureFlagProvider)) + featureFlagService.setFeatureEnabled(FeatureFlags.ShowStartChatFlow, true) + assertThat(featureFlagService.isFeatureEnabled(FeatureFlags.ShowStartChatFlow)).isEqualTo(true) + featureFlagService.setFeatureEnabled(FeatureFlags.ShowStartChatFlow, false) + assertThat(featureFlagService.isFeatureEnabled(FeatureFlags.ShowStartChatFlow)).isEqualTo(false) + } + + @Test + fun `given service with 2 runtime providers when feature is checked then it uses the priority correctly`() = runTest { + val lowPriorityfeatureFlagProvider = FakeRuntimeFeatureFlagProvider(LOW_PRIORITY) + val highPriorityfeatureFlagProvider = FakeRuntimeFeatureFlagProvider(HIGH_PRIORITY) + val featureFlagService = DefaultFeatureFlagService(setOf(lowPriorityfeatureFlagProvider, highPriorityfeatureFlagProvider)) + lowPriorityfeatureFlagProvider.setFeatureEnabled(FeatureFlags.ShowStartChatFlow, false) + highPriorityfeatureFlagProvider.setFeatureEnabled(FeatureFlags.ShowStartChatFlow, true) + assertThat(featureFlagService.isFeatureEnabled(FeatureFlags.ShowStartChatFlow)).isEqualTo(true) + } +} diff --git a/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/FakeRuntimeFeatureFlagProvider.kt b/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/FakeRuntimeFeatureFlagProvider.kt new file mode 100644 index 0000000000..5ff5cf932f --- /dev/null +++ b/libraries/featureflag/impl/src/test/kotlin/io/element/android/libraries/featureflag/impl/FakeRuntimeFeatureFlagProvider.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.featureflag.impl + +import io.element.android.libraries.featureflag.api.Feature + +class FakeRuntimeFeatureFlagProvider(override val priority: Int) : RuntimeFeatureFlagProvider { + + private val enabledFeatures = HashMap() + + override suspend fun setFeatureEnabled(feature: Feature, enabled: Boolean) { + enabledFeatures[feature.key] = enabled + } + + override suspend fun isFeatureEnabled(feature: Feature): Boolean { + return enabledFeatures[feature.key] ?: feature.defaultValue + } + + override fun hasFeature(feature: Feature): Boolean = true +}