libeufin

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

commit fec38bd1934f3da7cc94872dfe6bc6679b9e92f9
parent 2f4ac08b02f763a941d1ee0154ff6e2ed5b9c024
Author: Antoine A <>
Date:   Tue,  6 Feb 2024 16:11:41 +0100

Make more config values mandatory

Diffstat:
Mbank/conf/test.conf | 3+++
Mbank/conf/test_bonus.conf | 3+++
Mbank/conf/test_no_conversion.conf | 3+++
Mbank/conf/test_restrict.conf | 3+++
Mbank/conf/test_tan_err.conf | 3+++
Mbank/conf/test_x_taler_bank.conf | 5+++--
Mcommon/src/main/kotlin/TalerConfig.kt | 9++++++---
Mcontrib/bank.conf | 10+++++-----
Mcontrib/nexus.conf | 23++++++++++++++---------
Mnexus/conf/test.conf | 4+++-
Mnexus/src/test/kotlin/Common.kt | 64+++++++++++++++++++++++++---------------------------------------
Mnexus/src/test/kotlin/ConfigLoading.kt | 17-----------------
Mnexus/src/test/kotlin/DatabaseTest.kt | 380+++++++++++++++++++++++++++++++++++++------------------------------------------
Mnexus/src/test/kotlin/Ebics.kt | 18++++++++----------
Mtestbench/conf/integration.conf | 25+++++++++++++++++++++----
Mtestbench/conf/mini.conf | 22++++++++++++++++++++++
16 files changed, 300 insertions(+), 292 deletions(-)

