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 }