libeufin

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

EbicsTest.kt (6080B)


      1 /*
      2  * This file is part of LibEuFin.
      3  * Copyright (C) 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 import org.w3c.dom.Document
     21 import com.github.ajalt.clikt.core.CliktCommand
     22 import com.github.ajalt.clikt.testing.test
     23 import kotlinx.coroutines.runBlocking
     24 import io.ktor.http.*
     25 import io.ktor.http.content.*
     26 import org.junit.Test
     27 import tech.libeufin.nexus.cli.LibeufinNexus
     28 import tech.libeufin.nexus.*
     29 import tech.libeufin.common.*
     30 import tech.libeufin.common.test.*
     31 import tech.libeufin.common.crypto.CryptoUtil
     32 import tech.libeufin.ebics.test.*
     33 import tech.libeufin.ebics.*
     34 import kotlin.io.path.*
     35 import kotlin.test.*
     36 import java.time.LocalDate
     37 
     38 @OptIn(kotlin.io.path.ExperimentalPathApi::class)
     39 class EbicsTest {
     40     private val nexusCmd = LibeufinNexus()
     41     private val bank = EbicsState()
     42     private val args = "-L TRACE -c conf/fetch.conf"
     43 
     44     private fun ebicsSetup() {
     45         // Reset current keys
     46         val dir = Path("/tmp/ebics-test")
     47         dir.deleteRecursively()
     48         dir.createDirectories()
     49 
     50         // Set setup mock
     51         setMock(sequence {
     52             yield(bank::hev)
     53             yield(bank::ini)
     54             yield(bank::hia)
     55             yield(bank::hpb)
     56             yield(bank::hkd)
     57             yield(bank::receiptOk)
     58         })
     59 
     60         // Run setup
     61         nexusCmd.succeed("ebics-setup $args --auto-accept-keys")
     62     }
     63 
     64     @Test
     65     fun setup() {
     66         ebicsSetup()
     67     }
     68 
     69     @Test
     70     fun fetchPinnedDate() = setup { db, _ ->
     71         ebicsSetup()
     72 
     73         suspend fun resetCheckpoint() {
     74             db.serializable("DELETE FROM kv WHERE key=?") {
     75                 bind(CHECKPOINT_KEY)
     76                 executeUpdate()
     77             }
     78         }
     79 
     80         // Default transient
     81         setMock(sequence {
     82             yield(bank::haa)
     83             yield(bank::receiptOk)
     84             yield(bank::btdNoData)
     85         })
     86         nexusCmd.succeed("ebics-fetch $args --transient")
     87 
     88         // Pinned transient
     89         setMock(sequence {
     90             yield(bank::haa)
     91             yield(bank::receiptOk)
     92             yield(bank::btdNoDataPinned)
     93         })
     94         nexusCmd.succeed("ebics-fetch $args --transient --pinned-start 2024-06-05")
     95 
     96         // Init checkpoint
     97         setMock(sequence {
     98             yield(bank::hkd)
     99             yield(bank::receiptOk)
    100             yield(bank::btdNoData)
    101         })
    102         nexusCmd.succeed("ebics-fetch $args --transient --checkpoint")
    103 
    104         // Default checkpoint
    105         setMock(sequence {
    106             yield(bank::hkd)
    107             yield(bank::receiptOk)
    108             yield(bank::btdNoDataNow)
    109         })
    110         nexusCmd.succeed("ebics-fetch $args --transient --checkpoint")
    111 
    112         // Pinned checkpoint
    113         setMock(sequence {
    114             yield(bank::hkd)
    115             yield(bank::receiptOk)
    116             yield(bank::btdNoDataPinned)
    117         })
    118         nexusCmd.succeed("ebics-fetch $args --transient --checkpoint --pinned-start 2024-06-05")
    119 
    120         // Reset checkpoint
    121         resetCheckpoint()
    122         setMock(sequence {
    123             yield(bank::hkd)
    124             yield(bank::receiptOk)
    125             yield(bank::btdNoData)
    126         })
    127         nexusCmd.succeed("ebics-fetch $args --transient --checkpoint")
    128 
    129         // Reset checkpoint pinned
    130         resetCheckpoint()
    131         setMock(sequence {
    132             yield(bank::hkd)
    133             yield(bank::receiptOk)
    134             yield(bank::btdNoDataPinned)
    135         })
    136         nexusCmd.succeed("ebics-fetch $args --transient --checkpoint --pinned-start 2024-06-05")
    137     }
    138 
    139     @Test
    140     fun closePendingTransaction() = setup { db, _ ->
    141         ebicsSetup()
    142 
    143         // Failure before first segment
    144         setMock(sequence {
    145             // Failure to perform download
    146             yield(bank::failure)
    147             // Then continue
    148             yield(bank::haa)
    149             yield(bank::receiptOk)
    150             yield(bank::btdNoData)
    151         })
    152         nexusCmd.fail("ebics-fetch $args --transient")
    153         nexusCmd.succeed("ebics-fetch $args --transient")
    154 
    155         // Compliant server
    156         setMock(sequence {
    157             yield(bank::haa)
    158             yield(bank::receiptOk)
    159             // Failure to perform download
    160             yield(bank::initializeTx)
    161             yield(bank::failure)
    162             // Retry fail once
    163             yield(bank::failure)
    164             // Retry fail twice
    165             yield(bank::failure)
    166             // Retry succeed
    167             yield(bank::receiptErr)
    168             // Then continue
    169             yield(bank::haa)
    170             yield(bank::receiptOk)
    171             yield(bank::btdNoData)
    172         })
    173         nexusCmd.fail("ebics-fetch $args --transient")
    174         nexusCmd.fail("ebics-fetch $args --transient")
    175         nexusCmd.fail("ebics-fetch $args --transient")
    176         nexusCmd.succeed("ebics-fetch $args --transient")
    177 
    178         // Non compliant server
    179         setMock(sequence {
    180             yield(bank::haa)
    181             yield(bank::receiptOk)
    182             // Failure to perform download
    183             yield(bank::initializeTx)
    184             yield(bank::badRequest)
    185             // Retry fail
    186             yield(bank::failure)
    187 
    188             // Retry succeed
    189             yield(bank::badRequest)
    190             // Then continue
    191             yield(bank::haa)
    192             yield(bank::receiptOk)
    193             yield(bank::btdNoData)
    194         })
    195         nexusCmd.fail("ebics-fetch $args --transient")
    196         nexusCmd.fail("ebics-fetch $args --transient")
    197         nexusCmd.succeed("ebics-fetch $args --transient")
    198     }
    199 }