libeufin

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

TxCheck.kt (3503B)


      1 /*
      2  * This file is part of LibEuFin.
      3  * Copyright (C) 2024-2025 Taler Systems S.A.
      4  *
      5  * LibEuFin is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU Affero General Public License as
      7  * published by the Free Software Foundation; either version 3, or
      8  * (at your option) any later version.
      9  *
     10  * LibEuFin is distributed in the hope that it will be useful, but
     11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
     13  * Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Affero General Public
     16  * License along with LibEuFin; see the file COPYING.  If not, see
     17  * <http://www.gnu.org/licenses/>
     18  */
     19 
     20 package tech.libeufin.ebics.test
     21 
     22 import io.ktor.client.*
     23 import tech.libeufin.common.*
     24 import tech.libeufin.ebics.*
     25 import org.slf4j.Logger
     26 import org.slf4j.LoggerFactory
     27 
     28 data class TxCheckResult(
     29     var concurrentFetchAndFetch: Boolean = false,
     30     var concurrentFetchAndSubmit: Boolean = false,
     31     var concurrentSubmitAndSubmit: Boolean = false,
     32     var idempotentClose: Boolean = false
     33 )
     34 
     35 /**
     36  * Test EBICS implementation's transactions semantic:
     37  * - Can two fetch transactions run concurrently ?
     38  * - Can a fetch & submit transactions run concurrently ?
     39  * - Can two submit transactions run concurrently ?
     40  * - Is closing a submit transaction idempotent
     41  */
     42 suspend fun txCheck(
     43     client: HttpClient,
     44     cfg: EbicsHostConfig,
     45     clientKeys: ClientPrivateKeysFile,
     46     bankKeys: BankPublicKeysFile,
     47     fetchOrder: EbicsOrder,
     48     submitOrder: EbicsOrder
     49 ): TxCheckResult {
     50     val result = TxCheckResult()
     51     val fetch = EbicsBTS(cfg, bankKeys, clientKeys, fetchOrder)
     52     val submit = EbicsBTS(cfg, bankKeys, clientKeys, submitOrder)
     53     val ebicsLogger = EbicsLogger(null).tx("test").step("step")
     54 
     55     suspend fun EbicsBTS.close(id: String, phase: String, ebicsLogger: StepLogger) {
     56         val xml = downloadReceipt(id, false)
     57         postBTS(client, xml, phase, ebicsLogger)
     58     }
     59 
     60     val firstTxId = fetch.postBTS(client, fetch.downloadInitialization(null, null), "Init first fetch", ebicsLogger)
     61         .transactionID!!
     62     try {
     63         try {
     64             val id = fetch.postBTS(client, fetch.downloadInitialization(null, null), "Init second fetch", ebicsLogger).transactionID!!
     65             result.concurrentFetchAndFetch = true
     66             fetch.close(id, "Init second fetch", ebicsLogger)
     67         } catch (e: EbicsError.Code) {}
     68         
     69         var paylod = prepareUploadPayload(cfg, clientKeys, bankKeys, ByteArray(2000000).rand())
     70         try {
     71             val submitId = submit.postBTS(client, submit.uploadInitialization(paylod), "Init first submit", ebicsLogger). transactionID!!
     72             result.concurrentFetchAndSubmit = true
     73             submit.postBTS(client, submit.uploadTransfer(submitId, paylod, 1), "Submit first upload", ebicsLogger)
     74             try {
     75                 submit.postBTS(client, submit.uploadInitialization(paylod), "Init second submit", ebicsLogger)
     76                 result.concurrentSubmitAndSubmit = true
     77             } catch (e: EbicsError.Code) {}
     78         } catch (e: EbicsError.Code) {}
     79     } finally {
     80         fetch.close(firstTxId, "Close first fetch", ebicsLogger)
     81     }
     82 
     83     try {
     84         fetch.close(firstTxId, "Close first fetch a second time", ebicsLogger)
     85         result.idempotentClose = true
     86     } catch (e: Exception) {
     87         logger.debug { e.fmt() }
     88     }
     89 
     90     return result
     91 }