Makes sure the scope is cancelled when the NostrClient is done

This commit is contained in:
Vitor Pamplona
2025-10-03 18:01:34 -04:00
parent 66a5412961
commit 26462a150e
6 changed files with 32 additions and 14 deletions
@@ -21,24 +21,10 @@
package com.vitorpamplona.quartz.nip01Core.relay
import com.vitorpamplona.quartz.nip01Core.relay.sockets.okhttp.BasicOkHttpWebSocket
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import okhttp3.OkHttpClient
import kotlin.test.fail
open class BaseNostrClientTest {
companion object {
// Exists to avoid exceptions stopping the coroutine
val exceptionHandler =
CoroutineExceptionHandler { _, throwable ->
Log.e("AmethystCoroutine", "Caught exception: ${throwable.message}", throwable)
fail("Should not fail")
}
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob() + exceptionHandler)
val rootClient = OkHttpClient.Builder().build()
val socketBuilder = BasicOkHttpWebSocket.Builder { url -> rootClient }
}
@@ -24,6 +24,10 @@ import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.downloadFirstEvent
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.runBlocking
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -32,6 +36,7 @@ class NostrClientFirstEventTest : BaseNostrClientTest() {
@Test
fun testDownloadFirstEvent() =
runBlocking {
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
val client = NostrClient(socketBuilder, appScope)
val event =
@@ -45,6 +50,7 @@ class NostrClientFirstEventTest : BaseNostrClientTest() {
)
client.disconnect()
appScope.cancel()
assertEquals(MetadataEvent.KIND, event?.kind)
assertEquals("460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c", event?.pubKey)
@@ -27,6 +27,10 @@ import com.vitorpamplona.quartz.nip01Core.relay.client.listeners.IRelayClientLis
import com.vitorpamplona.quartz.nip01Core.relay.client.single.IRelayClient
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
import kotlinx.coroutines.runBlocking
@@ -38,6 +42,7 @@ class NostrClientManualSubTest : BaseNostrClientTest() {
@Test
fun testEoseAfter100Events() =
runBlocking {
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
val client = NostrClient(socketBuilder, appScope)
val resultChannel = Channel<String>(UNLIMITED)
@@ -97,6 +102,8 @@ class NostrClientManualSubTest : BaseNostrClientTest() {
client.unsubscribe(listener)
client.disconnect()
appScope.cancel()
assertEquals(101, events.size)
assertEquals(true, events.take(100).all { it.length == 64 })
assertEquals("EOSE", events[100])
@@ -29,6 +29,10 @@ import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent
import com.vitorpamplona.quartz.utils.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
import kotlinx.coroutines.coroutineScope
@@ -42,6 +46,7 @@ class NostrClientRepeatSubTest : BaseNostrClientTest() {
@Test
fun testRepeatSubEvents() =
runBlocking {
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
val client = NostrClient(socketBuilder, appScope)
val resultChannel = Channel<String>(UNLIMITED)
@@ -121,6 +126,8 @@ class NostrClientRepeatSubTest : BaseNostrClientTest() {
client.unsubscribe(listener)
client.disconnect()
appScope.cancel()
assertEquals(202, events.size)
assertEquals(true, events.take(100).all { it.length == 64 })
assertEquals("EOSE", events[100])
@@ -26,6 +26,10 @@ import com.vitorpamplona.quartz.nip01Core.relay.client.accessories.sendAndWaitFo
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.runBlocking
import kotlin.test.Test
import kotlin.test.assertEquals
@@ -34,6 +38,7 @@ class NostrClientSendAndWaitTest : BaseNostrClientTest() {
@Test
fun testSendAndWaitForResponse() =
runBlocking {
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
val client = NostrClient(socketBuilder, appScope)
val randomSigner = NostrSignerInternal(KeyPair())
@@ -53,6 +58,7 @@ class NostrClientSendAndWaitTest : BaseNostrClientTest() {
)
client.disconnect()
appScope.cancel()
assertEquals(true, resultDamus)
assertEquals(false, resultNos)
@@ -26,6 +26,10 @@ import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClientSubscription
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
import kotlinx.coroutines.runBlocking
@@ -37,6 +41,7 @@ class NostrClientSubscriptionTest : BaseNostrClientTest() {
@Test
fun testNostrClientSubscription() =
runBlocking {
val appScope = CoroutineScope(Dispatchers.Default + SupervisorJob())
val client = NostrClient(socketBuilder, appScope)
val resultChannel = Channel<Event>(UNLIMITED)
@@ -73,6 +78,7 @@ class NostrClientSubscriptionTest : BaseNostrClientTest() {
sub.closeSubscription()
client.disconnect()
appScope.cancel()
assertEquals(100, events.size)
}