libeufin

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

EncodingTest.kt (4519B)


      1 /*
      2  * This file is part of LibEuFin.
      3  * Copyright (C) 2024 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.junit.Test
     21 import tech.libeufin.common.Base32Crockford
     22 import tech.libeufin.common.rand
     23 import kotlin.test.assertContentEquals
     24 import kotlin.test.assertEquals
     25 import kotlin.test.assertFailsWith
     26 
     27 class EncodingTest {
     28     @Test
     29     fun base32() {
     30         fun roundTripBytes(data: ByteArray) {
     31             val encoded = Base32Crockford.encode(data)
     32             val decoded = Base32Crockford.decode(encoded)
     33             assertContentEquals(data, decoded)
     34         }
     35 
     36         // Empty
     37         assert(Base32Crockford.encode(ByteArray(0)).isEmpty())
     38         assert(Base32Crockford.decode("").isEmpty())
     39         roundTripBytes(ByteArray(0))
     40 
     41         // Many size
     42         for (size in 0..100) {
     43             roundTripBytes(ByteArray(size).rand())
     44         }
     45 
     46         val ORIGINAL    = "00111VVBASE32TESTXRST7M8J4H2VY3E0N561BAFWDCPKQG9ZNTG"
     47         val LOWERCASE   = "00111vvbase32testxrst7m8j4h2vy3e0n561bafwdcpkqg9zntg"
     48         val ALT         = "0O1ILVUBASE32TESTXRST7M8J4H2VY3E0N561BAFWDCPKQG9ZNTG"
     49         val ALT_LOWER   = "0o1ilvubase32testxrst7m8j4h2vy3e0n561bafwdcpkqg9zntg"
     50         val specialCases = listOf(LOWERCASE, ALT, ALT_LOWER)
     51 
     52         // Common case
     53         val decoded = Base32Crockford.decode(ORIGINAL)
     54         assertEquals(ORIGINAL, Base32Crockford.encode(decoded))
     55 
     56         // Special cases
     57         for (case in specialCases) {
     58             assertContentEquals(decoded, Base32Crockford.decode(case))
     59         }
     60 
     61         // Bad cases
     62         for (case in listOf('(', '\n', '@')) {
     63             val err = assertFailsWith<IllegalArgumentException> {
     64                 Base32Crockford.decode("CROCKFORDBASE32${case}TESTDATA")
     65             }
     66             assertEquals("invalid Base32 character: $case", err.message)
     67         }
     68         assertFailsWith<IllegalArgumentException> {
     69             Base32Crockford.decode("CROCKFORDBASE32🤯TESTDATA")
     70         }
     71 
     72         // Gnunet check
     73         val gnunetInstalled = try {
     74             val exitValue = ProcessBuilder("gnunet-base32", "-v").start().waitFor()
     75             exitValue == 0
     76         } catch (e: java.io.IOException) {
     77             false
     78         }
     79         if (gnunetInstalled) {
     80             for (size in 0..100) {
     81                 // Generate random blob
     82                 val blob = ByteArray(size).rand()
     83 
     84                 // Encode with kotlin
     85                 val encoded = Base32Crockford.encode(blob)
     86                 // Encode with gnunet
     87                 val gnunetEncoded = ProcessBuilder("gnunet-base32").start().run {
     88                     outputStream.use { it.write(blob) }
     89                     waitFor()
     90                     inputStream.readBytes().decodeToString()
     91                 }
     92                 // Check match
     93                 assertEquals(encoded, gnunetEncoded)
     94 
     95                 // Decode with kotlin
     96                 val decoded = Base32Crockford.decode(encoded)
     97                 // Decode with gnunet
     98                 val gnunetDecoded = ProcessBuilder("gnunet-base32", "-d").start().run {
     99                     outputStream.use { it.write(encoded.toByteArray()) }
    100                     waitFor()
    101                     inputStream.readBytes()
    102                 }
    103                 // Check match
    104                 assertContentEquals(decoded, gnunetDecoded)
    105             }
    106             for (case in specialCases) {
    107                 // Decode with kotlin
    108                 val decoded = Base32Crockford.decode(case)
    109                 // Decode with gnunet
    110                 val gnunetDecoded = ProcessBuilder("gnunet-base32", "-d").start().run {
    111                     outputStream.use { it.write(case.toByteArray()) }
    112                     waitFor()
    113                     inputStream.readBytes()
    114                 }
    115                 // Check match
    116                 assertContentEquals(decoded, gnunetDecoded)
    117             }
    118         }
    119     }
    120 }