diff --git a/bank/conf/test.conf b/bank/conf/test.conf @@ -1,4 +1,7 @@ [libeufin-bank] +CURRENCY = KUDOS +WIRE_TYPE = iban +IBAN_PAYTO_BIC = SANDBOXX DEFAULT_DEBT_LIMIT = KUDOS:100 SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com ALLOW_REGISTRATION = yes diff --git a/bank/conf/test_bonus.conf b/bank/conf/test_bonus.conf @@ -1,4 +1,7 @@ [libeufin-bank] +CURRENCY = KUDOS +WIRE_TYPE = iban +IBAN_PAYTO_BIC = SANDBOXX REGISTRATION_BONUS = KUDOS:100 ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes diff --git a/bank/conf/test_no_conversion.conf b/bank/conf/test_no_conversion.conf @@ -1,4 +1,7 @@ [libeufin-bank] +CURRENCY = KUDOS +WIRE_TYPE = iban +IBAN_PAYTO_BIC = SANDBOXX ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes diff --git a/bank/conf/test_restrict.conf b/bank/conf/test_restrict.conf @@ -1,4 +1,7 @@ [libeufin-bank] +CURRENCY = KUDOS +WIRE_TYPE = iban +IBAN_PAYTO_BIC = SANDBOXX DEFAULT_DEBT_LIMIT = KUDOS:100 allow_conversion = YES FIAT_CURRENCY = EUR diff --git a/bank/conf/test_tan_err.conf b/bank/conf/test_tan_err.conf @@ -1,4 +1,7 @@ [libeufin-bank] +CURRENCY = KUDOS +WIRE_TYPE = iban +IBAN_PAYTO_BIC = SANDBOXX DEFAULT_DEBT_LIMIT = KUDOS:100 SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com allow_conversion = YES diff --git a/bank/conf/test_x_taler_bank.conf b/bank/conf/test_x_taler_bank.conf @@ -1,12 +1,13 @@ [libeufin-bank] +CURRENCY = KUDOS +WIRE_TYPE = x-taler-bank +X_TALER_BANK_PAYTO_HOSTNAME = bank.hostname.test DEFAULT_DEBT_LIMIT = KUDOS:100 SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes ALLOW_EDIT_NAME = yes ALLOW_EDIT_CASHOUT_PAYTO_URI = yes -WIRE_TYPE = x-taler-bank -X_TALER_BANK_PAYTO_HOSTNAME = bank.hostname.test [libeufin-bankdb-postgres] CONFIG = postgresql:///libeufincheck diff --git a/common/src/main/kotlin/TalerConfig.kt b/common/src/main/kotlin/TalerConfig.kt @@ -38,10 +38,10 @@ private val reDirective = Regex("^\\s*@([a-zA-Z-_]+)@\\s*(.*?)\\s*$") class TalerConfigError private constructor (m: String) : Exception(m) { companion object { - fun missing(type: String, option: String, section: String): TalerConfigError = + fun missing(type: String, section: String, option: String): TalerConfigError = TalerConfigError("Missing $type option '$option' in section '$section'") - fun invalid(type: String, option: String, section: String, err: String): TalerConfigError = + fun invalid(type: String, section: String, option: String, err: String): TalerConfigError = TalerConfigError("Expected $type option '$option' in section '$section': $err") fun generic(msg: String): TalerConfigError = @@ -430,7 +430,10 @@ class TalerConfig internal constructor( fun lookupString(section: String, option: String): String? { val canonSection = section.uppercase() val canonOption = option.uppercase() - return this.sectionMap[canonSection]?.entries?.get(canonOption) + val str = this.sectionMap[canonSection]?.entries?.get(canonOption) + if (str == null) return null + if (str == "") return null + return str } fun requireString(section: String, option: String): String = diff --git a/contrib/bank.conf b/contrib/bank.conf @@ -1,15 +1,15 @@ [libeufin-bank] # Internal currency of the libeufin-bank -CURRENCY = KUDOS +CURRENCY = # Supported payment target type, this can either be iban or x-taler-bank -WIRE_TYPE = iban +WIRE_TYPE = -# Bank BIC used in generated iban payto URI -IBAN_PAYTO_BIC = SANDBOXX +# Bank BIC used in generated iban payto URI. Required if WIRE_TYPE = iban +# IBAN_PAYTO_BIC = -# Bank hostname used in generated x-taler-bank payto URI +# Bank hostname used in generated x-taler-bank payto URI. Required if WIRE_TYPE = x-taler-bank # X_TALER_BANK_PAYTO_HOSTNAME = bank.$FOO.taler.net # Default debt limit for newly created accounts Default is CURRENCY:0 diff --git a/contrib/nexus.conf b/contrib/nexus.conf @@ -4,26 +4,31 @@ LIBEUFIN_NEXUS_HOME = /var/lib/libeufin-nexus [nexus-ebics] # Currency used by the bank where Nexus is client. -CURRENCY = KUDOS +CURRENCY = # Base URL of the bank server. -HOST_BASE_URL = http://ebics.bank.com/ +HOST_BASE_URL = # EBICS host ID. -HOST_ID = mybank +HOST_ID = # EBICS user ID, as assigned by the bank. -USER_ID = myuser +USER_ID = # EBICS partner ID, as assigned by the bank. -PARTNER_ID = myorg +PARTNER_ID = # EBICS partner ID, as assigned by the bank. -SYSTEM_ID = banksys +SYSTEM_ID = -IBAN = CH9789144829733648596 -BIC = POFICHBE -NAME = LibEuFin +# IBAN of the bank account that is associated with the EBICS subscriber +IBAN = + +# BIC of the bank account that is associated with the EBICS subscriber +BIC = + +# Legal entity that is associated with the EBICS subscriber +NAME = # File that holds the bank EBICS keys. BANK_PUBLIC_KEYS_FILE = ${LIBEUFIN_NEXUS_HOME}/bank-ebics-keys.json diff --git a/nexus/conf/test.conf b/nexus/conf/test.conf @@ -1,5 +1,5 @@ [nexus-ebics] -currency = CHF +CURRENCY = CHF BANK_DIALECT = postfinance HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb BANK_PUBLIC_KEYS_FILE = test/tmp/bank-keys.json @@ -8,6 +8,8 @@ IBAN = CH7789144474425692816 HOST_ID = PFEBICS USER_ID = PFC00563 PARTNER_ID = PFC00563 +BIC = BIC +NAME = myname [libeufin-nexusdb-postgres] CONFIG = postgres:///libeufincheck \ No newline at end of file diff --git a/nexus/src/test/kotlin/Common.kt b/nexus/src/test/kotlin/Common.kt @@ -22,10 +22,12 @@ import io.ktor.client.engine.mock.* import io.ktor.client.request.* import kotlinx.serialization.json.Json import kotlinx.serialization.modules.SerializersModule +import kotlinx.coroutines.* import tech.libeufin.nexus.* import tech.libeufin.common.* import java.security.interfaces.RSAPrivateCrtKey import java.time.Instant +import kotlin.io.path.* val j = Json { this.serializersModule = SerializersModule { @@ -33,28 +35,33 @@ val j = Json { } } -val config: EbicsSetupConfig = run { - val handle = NEXUS_CONFIG_SOURCE.fromFile(null) - EbicsSetupConfig(handle) +fun conf( + conf: String = "test.conf", + lambda: suspend (EbicsSetupConfig) -> Unit +) { + val config = NEXUS_CONFIG_SOURCE.fromFile(Path("conf/$conf")) + val ctx = EbicsSetupConfig(config) + runBlocking { + lambda(ctx) + } } -fun prepDb(cfg: TalerConfig): Database { - val dbCfg = DatabaseConfig( - dbConnStr = "postgresql:///libeufincheck", - sqlDir = cfg.requirePath("paths", "datadir").resolve("sql") - ) - pgDataSource(dbCfg.dbConnStr).pgConnection().use { conn -> - println("SQL dir for testing: ${dbCfg.sqlDir}") - try { - resetDatabaseTables(conn, dbCfg, "libeufin-nexus") - } catch (e: Exception) { - logger.warn("Resetting an empty database throws, tolerating this...") - logger.warn(e.message) +fun setup( + conf: String = "test.conf", + lambda: suspend (Database, EbicsSetupConfig) -> Unit +) { + val config = NEXUS_CONFIG_SOURCE.fromFile(Path("conf/$conf")) + val dbCfg = config.dbConfig() + val ctx = EbicsSetupConfig(config) + Database(dbCfg.dbConnStr).use { + runBlocking { + it.conn { conn -> + resetDatabaseTables(conn, dbCfg, "libeufin-nexus") + initializeDatabaseTables(conn, dbCfg, "libeufin-nexus") + } + lambda(it, ctx) } - initializeDatabaseTables(conn, dbCfg, "libeufin-nexus") } - - return Database(dbCfg.dbConnStr) } val clientKeys = generateNewKeys() @@ -73,27 +80,6 @@ fun getMockedClient( } } -// Partial config to talk to PostFinance. -fun getPofiConfig( - userId: String, - partnerId: String, - accountOwner: String? = "NotGiven" - ) = """ - [nexus-ebics] - CURRENCY = KUDOS - HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb - HOST_ID = PFEBICS - USER_ID = $userId - PARTNER_ID = $partnerId - SYSTEM_ID = not-used - IBAN = CH9789144829733648596 - BIC = POFICHBE - NAME = LibEuFin - BANK_PUBLIC_KEYS_FILE = /tmp/pofi-testplatform-bank-keys.json - CLIENT_PRIVATE_KEYS_FILE = /tmp/pofi-testplatform-subscriber-keys.json - BANK_DIALECT = postfinance -""".trimIndent() - // Generates a payment initiation, given its subject. fun genInitPay( subject: String = "init payment", diff --git a/nexus/src/test/kotlin/ConfigLoading.kt b/nexus/src/test/kotlin/ConfigLoading.kt @@ -25,23 +25,6 @@ import kotlin.test.* import tech.libeufin.common.* class ConfigLoading { - /** - * Tests that the default configuration has _at least_ the options - * that are expected by the memory representation of config. - */ - @Test - fun loadRequiredValues() { - val handle = NEXUS_CONFIG_SOURCE.fromFile(null) - val cfg = EbicsSetupConfig(handle) - cfg._dump() - } - - @Test - fun loadPath() { - val handle = NEXUS_CONFIG_SOURCE.fromFile(null) - val cfg = EbicsSetupConfig(handle) - } - // Checks converting human-readable durations to seconds. @Test fun timeParsing() { diff --git a/nexus/src/test/kotlin/DatabaseTest.kt b/nexus/src/test/kotlin/DatabaseTest.kt @@ -25,37 +25,35 @@ import java.time.Instant import kotlin.random.Random import kotlin.test.* import kotlin.test.assertEquals +import kotlin.io.path.* class OutgoingPaymentsTest { @Test - fun register() { - val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null)) - runBlocking { - // With reconciling - genOutPay("paid by nexus", "first").run { - assertEquals( - PaymentInitiationOutcome.SUCCESS, - db.initiatedPaymentCreate(genInitPay("waiting for reconciliation", "first")) - ) - db.registerOutgoing(this).run { - assertTrue(new,) - assertTrue(initiated) - } - db.registerOutgoing(this).run { - assertFalse(new) - assertTrue(initiated) - } + fun register() = setup { db, _ -> + // With reconciling + genOutPay("paid by nexus", "first").run { + assertEquals( + PaymentInitiationOutcome.SUCCESS, + db.initiatedPaymentCreate(genInitPay("waiting for reconciliation", "first")) + ) + db.registerOutgoing(this).run { + assertTrue(new,) + assertTrue(initiated) } - // Without reconciling - genOutPay("not paid by nexus", "second").run { - db.registerOutgoing(this).run { - assertTrue(new) - assertFalse(initiated) - } - db.registerOutgoing(this).run { - assertFalse(new) - assertFalse(initiated) - } + db.registerOutgoing(this).run { + assertFalse(new) + assertTrue(initiated) + } + } + // Without reconciling + genOutPay("not paid by nexus", "second").run { + db.registerOutgoing(this).run { + assertTrue(new) + assertFalse(initiated) + } + db.registerOutgoing(this).run { + assertFalse(new) + assertFalse(initiated) } } } @@ -64,146 +62,132 @@ class OutgoingPaymentsTest { class IncomingPaymentsTest { // Tests creating and bouncing incoming payments in one DB transaction. @Test - fun bounce() { - val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null)) - runBlocking { - // creating and bouncing one incoming transaction. - val payment = genInPay("incoming and bounced") - db.registerMalformedIncoming( - payment, - TalerAmount("KUDOS:2.53"), - Instant.now() - ).run { - assertTrue(new) - } - db.registerMalformedIncoming( - payment, - TalerAmount("KUDOS:2.53"), - Instant.now() - ).run { - assertFalse(new) - } - db.conn { - // Checking one incoming got created - val checkIncoming = it.prepareStatement(""" - SELECT (amount).val as amount_value, (amount).frac as amount_frac - FROM incoming_transactions WHERE incoming_transaction_id = 1 - """).executeQuery() - assertTrue(checkIncoming.next()) - assertEquals(payment.amount.value, checkIncoming.getLong("amount_value")) - assertEquals(payment.amount.frac, checkIncoming.getInt("amount_frac")) - // Checking the bounced table got its row. - val checkBounced = it.prepareStatement(""" - SELECT 1 FROM bounced_transactions - WHERE incoming_transaction_id = 1 AND initiated_outgoing_transaction_id = 1 - """).executeQuery() - assertTrue(checkBounced.next()) - // check the related initiated payment exists. - val checkInitiated = it.prepareStatement(""" - SELECT - (amount).val as amount_value - ,(amount).frac as amount_frac - FROM initiated_outgoing_transactions - WHERE initiated_outgoing_transaction_id = 1 - """).executeQuery() - assertTrue(checkInitiated.next()) - assertEquals( - 53000000, - checkInitiated.getInt("amount_frac") - ) - assertEquals( - 2, - checkInitiated.getInt("amount_value") - ) - } + fun bounce() = setup { db, _ -> + // creating and bouncing one incoming transaction. + val payment = genInPay("incoming and bounced") + db.registerMalformedIncoming( + payment, + TalerAmount("KUDOS:2.53"), + Instant.now() + ).run { + assertTrue(new) + } + db.registerMalformedIncoming( + payment, + TalerAmount("KUDOS:2.53"), + Instant.now() + ).run { + assertFalse(new) + } + db.conn { + // Checking one incoming got created + val checkIncoming = it.prepareStatement(""" + SELECT (amount).val as amount_value, (amount).frac as amount_frac + FROM incoming_transactions WHERE incoming_transaction_id = 1 + """).executeQuery() + assertTrue(checkIncoming.next()) + assertEquals(payment.amount.value, checkIncoming.getLong("amount_value")) + assertEquals(payment.amount.frac, checkIncoming.getInt("amount_frac")) + // Checking the bounced table got its row. + val checkBounced = it.prepareStatement(""" + SELECT 1 FROM bounced_transactions + WHERE incoming_transaction_id = 1 AND initiated_outgoing_transaction_id = 1 + """).executeQuery() + assertTrue(checkBounced.next()) + // check the related initiated payment exists. + val checkInitiated = it.prepareStatement(""" + SELECT + (amount).val as amount_value + ,(amount).frac as amount_frac + FROM initiated_outgoing_transactions + WHERE initiated_outgoing_transaction_id = 1 + """).executeQuery() + assertTrue(checkInitiated.next()) + assertEquals( + 53000000, + checkInitiated.getInt("amount_frac") + ) + assertEquals( + 2, + checkInitiated.getInt("amount_value") + ) } } // Tests the creation of a talerable incoming payment. @Test - fun talerable() { - val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null)) + fun talerable() = setup { db, _ -> val reservePub = ByteArray(32) Random.nextBytes(reservePub) - runBlocking { - val inc = genInPay("reserve-pub") - // Checking the reserve is not found. - assertFalse(db.isReservePubFound(reservePub)) - assertTrue(db.registerTalerableIncoming(inc, reservePub).new) - // Checking the reserve is not found. - assertTrue(db.isReservePubFound(reservePub)) - assertFalse(db.registerTalerableIncoming(inc, reservePub).new) - } + val inc = genInPay("reserve-pub") + // Checking the reserve is not found. + assertFalse(db.isReservePubFound(reservePub)) + assertTrue(db.registerTalerableIncoming(inc, reservePub).new) + // Checking the reserve is not found. + assertTrue(db.isReservePubFound(reservePub)) + assertFalse(db.registerTalerableIncoming(inc, reservePub).new) } } class PaymentInitiationsTest { // Testing the insertion of the failure message. @Test - fun setFailureMessage() { - val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null)) - runBlocking { - assertEquals( - db.initiatedPaymentCreate(genInitPay("not submitted, has row ID == 1")), - PaymentInitiationOutcome.SUCCESS - ) - assertFalse(db.initiatedPaymentSetFailureMessage(3, "3 not existing")) - assertTrue(db.initiatedPaymentSetFailureMessage(1, "expired")) - // Checking the value from the database. - db.conn { conn -> - val idOne = conn.execSQLQuery(""" - SELECT failure_message - FROM initiated_outgoing_transactions - WHERE initiated_outgoing_transaction_id = 1; - """.trimIndent()) - assertTrue(idOne.next()) - val maybeMessage = idOne.getString("failure_message") - assertEquals("expired", maybeMessage) - } + fun setFailureMessage() = setup { db, _ -> + assertEquals( + db.initiatedPaymentCreate(genInitPay("not submitted, has row ID == 1")), + PaymentInitiationOutcome.SUCCESS + ) + assertFalse(db.initiatedPaymentSetFailureMessage(3, "3 not existing")) + assertTrue(db.initiatedPaymentSetFailureMessage(1, "expired")) + // Checking the value from the database. + db.conn { conn -> + val idOne = conn.execSQLQuery(""" + SELECT failure_message + FROM initiated_outgoing_transactions + WHERE initiated_outgoing_transaction_id = 1; + """.trimIndent()) + assertTrue(idOne.next()) + val maybeMessage = idOne.getString("failure_message") + assertEquals("expired", maybeMessage) } } // Tests the flagging of payments as submitted. @Test - fun paymentInitiationSetAsSubmitted() { - val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null)) + fun paymentInitiationSetAsSubmitted() = setup { db, _ -> val getRowOne = """ SELECT submitted FROM initiated_outgoing_transactions WHERE initiated_outgoing_transaction_id=1 """ - runBlocking { - // Creating the record first. Defaults to submitted == false. - assertEquals( - PaymentInitiationOutcome.SUCCESS, - db.initiatedPaymentCreate(genInitPay("not submitted, has row ID == 1")), - ) - // Asserting on the false default submitted state. - db.conn { conn -> - val isSubmitted = conn.execSQLQuery(getRowOne) - assertTrue(isSubmitted.next()) - assertEquals("unsubmitted", isSubmitted.getString("submitted")) - } - // Switching the submitted state to success. - assertTrue(db.initiatedPaymentSetSubmittedState(1, DatabaseSubmissionState.success)) - // Asserting on the submitted state being TRUE now. - db.conn { conn -> - val isSubmitted = conn.execSQLQuery(getRowOne) - assertTrue(isSubmitted.next()) - assertEquals("success", isSubmitted.getString("submitted")) - } + + // Creating the record first. Defaults to submitted == false. + assertEquals( + PaymentInitiationOutcome.SUCCESS, + db.initiatedPaymentCreate(genInitPay("not submitted, has row ID == 1")), + ) + // Asserting on the false default submitted state. + db.conn { conn -> + val isSubmitted = conn.execSQLQuery(getRowOne) + assertTrue(isSubmitted.next()) + assertEquals("unsubmitted", isSubmitted.getString("submitted")) + } + // Switching the submitted state to success. + assertTrue(db.initiatedPaymentSetSubmittedState(1, DatabaseSubmissionState.success)) + // Asserting on the submitted state being TRUE now. + db.conn { conn -> + val isSubmitted = conn.execSQLQuery(getRowOne) + assertTrue(isSubmitted.next()) + assertEquals("success", isSubmitted.getString("submitted")) } } // Tests creation, unique constraint violation handling, and // retrieving only one non-submitted payment. @Test - fun paymentInitiation() { - val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null)) - runBlocking { - val beEmpty = db.initiatedPaymentsSubmittableGet("KUDOS") // expect no records. - assertEquals(beEmpty.size, 0) - } + fun paymentInitiation() = setup { db, _ -> + val beEmpty = db.initiatedPaymentsSubmittableGet("KUDOS") // expect no records. + assertEquals(beEmpty.size, 0) val initPay = InitiatedPayment( id = -1, amount = TalerAmount(44, 0, "KUDOS"), @@ -212,19 +196,17 @@ class PaymentInitiationsTest { requestUid = "unique", initiationTime = Instant.now() ) - runBlocking { - assertNull(db.initiatedPaymentGetFromUid("unique")) - assertEquals(db.initiatedPaymentCreate(initPay), PaymentInitiationOutcome.SUCCESS) - assertEquals(db.initiatedPaymentCreate(initPay), PaymentInitiationOutcome.UNIQUE_CONSTRAINT_VIOLATION) - val haveOne = db.initiatedPaymentsSubmittableGet("KUDOS") - assertTrue("Size ${haveOne.size} instead of 1") { - haveOne.size == 1 - && haveOne.first().id == 1L - && haveOne.first().requestUid == "unique" - } - assertTrue(db.initiatedPaymentSetSubmittedState(1, DatabaseSubmissionState.success)) - assertNotNull(db.initiatedPaymentGetFromUid("unique")) + assertNull(db.initiatedPaymentGetFromUid("unique")) + assertEquals(db.initiatedPaymentCreate(initPay), PaymentInitiationOutcome.SUCCESS) + assertEquals(db.initiatedPaymentCreate(initPay), PaymentInitiationOutcome.UNIQUE_CONSTRAINT_VIOLATION) + val haveOne = db.initiatedPaymentsSubmittableGet("KUDOS") + assertTrue("Size ${haveOne.size} instead of 1") { + haveOne.size == 1 + && haveOne.first().id == 1L + && haveOne.first().requestUid == "unique" } + assertTrue(db.initiatedPaymentSetSubmittedState(1, DatabaseSubmissionState.success)) + assertNotNull(db.initiatedPaymentGetFromUid("unique")) } /** @@ -232,67 +214,61 @@ class PaymentInitiationsTest { * statuses from them. Checking it here. */ @Test - fun submittablePayments() { - val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null)) - runBlocking { - val beEmpty = db.initiatedPaymentsSubmittableGet("KUDOS") - assertEquals(0, beEmpty.size) - assertEquals( - db.initiatedPaymentCreate(genInitPay(requestUid = "first")), - PaymentInitiationOutcome.SUCCESS - ) - assertEquals( - db.initiatedPaymentCreate(genInitPay(requestUid = "second")), - PaymentInitiationOutcome.SUCCESS - ) - assertEquals( - db.initiatedPaymentCreate(genInitPay(requestUid = "third")), - PaymentInitiationOutcome.SUCCESS - ) + fun submittablePayments() = setup { db, _ -> + val beEmpty = db.initiatedPaymentsSubmittableGet("KUDOS") + assertEquals(0, beEmpty.size) + assertEquals( + db.initiatedPaymentCreate(genInitPay(requestUid = "first")), + PaymentInitiationOutcome.SUCCESS + ) + assertEquals( + db.initiatedPaymentCreate(genInitPay(requestUid = "second")), + PaymentInitiationOutcome.SUCCESS + ) + assertEquals( + db.initiatedPaymentCreate(genInitPay(requestUid = "third")), + PaymentInitiationOutcome.SUCCESS + ) - // Setting the first as "transient_failure", must be found. - assertTrue(db.initiatedPaymentSetSubmittedState( - 1, DatabaseSubmissionState.transient_failure - )) - // Setting the second as "success", must not be found. - assertTrue(db.initiatedPaymentSetSubmittedState( - 2, DatabaseSubmissionState.success - )) - val expectTwo = db.initiatedPaymentsSubmittableGet("KUDOS") - // the third initiation keeps the default "unsubmitted" - // state, must be found. Total 2. - assertEquals(2, expectTwo.size) - } + // Setting the first as "transient_failure", must be found. + assertTrue(db.initiatedPaymentSetSubmittedState( + 1, DatabaseSubmissionState.transient_failure + )) + // Setting the second as "success", must not be found. + assertTrue(db.initiatedPaymentSetSubmittedState( + 2, DatabaseSubmissionState.success + )) + val expectTwo = db.initiatedPaymentsSubmittableGet("KUDOS") + // the third initiation keeps the default "unsubmitted" + // state, must be found. Total 2. + assertEquals(2, expectTwo.size) } // Tests how the fetch method gets the list of // multiple unsubmitted payment initiations. @Test - fun paymentInitiationsMultiple() { - val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null)) - runBlocking { - assertEquals(db.initiatedPaymentCreate(genInitPay("#1", "unique1")), PaymentInitiationOutcome.SUCCESS) - assertEquals(db.initiatedPaymentCreate(genInitPay("#2", "unique2")), PaymentInitiationOutcome.SUCCESS) - assertEquals(db.initiatedPaymentCreate(genInitPay("#3", "unique3")), PaymentInitiationOutcome.SUCCESS) - assertEquals(db.initiatedPaymentCreate(genInitPay("#4", "unique4")), PaymentInitiationOutcome.SUCCESS) + fun paymentInitiationsMultiple() = setup { db, _ -> + assertEquals(db.initiatedPaymentCreate(genInitPay("#1", "unique1")), PaymentInitiationOutcome.SUCCESS) + assertEquals(db.initiatedPaymentCreate(genInitPay("#2", "unique2")), PaymentInitiationOutcome.SUCCESS) + assertEquals(db.initiatedPaymentCreate(genInitPay("#3", "unique3")), PaymentInitiationOutcome.SUCCESS) + assertEquals(db.initiatedPaymentCreate(genInitPay("#4", "unique4")), PaymentInitiationOutcome.SUCCESS) - // Marking one as submitted, hence not expecting it in the results. - db.conn { conn -> - conn.execSQLUpdate(""" - UPDATE initiated_outgoing_transactions - SET submitted='success' - WHERE initiated_outgoing_transaction_id=3; - """.trimIndent()) - } + // Marking one as submitted, hence not expecting it in the results. + db.conn { conn -> + conn.execSQLUpdate(""" + UPDATE initiated_outgoing_transactions + SET submitted='success' + WHERE initiated_outgoing_transaction_id=3; + """.trimIndent()) + } - // Expecting all the payments BUT the #3 in the result. - db.initiatedPaymentsSubmittableGet("KUDOS").apply { + // Expecting all the payments BUT the #3 in the result. + db.initiatedPaymentsSubmittableGet("KUDOS").apply { - assertEquals(3, this.size) - assertEquals("#1", this[0].wireTransferSubject) - assertEquals("#2", this[1].wireTransferSubject) - assertEquals("#4", this[2].wireTransferSubject) - } + assertEquals(3, this.size) + assertEquals("#1", this[0].wireTransferSubject) + assertEquals("#2", this[1].wireTransferSubject) + assertEquals("#4", this[2].wireTransferSubject) } } } \ No newline at end of file diff --git a/nexus/src/test/kotlin/Ebics.kt b/nexus/src/test/kotlin/Ebics.kt @@ -33,7 +33,7 @@ import kotlin.io.path.* class Ebics { // Checks XML is valid and INI. @Test - fun iniMessage() { + fun iniMessage() = conf { config -> val msg = generateIniMessage(config, clientKeys) val ini = XMLUtil.convertStringToJaxb<EbicsUnsecuredRequest>(msg) // ensures is valid assertEquals(ini.value.header.static.orderDetails.orderType, "INI") // ensures is INI @@ -41,7 +41,7 @@ class Ebics { // Checks XML is valid and HIA. @Test - fun hiaMessage() { + fun hiaMessage() = conf { config -> val msg = generateHiaMessage(config, clientKeys) val ini = XMLUtil.convertStringToJaxb<EbicsUnsecuredRequest>(msg) // ensures is valid assertEquals(ini.value.header.static.orderDetails.orderType, "HIA") // ensures is HIA @@ -49,7 +49,7 @@ class Ebics { // Checks XML is valid and HPB. @Test - fun hpbMessage() { + fun hpbMessage() = conf { config -> val msg = generateHpbMessage(config, clientKeys) val ini = XMLUtil.convertStringToJaxb<EbicsUnsecuredRequest>(msg) // ensures is valid assertEquals(ini.value.header.static.orderDetails.orderType, "HPB") // ensures is HPB @@ -58,7 +58,7 @@ class Ebics { // the main branches: unreachable bank, non-200 status // code, and 200. @Test - fun postMessage() { + fun postMessage() = conf { config -> val client404 = getMockedClient { respondError(HttpStatusCode.NotFound) } @@ -68,17 +68,15 @@ class Ebics { val clientOk = getMockedClient { respondOk("Not EBICS anyway.") } - runBlocking { - assertNull(client404.postToBank("http://ignored.example.com/", "ignored")) - assertNull(clientNoResponse.postToBank("http://ignored.example.com/", "ignored")) - assertNotNull(clientOk.postToBank("http://ignored.example.com/", "ignored")) - } + assertNull(client404.postToBank("http://ignored.example.com/", "ignored")) + assertNull(clientNoResponse.postToBank("http://ignored.example.com/", "ignored")) + assertNotNull(clientOk.postToBank("http://ignored.example.com/", "ignored")) } // Tests that internal repr. of keys lead to valid PDF. // Mainly tests that the function does not throw any error. @Test - fun keysPdf() { + fun keysPdf() = conf { config -> val pdf = generateKeysPdf(clientKeys, config) Path("/tmp/libeufin-nexus-test-keys.pdf").writeBytes(pdf) } diff --git a/testbench/conf/integration.conf b/testbench/conf/integration.conf @@ -1,4 +1,7 @@ [libeufin-bank] +CURRENCY = KUDOS +WIRE_TYPE = iban +IBAN_PAYTO_BIC = SANDBOXX SUGGESTED_WITHDRAWAL_EXCHANGE = https://exchange.example.com ALLOW_REGISTRATION = yes ALLOW_ACCOUNT_DELETION = yes @@ -7,11 +10,25 @@ FIAT_CURRENCY = EUR tan_sms = libeufin-tan-file.sh tan_email = libeufin-tan-fail.sh -[libeufin-bankdb-postgres] -CONFIG = postgresql:///libeufincheck - [nexus-ebics] -currency = EUR +CURRENCY = EUR + +# Bank +HOST_BASE_URL = http://bank.example.com/ +BANK_DIALECT = postfinance + +# EBICS IDs +HOST_ID = mybank +USER_ID = myuser +PARTNER_ID = myorg + +# Account information +IBAN = myiban +BIC = mybic +NAME = myname [libeufin-bankdb-postgres] +CONFIG = postgresql:///libeufincheck + +[libeufin-nexusdb-postgres] CONFIG = postgres:///libeufincheck diff --git a/testbench/conf/mini.conf b/testbench/conf/mini.conf @@ -1,3 +1,25 @@ +[libeufin-bank] +CURRENCY = KUDOS +WIRE_TYPE = iban +IBAN_PAYTO_BIC = SANDBOXX + +[nexus-ebics] +CURRENCY = CHF + +# Bank +HOST_BASE_URL = http://bank.example.com/ +BANK_DIALECT = postfinance + +# EBICS IDs +HOST_ID = mybank +USER_ID = myuser +PARTNER_ID = myorg + +# Account information +IBAN = myiban +BIC = mybic +NAME = myname + [libeufin-bankdb-postgres] CONFIG = postgresql:///libeufincheck