gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[libeufin] branch master updated (7723cf2b -> ba418b5d)


From: gnunet
Subject: [libeufin] branch master updated (7723cf2b -> ba418b5d)
Date: Thu, 25 Jan 2024 10:25:24 +0100

This is an automated email from the git hooks/post-receive script.

antoine pushed a change to branch master
in repository libeufin.

    from 7723cf2b Improve fs logic
     new 18d9d91d Improve ebics testbench adding support for Credit Suisse 
IsoTest
     new ba418b5d Improve taler config

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 bank/src/main/kotlin/tech/libeufin/bank/Config.kt  |   6 +-
 bank/src/test/kotlin/helpers.kt                    |   2 +-
 common/src/main/kotlin/Cli.kt                      |  19 +-
 common/src/main/kotlin/TalerConfig.kt              | 143 +++++------
 common/src/test/kotlin/TalerConfigTest.kt          |   6 +-
 .../main/kotlin/tech/libeufin/nexus/EbicsSetup.kt  |   2 +-
 nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt  |   7 +-
 nexus/src/test/kotlin/CliTest.kt                   |   2 +-
 nexus/src/test/kotlin/Common.kt                    |   4 +-
 nexus/src/test/kotlin/ConfigLoading.kt             |  24 +-
 nexus/src/test/kotlin/DatabaseTest.kt              |  16 +-
 testbench/README.md                                |  32 +++
 testbench/conf/netzbon.conf                        |  27 --
 testbench/conf/postfinance.conf                    |  26 --
 testbench/src/main/kotlin/Main.kt                  | 280 +++++++++++----------
 15 files changed, 273 insertions(+), 323 deletions(-)
 create mode 100644 testbench/README.md
 delete mode 100644 testbench/conf/netzbon.conf
 delete mode 100644 testbench/conf/postfinance.conf

diff --git a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt 
b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
index a7ee5c58..0ad5590a 100644
--- a/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
+++ b/bank/src/main/kotlin/tech/libeufin/bank/Config.kt
@@ -71,11 +71,7 @@ sealed class ServerConfig {
     data class Tcp(val port: Int): ServerConfig()
 }
 
