libeufin

Integration and sandbox testing for FinTech APIs and data formats
Log | Files | Refs | Submodules | README | LICENSE

commit 87d5e21cdcb554531e12c57ca6c73d99daf3e3a8
parent bb96fd4f635cd9b760363acc7aacb9f7d890cf89
Author: MS <ms@taler.net>
Date:   Sat, 22 Apr 2023 10:02:43 +0200

Conversion service tests.

Fixing job cancellation.

Diffstat:
Mnexus/src/test/kotlin/ConversionServiceTest.kt | 61+++++++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 43 insertions(+), 18 deletions(-)

diff --git a/nexus/src/test/kotlin/ConversionServiceTest.kt b/nexus/src/test/kotlin/ConversionServiceTest.kt @@ -10,9 +10,6 @@ import tech.libeufin.nexus.server.nexusApp import tech.libeufin.sandbox.* class ConversionServiceTest { - // Without this, "launch {}" never returns. - val doNothingHandler = CoroutineExceptionHandler { _, _ -> } - /** * Testing the buy-in monitor in the normal case: Nexus * communicates a new incoming fiat transaction and the @@ -44,15 +41,24 @@ class ConversionServiceTest { testApplication { application(nexusApp) // Start the buy-in monitor to let it download the fiat transaction. - val job = CoroutineScope(Dispatchers.IO).launch(doNothingHandler) { - buyinMonitor( - demobankName = "default", - accountToCredit = "exchange-0", - client = client - ) + runBlocking { + val job = launch { + /** + * The runInterruptible wrapper lets code without suspension + * points be cancel()'d. Without it, such code would ignore + * any call to cancel() and the test never return. + */ + runInterruptible { + buyinMonitor( + demobankName = "default", + accountToCredit = "exchange-0", + client = client + ) + } + } + delay(1000L) // Lets the DB persist. + job.cancelAndJoin() } - delay(1000L) - job.cancel() } // Checking that exchange got the converted amount. transaction { @@ -95,15 +101,34 @@ class ConversionServiceTest { ) testApplication { application(nexusApp) - CoroutineScope(Dispatchers.IO).launch(doNothingHandler) { - cashoutMonitor(client) - } - delay(1000L) // Lets DB persist the information. - transaction { - assert(CashoutSubmissionEntity.all().count() == 1L) - assert(CashoutSubmissionEntity.all().first().isSubmitted) + runBlocking { + val job = launch { + /** + * The runInterruptible wrapper lets code without suspension + * points be cancel()'d. Without it, such code would ignore + * any call to cancel() and the test never return. + */ + runInterruptible { + /** + * Without the runBlocking wrapper, cashoutMonitor doesn't + * compile. That's because it is a 'suspend' function and + * it needs a coroutine environment to execute; runInterruptible + * does NOT provide one. Furthermore, replacing runBlocking + * with "launch {}" would nullify runInterruptible, due to other + * jobs that cashoutMonitor internally launches and would escape + * the interruptible policy. + */ + runBlocking { cashoutMonitor(client) } + } + } + delay(1000L) // Lets DB persist the information. + job.cancelAndJoin() } } + transaction { + assert(CashoutSubmissionEntity.all().count() == 1L) + assert(CashoutSubmissionEntity.all().first().isSubmitted) + } } }