test: add util tests

This commit is contained in:
2026-06-12 16:14:08 +02:00
parent 4756681a2a
commit 321c3d9c55
14 changed files with 1282 additions and 104 deletions
@@ -0,0 +1,169 @@
package com.bitcointxoko.gudariwallet.util
import android.net.Uri
import io.mockk.every
import io.mockk.mockkStatic
import io.mockk.unmockkStatic
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
class Bip21ParserTest {
@Before
fun setUp() {
// Mock android.net.Uri.decode so tests run on the JVM without Android
mockkStatic(Uri::class)
// Default: pass-through (no encoding in most test inputs)
every { Uri.decode(any()) } answers { firstArg() }
}
@After
fun tearDown() {
unmockkStatic(Uri::class)
}
// -------------------------------------------------------------------------
// Full BIP-21 URI
// -------------------------------------------------------------------------
@Test
fun `full URI with single param returns correct map`() {
val result = Bip21Parser.parseParams("bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf?amount=0.001")
assertEquals(mapOf("amount" to "0.001"), result)
}
@Test
fun `full URI with multiple params returns all params`() {
val result = Bip21Parser.parseParams(
"bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf?amount=0.5&label=Foo&message=Bar"
)
assertEquals(
mapOf("amount" to "0.5", "label" to "Foo", "message" to "Bar"),
result
)
}
@Test
fun `full URI with no query string returns empty map`() {
val result = Bip21Parser.parseParams("bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf")
assertTrue(result.isEmpty())
}
@Test
fun `full URI with empty query string after question mark returns empty map`() {
val result = Bip21Parser.parseParams("bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf?")
assertTrue(result.isEmpty())
}
// -------------------------------------------------------------------------
// Raw query string (no URI prefix)
// -------------------------------------------------------------------------
@Test
fun `bare query string with single param returns correct map`() {
val result = Bip21Parser.parseParams("amount=0.001")
assertEquals(mapOf("amount" to "0.001"), result)
}
@Test
fun `bare query string with multiple params returns all params`() {
val result = Bip21Parser.parseParams("amount=0.001&label=Satoshi")
assertEquals(mapOf("amount" to "0.001", "label" to "Satoshi"), result)
}
// -------------------------------------------------------------------------
// URI-encoded values
// -------------------------------------------------------------------------
@Test
fun `percent-encoded value is decoded`() {
every { Uri.decode("Hello%20World") } returns "Hello World"
val result = Bip21Parser.parseParams("label=Hello%20World")
assertEquals(mapOf("label" to "Hello World"), result)
}
@Test
fun `percent-encoded value in full URI is decoded`() {
every { Uri.decode("Thank%20You") } returns "Thank You"
val result = Bip21Parser.parseParams(
"bitcoin:addr?message=Thank%20You"
)
assertEquals(mapOf("message" to "Thank You"), result)
}
// -------------------------------------------------------------------------
// Edge cases — blank / empty input
// -------------------------------------------------------------------------
@Test
fun `empty string returns empty map`() {
val result = Bip21Parser.parseParams("")
assertTrue(result.isEmpty())
}
@Test
fun `blank string returns empty map`() {
val result = Bip21Parser.parseParams(" ")
assertTrue(result.isEmpty())
}
// -------------------------------------------------------------------------
// Malformed pairs
// -------------------------------------------------------------------------
@Test
fun `pair with no equals sign is skipped`() {
// "label" has no '=', "amount=0.1" is valid
val result = Bip21Parser.parseParams("label&amount=0.1")
assertEquals(mapOf("amount" to "0.1"), result)
}
@Test
fun `pair starting with equals sign (empty key) is skipped`() {
// idx == 0, which is < 1, so this pair should be dropped
val result = Bip21Parser.parseParams("=value&amount=0.1")
assertEquals(mapOf("amount" to "0.1"), result)
}
@Test
fun `all malformed pairs return empty map`() {
val result = Bip21Parser.parseParams("noequalssign&=emptykey")
assertTrue(result.isEmpty())
}
// -------------------------------------------------------------------------
// Param with empty value
// -------------------------------------------------------------------------
@Test
fun `param with empty value is included with empty string`() {
val result = Bip21Parser.parseParams("label=")
assertEquals(mapOf("label" to ""), result)
}
// -------------------------------------------------------------------------
// Duplicate keys
// -------------------------------------------------------------------------
@Test
fun `duplicate keys — last value wins`() {
// Kotlin's toMap() on a list of pairs keeps the last value for duplicates
val result = Bip21Parser.parseParams("amount=0.001&amount=0.999")
assertEquals(mapOf("amount" to "0.999"), result)
}
// -------------------------------------------------------------------------
// Lightning / BIP-21 extensions (lightning param)
// -------------------------------------------------------------------------
@Test
fun `lightning param is parsed correctly`() {
val bolt11 = "lnbc1pvjluezpp5qqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqqqsyqcyq5rqwzqfqypqdpl2pkx"
every { Uri.decode(bolt11) } returns bolt11
val result = Bip21Parser.parseParams("amount=0.001&lightning=$bolt11")
assertEquals(bolt11, result["lightning"])
}
}