-fun talerConfig(configPath: String?): TalerConfig {
-    val config = TalerConfig(BANK_CONFIG_SOURCE)
-    config.load(configPath)
-    return config
-}
+fun talerConfig(configPath: Path?): TalerConfig = 
BANK_CONFIG_SOURCE.fromFile(configPath)
 
 fun TalerConfig.loadDbConfig(): DatabaseConfig  {
     return DatabaseConfig(
diff --git a/bank/src/test/kotlin/helpers.kt b/bank/src/test/kotlin/helpers.kt
index 6e5f6d02..fa8b63a4 100644
--- a/bank/src/test/kotlin/helpers.kt
+++ b/bank/src/test/kotlin/helpers.kt
@@ -57,7 +57,7 @@ fun setup(
     conf: String = "test.conf",
     lambda: suspend (Database, BankConfig) -> Unit
 ) {
-    val config = talerConfig("conf/$conf")
+    val config = talerConfig(Path("conf/$conf"))
     val dbCfg = config.loadDbConfig()
     val ctx = config.loadBankConfig()
     Database(dbCfg.dbConnStr, ctx.regionalCurrency, ctx.fiatCurrency).use {
diff --git a/common/src/main/kotlin/Cli.kt b/common/src/main/kotlin/Cli.kt
index 2db1e906..0209dc53 100644
--- a/common/src/main/kotlin/Cli.kt
+++ b/common/src/main/kotlin/Cli.kt
@@ -27,6 +27,7 @@ import com.github.ajalt.clikt.parameters.groups.*
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 import org.slf4j.event.Level
+import java.nio.file.Path
 
 private val logger: Logger = LoggerFactory.getLogger("libeufin-config")
 
@@ -51,21 +52,11 @@ fun cliCmd(logger: Logger, level: Level, lambda: () -> 
Unit) {
     }
 }
 
-private fun talerConfig(configSource: ConfigSource, configPath: String?): 
TalerConfig {
-    val config = TalerConfig(configSource)
-    config.load(configPath)
-    return config
-}
-
 class CommonOption: OptionGroup() {
     val config by option(
         "--config", "-c",
         help = "Specifies the configuration file"
-    ).path(
-        mustExist = true, 
-        canBeDir = false, 
-        mustBeReadable = true,
-    ).convert { it.toString() } // TODO take path to load config
+    ).path()
     val log by option(
         "--log", "-L",
         help = "Configure logging to use LOGLEVEL"
@@ -91,7 +82,7 @@ private class CliConfigGet(private val configSource: 
ConfigSource) : CliktComman
 
 
     override fun run() = cliCmd(logger, common.log) {
-        val config = talerConfig(configSource, common.config)
+        val config = configSource.fromFile(common.config)
         if (isPath) {
             val res = config.lookupPath(sectionName, optionName)
             if (res == null) {
@@ -115,7 +106,7 @@ private class CliConfigPathsub(private val configSource: 
ConfigSource) : CliktCo
     private val pathExpr by argument()
 
     override fun run() = cliCmd(logger, common.log) {
-        val config = talerConfig(configSource, common.config)
+        val config = configSource.fromFile(common.config)
         println(config.pathsub(pathExpr))
     }
 }
@@ -124,7 +115,7 @@ private class CliConfigDump(private val configSource: 
ConfigSource) : CliktComma
     private val common by CommonOption()
 
     override fun run() = cliCmd(logger, common.log) {
-        val config = talerConfig(configSource, common.config)
+        val config = configSource.fromFile(common.config)
         println("# install path: ${config.getInstallPath()}")
         println(config.stringify())
     }
diff --git a/common/src/main/kotlin/TalerConfig.kt 
b/common/src/main/kotlin/TalerConfig.kt
index f98f6e5e..26fd4c5f 100644
--- a/common/src/main/kotlin/TalerConfig.kt
+++ b/common/src/main/kotlin/TalerConfig.kt
@@ -61,6 +61,21 @@ data class ConfigSource(
     val installPathBinary: String = "taler-config",
 )
 
+fun ConfigSource.fromMem(content: String): TalerConfig {
+    val cfg = TalerConfig(this)
+    cfg.loadDefaults()
+    cfg.loadFromMem(content, null)
+    return cfg
+}
+
+fun ConfigSource.fromFile(file: Path?): TalerConfig {
+    val cfg = TalerConfig(this)
+    cfg.loadDefaults()
+    val path = file ?: cfg.findDefaultConfigFilename()
+    if (path != null) cfg.loadFromFile(path)
+    return cfg
+}
+
 /**
  * Reader and writer for Taler-style configuration files.
  *
@@ -69,8 +84,8 @@ data class ConfigSource(
  *
  * @param configSource information about where to load configuration defaults 
from
  */
-class TalerConfig(
-    private val configSource: ConfigSource,
+class TalerConfig internal constructor(
+    val configSource: ConfigSource,
 ) {
     private val sectionMap: MutableMap<String, Section> = mutableMapOf()
 
@@ -79,7 +94,55 @@ class TalerConfig(
     private val installPathBinary = configSource.installPathBinary
     val sections: Set<String> get() = sectionMap.keys
 
-    private fun internalLoadFromString(s: String, source: Path?) {
+    /**
+     * Load configuration defaults from the file system
+     * and populate the PATHS section based on the installation path.
+     */
+    internal fun loadDefaults() {
+        val installDir = getInstallPath()
+        val baseConfigDir = Path(installDir, "share/$projectName/config.d")
+        setSystemDefault("PATHS", "PREFIX", "$installDir/")
+        setSystemDefault("PATHS", "BINDIR", "$installDir/bin/")
+        setSystemDefault("PATHS", "LIBEXECDIR", 
"$installDir/$projectName/libexec/")
+        setSystemDefault("PATHS", "DOCDIR", 
"$installDir/share/doc/$projectName/")
+        setSystemDefault("PATHS", "ICONDIR", "$installDir/share/icons/")
+        setSystemDefault("PATHS", "LOCALEDIR", "$installDir/share/locale/")
+        setSystemDefault("PATHS", "LIBDIR", "$installDir/lib/$projectName/")
+        setSystemDefault("PATHS", "DATADIR", "$installDir/share/$projectName/")
+        for (filePath in baseConfigDir.listDirectoryEntries()) {
+            loadFromFile(filePath)
+        }
+    }
+
+    private fun loadFromGlob(source: Path, glob: String) {
+        // FIXME: Check that the Kotlin glob matches the glob from our spec
+        for (entry in source.parent.listDirectoryEntries(glob)) {
+            loadFromFile(entry)
+        }
+    }
+
+    private fun loadSecret(sectionName: String, secretFilename: Path) {
+        if (!secretFilename.isReadable()) {
+            logger.warn("unable to read secrets from $secretFilename")
+        } else {
+            loadFromFile(secretFilename)
+        }
+    }
+
+    internal fun loadFromFile(file: Path) {
+        val content =  try {
+            file.readText()
+        } catch (e: Exception) {
+            when {
+                e is NoSuchFileException -> throw Exception("Could not read 
config at '$file': no such file")
+                e is AccessDeniedException -> throw Exception("Could not read 
config at '$file': permission denied")
+                else -> throw Exception("Could not read config at '$file'", e)
+            }
+        }
+        loadFromMem(content, file)
+    }
+
+    internal fun loadFromMem(s: String, source: Path?) {
         val lines = s.lines()
         var lineNum = 0
         var currentSection: String? = null
@@ -102,11 +165,11 @@ class TalerConfig(
                 when (directiveName) {
                     "inline" -> {
                         val innerFilename = 
source.resolveSibling(directiveArg.trim())
-                        this.loadFromFilename(innerFilename)
+                        loadFromFile(innerFilename)
                     }
                     "inline-matching" -> {
                         val glob = directiveArg.trim()
-                        this.loadFromGlob(source, glob)
+                        loadFromGlob(source, glob)
                     }
                     "inline-secret" -> {
                         val arg = directiveArg.trim()
@@ -151,21 +214,6 @@ class TalerConfig(
         }
     }
 
-    private fun loadFromGlob(source: Path, glob: String) {
-        // FIXME: Check that the Kotlin glob matches the glob from our spec
-        for (entry in source.parent.listDirectoryEntries(glob)) {
-            loadFromFilename(entry)
-        }
-    }
-
-    private fun loadSecret(sectionName: String, secretFilename: Path) {
-        if (!secretFilename.isReadable()) {
-            logger.warn("unable to read secrets from $secretFilename")
-        } else {
-            this.loadFromFilename(secretFilename)
-        }
-    }
-
     private fun provideSection(name: String): Section {
         val canonSecName = name.uppercase()
         val existingSec = this.sectionMap[canonSecName]
@@ -177,10 +225,6 @@ class TalerConfig(
         return newSection
     }
 
-    fun loadFromString(s: String) {
-        internalLoadFromString(s, null)
-    }
-
     private fun setSystemDefault(section: String, option: String, value: 
String) {
         // FIXME: The value should be marked as a system default for 
diagnostics pretty printing
         val sec = provideSection(section)
@@ -213,38 +257,6 @@ class TalerConfig(
         return outStr.toString()
     }
 
-    /**
-     * Read values into the configuration from the given entry point
-     * filename.  Defaults are *not* loaded automatically.
-     */
-    fun loadFromFilename(path: Path) {
-        internalLoadFromString(path.readText(), path)
-    }
-
-    private fun loadDefaultsFromDir(dirname: Path) {
-        for (filePath in dirname.listDirectoryEntries()) {
-            loadFromFilename(filePath)
-        }
-    }
-
-    /**
-     * Load configuration defaults from the file system
-     * and populate the PATHS section based on the installation path.
-     */
-    fun loadDefaults() {
-        val installDir = getInstallPath()
-        val baseConfigDir = Path(installDir, "share/$projectName/config.d")
-        setSystemDefault("PATHS", "PREFIX", "$installDir/")
-        setSystemDefault("PATHS", "BINDIR", "$installDir/bin/")
-        setSystemDefault("PATHS", "LIBEXECDIR", 
"$installDir/$projectName/libexec/")
-        setSystemDefault("PATHS", "DOCDIR", 
"$installDir/share/doc/$projectName/")
-        setSystemDefault("PATHS", "ICONDIR", "$installDir/share/icons/")
-        setSystemDefault("PATHS", "LOCALEDIR", "$installDir/share/locale/")
-        setSystemDefault("PATHS", "LIBDIR", "$installDir/lib/$projectName/")
-        setSystemDefault("PATHS", "DATADIR", "$installDir/share/$projectName/")
-        loadDefaultsFromDir(baseConfigDir)
-    }
-
     private fun variableLookup(x: String, recursionDepth: Int = 0): Path? {
         val pathRes = this.lookupString("PATHS", x)
         if (pathRes != null) {
@@ -345,29 +357,12 @@ class TalerConfig(
         return Path(result.toString())
     }
 
-    /**
-     * Load configuration values from the file system.
-     * If no entrypoint is specified, the default entrypoint
-     * is used.
-     */
-    fun load(entrypoint: String? = null) {
-        loadDefaults()
-        if (entrypoint != null) {
-            loadFromFilename(Path(entrypoint))
-        } else {
-            val defaultFilename = findDefaultConfigFilename()
-            if (defaultFilename != null) {
-                loadFromFilename(defaultFilename)
-            }
-        }
-    }
-
     /**
      * Determine the filename of the default configuration file.
      *
      * If no such file can be found, return null.
      */
-    private fun findDefaultConfigFilename(): Path? {
+    internal fun findDefaultConfigFilename(): Path? {
         val xdg = System.getenv("XDG_CONFIG_HOME")
         val home = System.getenv("HOME")
 
diff --git a/common/src/test/kotlin/TalerConfigTest.kt 
b/common/src/test/kotlin/TalerConfigTest.kt
index 0167aa00..6cc7aa04 100644
--- a/common/src/test/kotlin/TalerConfigTest.kt
+++ b/common/src/test/kotlin/TalerConfigTest.kt
@@ -27,9 +27,7 @@ class TalerConfigTest {
     @Test
     fun parsing() {
         // We assume that libeufin-bank is installed. We could also try to 
locate the source tree here.
-        val conf = TalerConfig(ConfigSource("libeufin", "libeufin-bank", 
"libeufin-bank"))
-        conf.loadDefaults()
-        conf.loadFromString(
+        val conf = ConfigSource("libeufin", "libeufin-bank", 
"libeufin-bank").fromMem(
             """
 
             [foo]
@@ -49,7 +47,7 @@ class TalerConfigTest {
     @Test
     fun substitution() {
         // We assume that libeufin-bank is installed. We could also try to 
locate the source tree here.
-        val conf = TalerConfig(ConfigSource("libeufin", "libeufin-bank", 
"libeufin-bank"))
+        val conf = ConfigSource("libeufin", "libeufin-bank", 
"libeufin-bank").fromFile(null)
         conf.putValueString("PATHS", "DATADIR", "mydir")
         conf.putValueString("foo", "bar", "baz")
         conf.putValueString("foo", "bar2", "baz")
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
index 32655979..f23b3a33 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/EbicsSetup.kt
@@ -189,7 +189,7 @@ suspend fun doKeysRequestAndUpdateState(
  * @param configFile location of the configuration entry point.
  * @return internal representation of the configuration.
  */
-fun extractEbicsConfig(configFile: String?): EbicsSetupConfig {
+fun extractEbicsConfig(configFile: Path?): EbicsSetupConfig {
     val config = loadConfig(configFile)
     return EbicsSetupConfig(config)
 }
diff --git a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt 
b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
index 4d27910a..a5f8dccf 100644
--- a/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
+++ b/nexus/src/main/kotlin/tech/libeufin/nexus/Main.kt
@@ -33,6 +33,7 @@ import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 import tech.libeufin.nexus.ebics.*
 import tech.libeufin.common.*
+import java.nio.file.Path
 
 val NEXUS_CONFIG_SOURCE = ConfigSource("libeufin", "libeufin-nexus", 
"libeufin-nexus")
 val logger: Logger = LoggerFactory.getLogger("libeufin-nexus")
@@ -195,11 +196,7 @@ class EbicsSetupConfig(val config: TalerConfig) {
  * @param configFile potentially NULL configuration file location.
  * @return the configuration handle.
  */
-fun loadConfig(configFile: String?): TalerConfig {
-    val config = TalerConfig(NEXUS_CONFIG_SOURCE)
-    config.load(configFile)
-    return config
-}
+fun loadConfig(configFile: Path?): TalerConfig = 
NEXUS_CONFIG_SOURCE.fromFile(configFile)
 
 /**
  * Abstracts fetching the DB config values to set up Nexus.
diff --git a/nexus/src/test/kotlin/CliTest.kt b/nexus/src/test/kotlin/CliTest.kt
index 56570bea..de41523e 100644
--- a/nexus/src/test/kotlin/CliTest.kt
+++ b/nexus/src/test/kotlin/CliTest.kt
@@ -49,7 +49,7 @@ class CliTest {
         val cmds = listOf("ebics-submit", "ebics-fetch")
         val allCmds = listOf("ebics-submit", "ebics-fetch", "ebics-setup")
         val conf = "conf/test.conf"
-        val cfg = loadConfig(conf)
+        val cfg = loadConfig(Path(conf))
         val clientKeysPath = cfg.requirePath("nexus-ebics", 
"client_private_keys_file")
         val bankKeysPath = cfg.requirePath("nexus-ebics", 
"bank_public_keys_file")
         clientKeysPath.parent!!.createDirectories()
diff --git a/nexus/src/test/kotlin/Common.kt b/nexus/src/test/kotlin/Common.kt
index f6db6bfe..422450fc 100644
--- a/nexus/src/test/kotlin/Common.kt
+++ b/nexus/src/test/kotlin/Common.kt
@@ -34,13 +34,11 @@ val j = Json {
 }
 
 val config: EbicsSetupConfig = run {
-    val handle = TalerConfig(NEXUS_CONFIG_SOURCE)
-    handle.load()
+    val handle = NEXUS_CONFIG_SOURCE.fromFile(null)
     EbicsSetupConfig(handle)
 }
 
 fun prepDb(cfg: TalerConfig): Database {
-    cfg.loadDefaults()
     val dbCfg = DatabaseConfig(
         dbConnStr = "postgresql:///libeufincheck",
         sqlDir = cfg.requirePath("paths", "datadir").resolve("sql")
diff --git a/nexus/src/test/kotlin/ConfigLoading.kt 
b/nexus/src/test/kotlin/ConfigLoading.kt
index 1155763c..a4047dff 100644
--- a/nexus/src/test/kotlin/ConfigLoading.kt
+++ b/nexus/src/test/kotlin/ConfigLoading.kt
@@ -31,37 +31,17 @@ class ConfigLoading {
      */
     @Test
     fun loadRequiredValues() {
-        val handle = TalerConfig(NEXUS_CONFIG_SOURCE)
-        handle.load()
+        val handle = NEXUS_CONFIG_SOURCE.fromFile(null)
         val cfg = EbicsSetupConfig(handle)
         cfg._dump()
     }
 
     @Test
     fun loadPath() {
-        val handle = TalerConfig(NEXUS_CONFIG_SOURCE)
-        handle.load()
+        val handle = NEXUS_CONFIG_SOURCE.fromFile(null)
         val cfg = EbicsSetupConfig(handle)
     }
 
-
-    /**
-     * Tests that if the configuration lacks at least one option, then
-     * the config loader throws exception.
-     */
-    @Test
-    fun detectMissingValues() {
-        val handle = TalerConfig(NEXUS_CONFIG_SOURCE)
-        handle.loadFromString("""
-            [ebics-nexus]
-            # All the other defaults won't be loaded.
-            BANK_DIALECT = postfinance
-        """.trimIndent())
-        assertFailsWith<TalerConfigError> {
-            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
index 58fa9735..6e2443e7 100644
--- a/nexus/src/test/kotlin/DatabaseTest.kt
+++ b/nexus/src/test/kotlin/DatabaseTest.kt
@@ -29,7 +29,7 @@ import kotlin.test.assertEquals
 class OutgoingPaymentsTest {
     @Test
     fun register() {
-        val db = prepDb(TalerConfig(NEXUS_CONFIG_SOURCE))
+        val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null))
         runBlocking {
             // With reconciling
             genOutPay("paid by nexus", "first").run {
@@ -65,7 +65,7 @@ class IncomingPaymentsTest {
     // Tests creating and bouncing incoming payments in one DB transaction.
     @Test
     fun bounce() {
-        val db = prepDb(TalerConfig(NEXUS_CONFIG_SOURCE))
+        val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null))
         runBlocking {
             // creating and bouncing one incoming transaction.
             val payment = genInPay("incoming and bounced")
@@ -122,7 +122,7 @@ class IncomingPaymentsTest {
     // Tests the creation of a talerable incoming payment.
     @Test
     fun talerable() {
-        val db = prepDb(TalerConfig(NEXUS_CONFIG_SOURCE))
+        val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null))
         val reservePub = ByteArray(32)
         Random.nextBytes(reservePub)
 
@@ -142,7 +142,7 @@ class PaymentInitiationsTest {
     // Testing the insertion of the failure message.
     @Test
     fun setFailureMessage() {
-        val db = prepDb(TalerConfig(NEXUS_CONFIG_SOURCE))
+        val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null))
         runBlocking {
             assertEquals(
                 db.initiatedPaymentCreate(genInitPay("not submitted, has row 
ID == 1")),
@@ -166,7 +166,7 @@ class PaymentInitiationsTest {
     // Tests the flagging of payments as submitted.
     @Test
     fun paymentInitiationSetAsSubmitted() {
-        val db = prepDb(TalerConfig(NEXUS_CONFIG_SOURCE))
+        val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null))
         val getRowOne = """
                     SELECT submitted
                       FROM initiated_outgoing_transactions
@@ -199,7 +199,7 @@ class PaymentInitiationsTest {
     // retrieving only one non-submitted payment.
     @Test
     fun paymentInitiation() {
-        val db = prepDb(TalerConfig(NEXUS_CONFIG_SOURCE))
+        val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null))
         runBlocking {
             val beEmpty = db.initiatedPaymentsSubmittableGet("KUDOS") // 
expect no records.
             assertEquals(beEmpty.size, 0)
@@ -232,7 +232,7 @@ class PaymentInitiationsTest {
      */
     @Test
     fun submittablePayments() {
-        val db = prepDb(TalerConfig(NEXUS_CONFIG_SOURCE))
+        val db = prepDb(NEXUS_CONFIG_SOURCE.fromFile(null))
         runBlocking {
             val beEmpty = db.initiatedPaymentsSubmittableGet("KUDOS")
             assertEquals(0, beEmpty.size)
@@ -268,7 +268,7 @@ class PaymentInitiationsTest {
     // multiple unsubmitted payment initiations.
     @Test
     fun paymentInitiationsMultiple() {
-        val db = prepDb(TalerConfig(NEXUS_CONFIG_SOURCE))
+        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)
diff --git a/testbench/README.md b/testbench/README.md
new file mode 100644
index 00000000..63cc81be
--- /dev/null
+++ b/testbench/README.md
@@ -0,0 +1,32 @@
+# LibEuFin Test Bench
+
+## Interactive EBICS test
+
+To add a platform write a minimal configuration file at 
`testbench/test/PLATFORM/ebics.conf` such as :
+
+
+``` ini
+[nexus-ebics]
+currency = CHF
+
+# Bank
+HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb
+BANK_DIALECT = postfinance
+
+# EBICS IDs
+HOST_ID = PFEBICS
+USER_ID = PFC00563
+PARTNER_ID = PFC00563
+
+IBAN = CH7789144474425692816
+```
+
+To start the interactive EBICS test run :
+
+``` sh
+make testbench platform=PLATFORM
+```
+
+If HOST_BASE_URL is one a known test platform we will generate and then offer 
to reset client private keys to test keys registration, otherwise, we will 
expect existing keys to be found at `testbench/test/PLATFORM/ebics.edited.conf`.
+
+This minimal configuration will be augmented on start, you can find the full 
documentation at `testbench/test/PLATFORM/client-ebics-keys.json`.
\ No newline at end of file
diff --git a/testbench/conf/netzbon.conf b/testbench/conf/netzbon.conf
deleted file mode 100644
index 84aed7aa..00000000
--- a/testbench/conf/netzbon.conf
+++ /dev/null
@@ -1,27 +0,0 @@
-[paths]
-LIBEUFIN_NEXUS_HOME = test/netzbon
-
-[nexus-ebics]
-CURRENCY = CHF
-
-# Bank
-HOST_BASE_URL = https://ebics.postfinance.ch/ebics/ebics.aspx
-BANK_DIALECT = postfinance
-
-# EBICS IDs
-HOST_ID = PFEBICS
-USER_ID = 5183101
-PARTNER_ID = 51831
-
-IBAN = CH4009000000160948810
-BIC = POFICHBEXXX
-NAME = Genossenschaft Netz Soziale Oekonomie
-
-[nexus-fetch]
-FREQUENCY = 5s
-
-[nexus-submit]
-FREQUENCY = 5s
-
-[nexus-postgres]
-CONFIG = postgres:///libeufincheck
diff --git a/testbench/conf/postfinance.conf b/testbench/conf/postfinance.conf
deleted file mode 100644
index 7799b13e..00000000
--- a/testbench/conf/postfinance.conf
+++ /dev/null
@@ -1,26 +0,0 @@
-[paths]
-LIBEUFIN_NEXUS_HOME = test/postfinance
-
-[nexus-ebics]
-currency = CHF
-
-# Bank
-HOST_BASE_URL = https://isotest.postfinance.ch/ebicsweb/ebicsweb
-BANK_DIALECT = postfinance
-
-# EBICS IDs
-HOST_ID = PFEBICS
-USER_ID = PFC00563
-PARTNER_ID = PFC00563
-
-#IBAN = CH2989144971918294289
-IBAN = CH7789144474425692816
-
-[nexus-fetch]
-FREQUENCY = 5s
-
-[nexus-submit]
-FREQUENCY = 5s
-
-[nexus-postgres]
-CONFIG = postgres:///libeufincheck
diff --git a/testbench/src/main/kotlin/Main.kt 
b/testbench/src/main/kotlin/Main.kt
index 60055e42..076d5001 100644
--- a/testbench/src/main/kotlin/Main.kt
+++ b/testbench/src/main/kotlin/Main.kt
@@ -64,161 +64,177 @@ fun CliktCommandTestResult.assertErr(msg: String? = null) 
{
     assertEquals(1, statusCode, msg)
 }
 
-enum class Kind {
-    postfinance, 
-    netzbon
+data class Kind(val name: String, val settings: String?) {
+    val test get() = settings != null
 }
 
 class Cli : CliktCommand("Run integration tests on banks provider") {
-    val kind: Kind by argument().enum<Kind>()
+    val platform by argument()
+
     override fun run() {
-        val name = kind.name
-        step("Test init $name")
+        // List available platform
+        val platforms = Path("test").listDirectoryEntries().filter { 
it.isDirectory() }.map { it.getFileName().toString() }
+        if (!platforms.contains(platform)) {
+            println("Unknown platform '$platform', expected one of $platforms")
+            throw ProgramResult(1)
+        }
 
-        runBlocking {
-            Path("test/$name").createDirectories()
-            val conf = "conf/$name.conf"
-            val log = "DEBUG"
-            val flags = " -c $conf -L $log"
-            val ebicsFlags = "$flags --transient --debug-ebics test/$name"
-            val cfg = loadConfig(conf)
-
-            val clientKeysPath = cfg.requirePath("nexus-ebics", 
"client_private_keys_file")
-            val bankKeysPath = cfg.requirePath("nexus-ebics", 
"bank_public_keys_file")
+        // Augment config
+        val simpleCfg = Path("test/$platform/ebics.conf").readText()
+        val conf = Path("test/$platform/ebics.edited.conf")
+        conf.writeText(
+        """$simpleCfg
+        [paths]
+        LIBEUFIN_NEXUS_HOME = test/$platform
+
+        [nexus-fetch]
+        FREQUENCY = 5s
+
+        [nexus-submit]
+        FREQUENCY = 5s
+
+        [nexus-postgres]
+        CONFIG = postgres:///libeufincheck
+        """)
+        val cfg = loadConfig(conf)
+
+        // Check if paltform is known
+        val kind = when (cfg.requireString("nexus-ebics", "host_base_url")) {
+            "https://isotest.postfinance.ch/ebicsweb/ebicsweb"; -> 
+                Kind("PostFinance IsoTest", 
"https://isotest.postfinance.ch/corporates/user/settings/ebics";)
+            "https://iso20022test.credit-suisse.com/ebicsweb/ebicsweb"; ->
+                Kind("Credit Suisse isoTest", 
"https://iso20022test.credit-suisse.com/user/settings/ebics";)   
+            "https://ebics.postfinance.ch/ebics/ebics.aspx"; -> 
+                Kind("PostFinance", null)
+            else -> Kind("Unknown", null)
+        }
+
+        // Prepare cmds
+        val log = "DEBUG"
+        val flags = " -c $conf -L $log"
+        val ebicsFlags = "$flags --transient --debug-ebics test/$platform"
+        val clientKeysPath = cfg.requirePath("nexus-ebics", 
"client_private_keys_file")
+        val bankKeysPath = cfg.requirePath("nexus-ebics", 
"bank_public_keys_file")
+
+        var hasClientKeys = clientKeysPath.exists()
+        var hasBankKeys = bankKeysPath.exists()
+
+        // Alternative payto ?
+        val payto = 
"payto://iban/CH6208704048981247126?receiver-name=Grothoff%20Hans"
         
-            var hasClientKeys = clientKeysPath.exists()
-            var hasBankKeys = bankKeysPath.exists()
+        runBlocking {
+            step("Test init ${kind.name}")
 
             if (ask("Reset DB ? y/n>") == "y") nexusCmd.test("dbinit -r 
$flags").assertOk()
             else nexusCmd.test("dbinit $flags").assertOk()
             val nexusDb = NexusDb("postgresql:///libeufincheck")
 
-            when (kind) {
-                Kind.postfinance -> {
-                    if (hasClientKeys || hasBankKeys) {
-                        if (ask("Reset keys ? y/n>") == "y") {
-                            if (hasClientKeys) clientKeysPath.deleteIfExists()
-                            if (hasBankKeys) bankKeysPath.deleteIfExists()
-                            hasClientKeys = false
-                            hasBankKeys = false
+            val cmds = buildMap<String, suspend () -> Unit> {
+                put("reset-db", suspend {
+                    nexusCmd.test("dbinit -r $flags").assertOk()
+                })
+                put("recover", suspend {
+                    step("Recover old transactions")
+                    nexusCmd.test("ebics-fetch $ebicsFlags --pinned-start 
2022-01-01").assertOk()
+                })
+                put("fetch", suspend {
+                    step("Fetch new transactions")
+                    nexusCmd.test("ebics-fetch $ebicsFlags").assertOk()
+                })
+                put("submit", suspend {
+                    step("Submit pending transactions")
+                    nexusCmd.test("ebics-submit $ebicsFlags").assertOk()
+                })
+                put("logs", suspend {
+                    step("Fetch HAC logs")
+                    nexusCmd.test("ebics-fetch $ebicsFlags 
--only-logs").assertOk()
+                })
+                put("ack", suspend {
+                    step("Fetch CustomerPaymentStatusReport")
+                    nexusCmd.test("ebics-fetch $ebicsFlags 
--only-ack").assertOk()
+                })
+                if (kind.test) {
+                    put("reset-keys", suspend {
+                        clientKeysPath.deleteIfExists()
+                        bankKeysPath.deleteIfExists()
+                        hasClientKeys = false
+                        hasBankKeys = false
+                    })
+                    put("tx", suspend {
+                        step("Test submit one transaction")
+                        nexusDb.initiatedPaymentCreate(InitiatedPayment(
+                            amount = TalerAmount("CFH:42"),
+                            creditPaytoUri = IbanPayto(payto).requireFull(),
+                            wireTransferSubject = "single transaction test",
+                            initiationTime = Instant.now(),
+                            requestUid = Base32Crockford.encode(randBytes(16))
+                        ))
+                        nexusCmd.test("ebics-submit $ebicsFlags").assertOk()
+                    })
+                    put("txs", suspend {
+                        step("Test submit many transaction")
+                        repeat(4) {
+                            nexusDb.initiatedPaymentCreate(InitiatedPayment(
+                                amount = TalerAmount("CFH:${100L+it}"),
+                                creditPaytoUri = 
IbanPayto(payto).requireFull(),
+                                wireTransferSubject = "multi transaction test 
$it",
+                                initiationTime = Instant.now(),
+                                requestUid = 
Base32Crockford.encode(randBytes(16))
+                            ))
                         }
-                    }
-                  
-                    if (!hasClientKeys) {
+                        nexusCmd.test("ebics-submit $ebicsFlags").assertOk()
+                    })
+                } else {
+                    put("tx", suspend {
+                        step("Submit new transaction")
+                        // TODO interactive payment editor
+                        nexusDb.initiatedPaymentCreate(InitiatedPayment(
+                            amount = TalerAmount("CFH:1.1"),
+                            creditPaytoUri = IbanPayto(payto).requireFull(),
+                            wireTransferSubject = "single transaction test",
+                            initiationTime = Instant.now(),
+                            requestUid = Base32Crockford.encode(randBytes(16))
+                        ))
+                        nexusCmd.test("ebics-submit $ebicsFlags").assertOk()
+                    })
+                }
+            }
+
+            while (true) {
+                if (!hasClientKeys) {
+                    if (kind.test) {
                         step("Test INI order")
-                        ask("Got to 
https://isotest.postfinance.ch/corporates/user/settings/ebics and click on 
'Reset EBICS user'.\nPress Enter when done>")
+                        ask("Got to ${kind.settings} and click on 'Reset EBICS 
user'.\nPress Enter when done>")
                         nexusCmd.test("ebics-setup $flags")
                             .assertErr("ebics-setup should failed the first 
time")
-                    }
-        
-                    if (!hasBankKeys) {
-                        step("Test HIA order")
-                        ask("Got to 
https://isotest.postfinance.ch/corporates/user/settings/ebics and click on 
'Activate EBICS user'.\nPress Enter when done>")
-                        nexusCmd.test("ebics-setup --auto-accept-keys $flags")
-                            .assertOk("ebics-setup should succeed the second 
time")
-                    }
-                   
-                    val payto = 
"payto://iban/CH2989144971918294289?receiver-name=Test"
-        
-                    step("Test fetch transactions")
-                    nexusCmd.test("ebics-fetch $ebicsFlags --pinned-start 
2022-01-01").assertOk()
-
-                    while (true) {
-                        when (ask("Run 'fetch', 'submit', 'tx', 'txs', 'logs', 
'ack' or 'exit'>")) {
-                            "fetch" -> {
-                                step("Fetch new transactions")
-                                nexusCmd.test("ebics-fetch 
$ebicsFlags").assertOk()
-                            }
-                            "tx" -> {
-                                step("Test submit one transaction")
-                                
nexusDb.initiatedPaymentCreate(InitiatedPayment(
-                                    amount = TalerAmount("CFH:42"),
-                                    creditPaytoUri = 
IbanPayto(payto).requireFull(),
-                                    wireTransferSubject = "single transaction 
test",
-                                    initiationTime = Instant.now(),
-                                    requestUid = 
Base32Crockford.encode(randBytes(16))
-                                ))
-                                nexusCmd.test("ebics-submit 
$ebicsFlags").assertOk()
-                            }
-                            "txs" -> {
-                                step("Test submit many transaction")
-                                repeat(4) {
-                                    
nexusDb.initiatedPaymentCreate(InitiatedPayment(
-                                        amount = TalerAmount("CFH:${100L+it}"),
-                                        creditPaytoUri = 
IbanPayto(payto).requireFull(),
-                                        wireTransferSubject = "multi 
transaction test $it",
-                                        initiationTime = Instant.now(),
-                                        requestUid = 
Base32Crockford.encode(randBytes(16))
-                                    ))
-                                }
-                                nexusCmd.test("ebics-submit 
$ebicsFlags").assertOk()
-                            }
-                            "submit" -> {
-                                step("Submit pending transactions")
-                                nexusCmd.test("ebics-submit 
$ebicsFlags").assertOk()
-                            }
-                            "logs" -> {
-                                step("Fetch logs")
-                                nexusCmd.test("ebics-fetch $ebicsFlags 
--only-logs").assertOk()
-                            }
-                            "ack" -> {
-                                step("Fetch ack")
-                                nexusCmd.test("ebics-fetch $ebicsFlags 
--only-ack").assertOk()
-                            }
-                            "exit" -> break
-                        }
-                    }
-                }
-                Kind.netzbon -> {
-                    if (!hasClientKeys)
+                        ask("Got to ${kind.settings} and click on 'Activate 
EBICS user'.\nPress Enter when done>")
+                    } else {
                         throw Exception("Clients keys are required to run 
netzbon tests")
-                        
-                    if (!hasBankKeys) {
-                        step("Test HIA order")
-                        nexusCmd.test("ebics-setup --auto-accept-keys 
$flags").assertOk("ebics-setup should succeed the second time")
                     }
+                } 
     
-                    step("Test fetch transactions")
-                    nexusCmd.test("ebics-fetch $ebicsFlags --pinned-start 
2022-01-01").assertOk()
+                if (!hasBankKeys) {
+                    step("Test HIA order")
+                    nexusCmd.test("ebics-setup --auto-accept-keys $flags")
+                        .assertOk("ebics-setup should succeed the second time")
+                }
 
-                    while (true) {
-                        when (ask("Run 'fetch', 'submit', 'logs', 'ack' or 
'exit'>")) {
-                            "fetch" -> {
-                                step("Fetch new transactions")
-                                nexusCmd.test("ebics-fetch 
$ebicsFlags").assertOk()
-                            }
-                            "submit" -> {
-                                step("Submit pending transactions")
-                                nexusCmd.test("ebics-submit 
$ebicsFlags").assertOk()
-                            }
-                            "tx" -> {
-                                step("Submit new transaction")
-                                // TODO interactive payment editor
-                                
nexusDb.initiatedPaymentCreate(InitiatedPayment(
-                                    amount = TalerAmount("CFH:1.1"),
-                                    creditPaytoUri = 
IbanPayto("payto://iban/CH6208704048981247126?receiver-name=Grothoff%20Hans").requireFull(),
-                                    wireTransferSubject = "single transaction 
test",
-                                    initiationTime = Instant.now(),
-                                    requestUid = 
Base32Crockford.encode(randBytes(16))
-                                ))
-                                nexusCmd.test("ebics-submit 
$ebicsFlags").assertOk()
-                            }
-                            "logs" -> {
-                                step("Fetch logs")
-                                nexusCmd.test("ebics-fetch $ebicsFlags 
--only-logs").assertOk()
-                            }
-                            "ack" -> {
-                                step("Fetch ack")
-                                nexusCmd.test("ebics-fetch $ebicsFlags 
--only-ack").assertOk()
-                            }
-                            "exit" -> break
-                        }
+                val arg = ask("testbench >")!!.trim()
+                if (arg == "exit") break
+                val cmd = cmds[arg]
+                if (cmd != null) {
+                    cmd()
+                } else {
+                    if (arg != "?" && arg != "help") {
+                        println("Unknown command '$arg'")
+                    }
+                    println("Commands:")
+                    for ((name, _) in cmds) {
+                        println("  $name")
                     }
                 }
             }
         }
-                
-        step("Test succeed")
     }
 }
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]