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 }