From aa665d48c0d26ab8d35ad6c107c0df188a1ca405 Mon Sep 17 00:00:00 2001 From: Nicklas Lundin Date: Thu, 5 Oct 2023 13:41:46 +0200 Subject: [PATCH] test: fix issue with leaking events between tests (#74) * test: fix issue with leaking events between tests * await provider ready using specified EventsHandler --- .../confidence/ConfidenceIntegrationTests.kt | 26 +++++++++---- .../confidence/StorageFileCacheTests.kt | 3 ++ .../com/spotify/confidence/TestExtensions.kt | 39 +++++++++++++++++++ 3 files changed, 60 insertions(+), 8 deletions(-) create mode 100644 Provider/src/test/java/com/spotify/confidence/TestExtensions.kt diff --git a/Provider/src/test/java/com/spotify/confidence/ConfidenceIntegrationTests.kt b/Provider/src/test/java/com/spotify/confidence/ConfidenceIntegrationTests.kt index e00526b3..6daa4436 100644 --- a/Provider/src/test/java/com/spotify/confidence/ConfidenceIntegrationTests.kt +++ b/Provider/src/test/java/com/spotify/confidence/ConfidenceIntegrationTests.kt @@ -10,9 +10,9 @@ import dev.openfeature.sdk.ImmutableStructure import dev.openfeature.sdk.OpenFeatureAPI import dev.openfeature.sdk.Reason import dev.openfeature.sdk.Value -import dev.openfeature.sdk.async.awaitProviderReady import dev.openfeature.sdk.events.EventHandler import dev.openfeature.sdk.events.OpenFeatureEvents +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runBlocking import org.junit.Assert.assertEquals import org.junit.Assert.assertNotEquals @@ -33,7 +33,6 @@ class ConfidenceIntegrationTests { @Before fun setup() { whenever(mockContext.filesDir).thenReturn(Files.createTempDirectory("tmpTests").toFile()) - EventHandler.eventsPublisher().publish(OpenFeatureEvents.ProviderStale) } @Test @@ -73,16 +72,20 @@ class ConfidenceIntegrationTests { ) } + val eventsHandler = EventHandler(Dispatchers.IO).apply { + publish(OpenFeatureEvents.ProviderStale) + } OpenFeatureAPI.setProvider( ConfidenceFeatureProvider.create( mockContext, clientSecret, - initialisationStrategy = InitialisationStrategy.ActivateAndFetchAsync + initialisationStrategy = InitialisationStrategy.ActivateAndFetchAsync, + eventsPublisher = eventsHandler ), context ) runBlocking { - awaitProviderReady() + awaitProviderReady(eventsHandler = eventsHandler) } val intDetails = OpenFeatureAPI.getClient() @@ -100,11 +103,15 @@ class ConfidenceIntegrationTests { @Test fun testSimpleResolveInMemoryCache() { + val eventsHandler = EventHandler(Dispatchers.IO).apply { + publish(OpenFeatureEvents.ProviderStale) + } OpenFeatureAPI.setProvider( ConfidenceFeatureProvider.create( mockContext, clientSecret, - initialisationStrategy = InitialisationStrategy.FetchAndActivate + initialisationStrategy = InitialisationStrategy.FetchAndActivate, + eventsPublisher = eventsHandler ), ImmutableContext( targetingKey = UUID.randomUUID().toString(), @@ -118,7 +125,7 @@ class ConfidenceIntegrationTests { ) ) runBlocking { - awaitProviderReady() + awaitProviderReady(eventsHandler = eventsHandler) } val intDetails = OpenFeatureAPI.getClient() @@ -136,10 +143,13 @@ class ConfidenceIntegrationTests { @Test fun testSimpleResolveStoredCache() { + val eventsHandler = EventHandler(Dispatchers.IO).apply { + publish(OpenFeatureEvents.ProviderStale) + } val cacheFile = File(mockContext.filesDir, FLAGS_FILE_NAME) assertEquals(0L, cacheFile.length()) OpenFeatureAPI.setProvider( - ConfidenceFeatureProvider.create(mockContext, clientSecret), + ConfidenceFeatureProvider.create(mockContext, clientSecret, eventsPublisher = eventsHandler), ImmutableContext( targetingKey = UUID.randomUUID().toString(), attributes = mutableMapOf( @@ -153,7 +163,7 @@ class ConfidenceIntegrationTests { ) runBlocking { - awaitProviderReady() + awaitProviderReady(eventsHandler = eventsHandler) } assertNotEquals(0L, cacheFile.length()) diff --git a/Provider/src/test/java/com/spotify/confidence/StorageFileCacheTests.kt b/Provider/src/test/java/com/spotify/confidence/StorageFileCacheTests.kt index f68c5446..c8bb0f28 100644 --- a/Provider/src/test/java/com/spotify/confidence/StorageFileCacheTests.kt +++ b/Provider/src/test/java/com/spotify/confidence/StorageFileCacheTests.kt @@ -1,3 +1,5 @@ +@file:OptIn(ExperimentalCoroutinesApi::class) + package com.spotify.confidence import android.content.Context @@ -16,6 +18,7 @@ import dev.openfeature.sdk.async.awaitProviderReady import dev.openfeature.sdk.events.EventHandler import dev.openfeature.sdk.events.OpenFeatureEvents import junit.framework.TestCase +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest diff --git a/Provider/src/test/java/com/spotify/confidence/TestExtensions.kt b/Provider/src/test/java/com/spotify/confidence/TestExtensions.kt new file mode 100644 index 00000000..c1405c17 --- /dev/null +++ b/Provider/src/test/java/com/spotify/confidence/TestExtensions.kt @@ -0,0 +1,39 @@ +package com.spotify.confidence + +import dev.openfeature.sdk.events.EventHandler +import dev.openfeature.sdk.events.OpenFeatureEvents +import dev.openfeature.sdk.events.observe +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.flow.take +import kotlinx.coroutines.launch +import kotlinx.coroutines.suspendCancellableCoroutine + +suspend fun awaitProviderReady( + + eventsHandler: EventHandler, + + dispatcher: CoroutineDispatcher = Dispatchers.IO + +) = suspendCancellableCoroutine { continuation -> + + fun observeProviderReady() = eventsHandler + .observe() + .onStart { + if (eventsHandler.isProviderReady()) { + this.emit(OpenFeatureEvents.ProviderReady) + } + } + + val coroutineScope = CoroutineScope(dispatcher) + + coroutineScope.launch { + observeProviderReady() + .take(1) + .collect { + continuation.resumeWith(Result.success(Unit)) + } + } +} \ No newline at end of file