diff --git a/pom.xml b/pom.xml index fb3c039..614ede7 100644 --- a/pom.xml +++ b/pom.xml @@ -83,33 +83,25 @@ - - org.assertj - assertj-core - ${version.org.assertj} - test - - org.junit.jupiter junit-jupiter-api ${version.org.junit.jupiter} test - org.junit.jupiter junit-jupiter-engine ${version.org.junit.jupiter} test - - com.squareup.okhttp3 - mockwebserver - ${version.com.squareup.okhttp3} + org.jetbrains.kotlin + kotlin-test-junit5 + ${version.kotlin} test + diff --git a/src/main/kotlin/xyz/block/dap/DAP.kt b/src/main/kotlin/xyz/block/dap/DAP.kt deleted file mode 100644 index 4e67bc7..0000000 --- a/src/main/kotlin/xyz/block/dap/DAP.kt +++ /dev/null @@ -1,10 +0,0 @@ -package xyz.block.dap - -data class DAP( - val handle: String, - val domain: String -) { - override fun toString(): String { - return "@$handle/$domain'" - } -} diff --git a/src/main/kotlin/xyz/block/dap/Dap.kt b/src/main/kotlin/xyz/block/dap/Dap.kt new file mode 100644 index 0000000..039e350 --- /dev/null +++ b/src/main/kotlin/xyz/block/dap/Dap.kt @@ -0,0 +1,34 @@ +package xyz.block.dap + +import java.util.regex.Pattern + +data class Dap( + val handle: String, + val domain: String +) { + override fun toString(): String { + return "$PREFIX$handle$SEPARATOR$domain'" + } + + companion object { + const val PREFIX = "@" + const val SEPARATOR = "/" + + private const val DAP_REGEX = """^$PREFIX([^$PREFIX$SEPARATOR]+)$SEPARATOR([^$PREFIX$SEPARATOR]+)$""" + private val DAP_PATTERN = Pattern.compile(DAP_REGEX) + + fun parse(dap: String): Dap { + val matcher = DAP_PATTERN.matcher(dap) + matcher.find() + if (!matcher.matches()) { + throw InvalidDapException + } + val handle = matcher.group(1) + val domain = matcher.group(2) + + return Dap(handle, domain) + } + } +} + +object InvalidDapException : Throwable(message = "Invalid DAP") diff --git a/src/main/kotlin/xyz/block/maddr/MoneyAddress.kt b/src/main/kotlin/xyz/block/maddr/MoneyAddress.kt index 6824e04..ce42ec4 100644 --- a/src/main/kotlin/xyz/block/maddr/MoneyAddress.kt +++ b/src/main/kotlin/xyz/block/maddr/MoneyAddress.kt @@ -1,14 +1,14 @@ package xyz.block.maddr import xyz.block.maddr.MoneyAddress.Companion.KIND -import xyz.block.maddr.urn.URN +import xyz.block.maddr.urn.Urn // TODO(aparker) - placeholder, this should come from web5-kt data class DidService(val id: String, val type: String, val serviceEndpoints: List) data class MoneyAddress( val id: String, - val urn: URN, + val urn: Urn, val currency: String, val css: String ) { @@ -19,11 +19,11 @@ data class MoneyAddress( fun DidService.toMoneyAddresses(): List { if (type != KIND) { - throw InvalidMoneyAddressException("invalid service type: $type") + throw InvalidMoneyAddressException } return serviceEndpoints.map { endpoint -> - val urn = URN.parse(endpoint) + val urn = Urn.parse(endpoint) MoneyAddress( id = id, urn = urn, @@ -33,5 +33,4 @@ fun DidService.toMoneyAddresses(): List { } } -data class InvalidMoneyAddressException(val invalidValue: String) : - Throwable("Invalid MoneyAddress: $invalidValue") +object InvalidMoneyAddressException : Throwable("Invalid MoneyAddress") diff --git a/src/main/kotlin/xyz/block/maddr/urn/URN.kt b/src/main/kotlin/xyz/block/maddr/urn/URN.kt deleted file mode 100644 index d562d52..0000000 --- a/src/main/kotlin/xyz/block/maddr/urn/URN.kt +++ /dev/null @@ -1,39 +0,0 @@ -package xyz.block.maddr.urn - -data class URN( - val nid: String, - val nss: String -) { - private val urn: String = "$PREFIX$nid:$nss" - - override fun toString(): String { - return urn - } - - companion object { - const val PREFIX = "urn:" - - fun parse(input: String): URN { - if (!input.startsWith(PREFIX)) { - throw InvalidUrnException("incorrect prefix", input) - } - val urnBody = input.substringAfter(PREFIX) - if (urnBody.isBlank()) { - throw InvalidUrnException("missing body", input) - } - val nid = urnBody.substringBefore(":") - val nss = urnBody.substringAfter(":") - - if (nid.isBlank()) { - throw InvalidUrnException("missing nid", input) - } - if (nss.isBlank() || nss == urnBody) { - throw InvalidUrnException("missing nss", input) - } - return URN(nid, nss) - } - } -} - -data class InvalidUrnException(val reason: String, val invalidValue: String) : - Throwable("Invalid URN: $reason: $invalidValue") diff --git a/src/main/kotlin/xyz/block/maddr/urn/Urn.kt b/src/main/kotlin/xyz/block/maddr/urn/Urn.kt new file mode 100644 index 0000000..8976b3b --- /dev/null +++ b/src/main/kotlin/xyz/block/maddr/urn/Urn.kt @@ -0,0 +1,35 @@ +package xyz.block.maddr.urn + +import java.util.regex.Pattern + +data class Urn( + val nid: String, + val nss: String +) { + private val urn: String = "$PREFIX$nid:$nss" + + override fun toString(): String { + return urn + } + + companion object { + const val PREFIX = "urn:" + private const val SEPARATOR = ":" + + private val URN_PATTERN = Pattern.compile("""^${PREFIX}([^$SEPARATOR]+)$SEPARATOR(.+)$""") + + fun parse(urn: String): Urn { + val matcher = URN_PATTERN.matcher(urn) + matcher.find() + if (!matcher.matches()) { + throw InvalidUrnException + } + val nid = matcher.group(1) + val nss = matcher.group(2) + + return Urn(nid, nss) + } + } +} + +object InvalidUrnException : Throwable("Invalid URN") diff --git a/src/test/kotlin/xyz/block/dap/DAPTest.kt b/src/test/kotlin/xyz/block/dap/DAPTest.kt deleted file mode 100644 index 1b8234a..0000000 --- a/src/test/kotlin/xyz/block/dap/DAPTest.kt +++ /dev/null @@ -1,13 +0,0 @@ -package xyz.block.dap - -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test - -class DAPTest { - - @Test - fun testDapStringRepresentation() { - val dap = DAP("handle", "domain.com") - assertEquals("@handle/domain.com'", dap.toString()) - } -} diff --git a/src/test/kotlin/xyz/block/dap/DapTest.kt b/src/test/kotlin/xyz/block/dap/DapTest.kt new file mode 100644 index 0000000..2fd239a --- /dev/null +++ b/src/test/kotlin/xyz/block/dap/DapTest.kt @@ -0,0 +1,42 @@ +package xyz.block.dap + +import org.junit.jupiter.api.assertThrows +import kotlin.test.Test +import kotlin.test.assertEquals + +class DapTest { + + @Test + fun testDapToString() { + val dap = Dap("handle", "domain.com") + assertEquals("@handle/domain.com'", dap.toString()) + } + + @Test + fun testParseDap() { + val dap = Dap.parse("@handle/domain.com") + assertEquals("handle", dap.handle) + assertEquals("domain.com", dap.domain) + } + + @Test + fun testParseInvalidDaps() { + val invalidDaps = listOf( + "", + "a", + "@handle", + "@handle/", + "@handle@/domain.com", + "@handle//domain.com", + "@handle/@domain.com", + "@handle/domain.com@", + "@handle/domain.com/", + ) + for (dap in invalidDaps) { + val exception = assertThrows { + Dap.parse(dap) + } + assertEquals("Invalid DAP", exception.message) + } + } +} diff --git a/src/test/kotlin/xyz/block/maddr/MoneyAddressTest.kt b/src/test/kotlin/xyz/block/maddr/MoneyAddressTest.kt index e3e2f4a..fc42d2c 100644 --- a/src/test/kotlin/xyz/block/maddr/MoneyAddressTest.kt +++ b/src/test/kotlin/xyz/block/maddr/MoneyAddressTest.kt @@ -1,11 +1,12 @@ package xyz.block.maddr -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertThrows -import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows import xyz.block.maddr.urn.InvalidUrnException +import kotlin.test.Test +import kotlin.test.assertEquals class MoneyAddressTest { + @Test fun testDidToMoneyAddress() { val did = DidService("didpay", "maddr", listOf("urn:nid:nss")) @@ -59,7 +60,7 @@ class MoneyAddressTest { @Test fun testDidToMoneyAddressInvalidServiceType() { - assertThrows(InvalidMoneyAddressException::class.java) { + assertThrows { val did = DidService("didpay", "not-maddr", listOf("urn:nid:nss")) did.toMoneyAddresses() } @@ -67,10 +68,9 @@ class MoneyAddressTest { @Test fun testDidToMoneyAddressInvalidUrn() { - assertThrows(InvalidUrnException::class.java) { + assertThrows { val did = DidService("didpay", "maddr", listOf("not-a-urn")) did.toMoneyAddresses() } } } - diff --git a/src/test/kotlin/xyz/block/maddr/urn/URNTest.kt b/src/test/kotlin/xyz/block/maddr/urn/URNTest.kt deleted file mode 100644 index 1d432f1..0000000 --- a/src/test/kotlin/xyz/block/maddr/urn/URNTest.kt +++ /dev/null @@ -1,50 +0,0 @@ -package xyz.block.maddr.urn - -import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.Test - -class URNTest { - @Test - fun testUrnParsing() { - val urn = URN.parse("urn:nid:nss") - assertEquals("urn:nid:nss", urn.toString()) - assertEquals("nid", urn.nid) - assertEquals("nss", urn.nss) - } - - @Test - fun testUrnParsingWithNssParts() { - val urn = URN.parse("urn:nid:nss1:nss2:nss3") - assertEquals("urn:nid:nss1:nss2:nss3", urn.toString()) - assertEquals("nid", urn.nid) - assertEquals("nss1:nss2:nss3", urn.nss) - } - - @Test - fun testUrnParsingInvalidPrefix() { - assertThrows(InvalidUrnException::class.java) { - URN.parse("invalid:nid:nss") - } - } - - @Test - fun testUrnParsingEmptyNss() { - assertThrows(InvalidUrnException::class.java) { - URN.parse("urn:nid:") - } - } - - @Test - fun testUrnParsingMissingNss() { - assertThrows(InvalidUrnException::class.java) { - URN.parse("urn:nid") - } - } - - @Test - fun testUrnParsingMissingNid() { - assertThrows(InvalidUrnException::class.java) { - URN.parse("uri:") - } - } -} \ No newline at end of file diff --git a/src/test/kotlin/xyz/block/maddr/urn/UrnTest.kt b/src/test/kotlin/xyz/block/maddr/urn/UrnTest.kt new file mode 100644 index 0000000..90c56cd --- /dev/null +++ b/src/test/kotlin/xyz/block/maddr/urn/UrnTest.kt @@ -0,0 +1,43 @@ +package xyz.block.maddr.urn + +import org.junit.jupiter.api.assertThrows +import kotlin.test.Test +import kotlin.test.assertEquals + +class UrnTest { + + @Test + fun testUrnParsing() { + val urn = Urn.parse("urn:nid:nss") + assertEquals("urn:nid:nss", urn.toString()) + assertEquals("nid", urn.nid) + assertEquals("nss", urn.nss) + } + + @Test + fun testUrnParsingWithNssParts() { + val urn = Urn.parse("urn:nid:nss1:nss2:nss3") + assertEquals("urn:nid:nss1:nss2:nss3", urn.toString()) + assertEquals("nid", urn.nid) + assertEquals("nss1:nss2:nss3", urn.nss) + } + + @Test + fun testParseInvalidUrn() { + val invalidUrns = listOf( + "", + "invalid:nid:nss", + "invalid::nss", + "invalid:nid:", + "invalid:nid", + "invalid:", + "invalid::", + ) + for (urn in invalidUrns) { + val exception = assertThrows { + Urn.parse(urn) + } + assertEquals("Invalid URN", exception.message) + } + } +}