summaryrefslogtreecommitdiff
path: root/taler-kotlin-android/src/test/java/net/taler/common
diff options
context:
space:
mode:
Diffstat (limited to 'taler-kotlin-android/src/test/java/net/taler/common')
-rw-r--r--taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt372
-rw-r--r--taler-kotlin-android/src/test/java/net/taler/common/ContractTermsTest.kt9
-rw-r--r--taler-kotlin-android/src/test/java/net/taler/common/TalerUriTest.kt65
-rw-r--r--taler-kotlin-android/src/test/java/net/taler/common/TestUtils.kt40
-rw-r--r--taler-kotlin-android/src/test/java/net/taler/common/TimeTest.kt46
-rw-r--r--taler-kotlin-android/src/test/java/net/taler/common/VersionTest.kt65
6 files changed, 592 insertions, 5 deletions
diff --git a/taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt b/taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt
new file mode 100644
index 0000000..1ea4e70
--- /dev/null
+++ b/taler-kotlin-android/src/test/java/net/taler/common/AmountTest.kt
@@ -0,0 +1,372 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import android.os.Build
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Test
+import java.text.DecimalFormatSymbols
+import kotlin.random.Random
+
+class AmountTest {
+
+ companion object {
+ fun getRandomAmount() = getRandomAmount(getRandomString(1, Random.nextInt(1, 12)))
+ fun getRandomAmount(currency: String): Amount {
+ val value = Random.nextLong(0, Amount.MAX_VALUE)
+ val fraction = Random.nextInt(0, Amount.MAX_FRACTION)
+ return Amount(currency, value, fraction)
+ }
+ }
+
+ @Test
+ fun testFromJSONString() {
+ var str = "TESTKUDOS:23.42"
+ var amount = Amount.fromJSONString(str)
+ assertEquals(str, amount.toJSONString())
+ assertEquals("TESTKUDOS", amount.currency)
+ assertEquals(23, amount.value)
+ assertEquals((0.42 * 1e8).toInt(), amount.fraction)
+
+ str = "EUR:500000000.00000001"
+ amount = Amount.fromJSONString(str)
+ assertEquals(str, amount.toJSONString())
+ assertEquals("EUR", amount.currency)
+ assertEquals(500000000, amount.value)
+ assertEquals(1, amount.fraction)
+
+ str = "EUR:1500000000.00000003"
+ amount = Amount.fromJSONString(str)
+ assertEquals(str, amount.toJSONString())
+ assertEquals("EUR", amount.currency)
+ assertEquals(1500000000, amount.value)
+ assertEquals(3, amount.fraction)
+ }
+
+ @Test
+ fun testToString() {
+ amountToString(
+ amount = Amount.fromString("KUDOS", "13.71"),
+ spec = CurrencySpecification(
+ name = "Test (Taler Demostrator)",
+ numFractionalInputDigits = 2,
+ numFractionalNormalDigits = 2,
+ numFractionalTrailingZeroDigits = 2,
+ altUnitNames = mapOf(0 to "ク"),
+ ),
+ rawStr = "13.71",
+ fraction = 71000000,
+ specAmount = "13.71",
+ noSpecAmount = "13.71",
+ currency = "KUDOS",
+ symbol = "ク",
+ )
+
+ amountToString(
+ amount = Amount.fromString("TESTKUDOS", "23.42"),
+ spec = CurrencySpecification(
+ name = "Test (Taler Unstable Demostrator)",
+ numFractionalInputDigits = 0,
+ numFractionalNormalDigits = 0,
+ numFractionalTrailingZeroDigits = 0,
+ altUnitNames = mapOf(0 to "テ"),
+ ),
+ rawStr = "23.42",
+ fraction = 42000000,
+ specAmount = "23",
+ noSpecAmount = "23.42",
+ currency = "TESTKUDOS",
+ symbol = "テ",
+ )
+
+ amountToString(
+ amount = Amount.fromString("BITCOINBTC", "0.00000001"),
+ spec = CurrencySpecification(
+ name = "Bitcoin",
+ numFractionalInputDigits = 8,
+ numFractionalNormalDigits = 8,
+ numFractionalTrailingZeroDigits = 0,
+ altUnitNames = mapOf(
+ 0 to "₿",
+ // TODO: uncomment when units get implemented
+ // and then write tests for units, please
+// -1 to "d₿",
+// -2 to "c₿",
+// -3 to "m₿",
+// -6 to "µ₿",
+// -8 to "sat",
+ ),
+ ),
+ rawStr = "0.00000001",
+ fraction = 1,
+ specAmount = "0.00000001",
+ noSpecAmount = "0.00000001",
+ currency = "BITCOINBTC",
+ symbol = "₿",
+ )
+
+ val specEUR = CurrencySpecification(
+ name = "EUR",
+ numFractionalInputDigits = 2,
+ numFractionalNormalDigits = 2,
+ numFractionalTrailingZeroDigits = 2,
+ altUnitNames = mapOf(0 to "€"),
+ )
+
+ amountToString(
+ amount = Amount.fromString("EUR", "1500000000.00000003"),
+ spec = specEUR,
+ rawStr = "1500000000.00000003",
+ fraction = 3,
+ specAmount = "1,500,000,000.00",
+ noSpecAmount = "1,500,000,000.00000003",
+ currency = "EUR",
+ symbol = "€",
+ )
+
+ amountToString(
+ amount = Amount.fromString("EUR", "500000000.126"),
+ spec = specEUR,
+ rawStr = "500000000.126",
+ fraction = 12600000,
+ specAmount = "500,000,000.13",
+ noSpecAmount = "500,000,000.126",
+ currency = "EUR",
+ symbol = "€",
+ )
+
+ amountToString(
+ amount = Amount.fromString("NOSYMBOL", "13.24"),
+ spec = CurrencySpecification(
+ name = "No symbol!",
+ numFractionalInputDigits = 2,
+ numFractionalNormalDigits = 2,
+ numFractionalTrailingZeroDigits = 2,
+ altUnitNames = mapOf(),
+ ),
+ rawStr = "13.24",
+ fraction = 24000000,
+ specAmount = "13.24",
+ noSpecAmount = "13.24",
+ currency = "NOSYMBOL",
+ symbol = "NOSYMBOL",
+ )
+ }
+
+ private fun amountToString(
+ amount: Amount,
+ spec: CurrencySpecification,
+ rawStr: String,
+ fraction: Int,
+ specAmount: String,
+ noSpecAmount: String,
+ currency: String,
+ symbol: String,
+ ) {
+ val symbols = DecimalFormatSymbols.getInstance()
+ symbols.decimalSeparator = '.'
+ symbols.groupingSeparator = ','
+ symbols.monetaryDecimalSeparator = '.'
+ if (Build.VERSION.SDK_INT >= 34) {
+ symbols.monetaryGroupingSeparator = ','
+ }
+
+ // Only the raw amount
+ assertEquals(rawStr, amount.amountStr)
+ assertEquals(fraction, amount.fraction)
+
+ // The amount without currency spec
+ assertEquals("$noSpecAmount $currency", amount.toString(symbols = symbols))
+ assertEquals(noSpecAmount, amount.toString(symbols = symbols, showSymbol = false))
+ assertEquals("-$noSpecAmount $currency", amount.toString(symbols = symbols, negative = true))
+ assertEquals("-$noSpecAmount", amount.toString(symbols = symbols, showSymbol = false, negative = true))
+
+ // The amount with currency spec
+ val withSpec = amount.withSpec(spec)
+ assertEquals(specAmount, withSpec.toString(symbols = symbols, showSymbol = false))
+ assertEquals(specAmount, withSpec.toString(symbols = symbols, showSymbol = false))
+ assertEquals("-$specAmount", withSpec.toString(symbols = symbols, showSymbol = false, negative = true))
+ assertEquals("-$specAmount", withSpec.toString(symbols = symbols, showSymbol = false, negative = true))
+ if (spec.symbol != null) {
+ assertEquals("${symbol}$specAmount", withSpec.toString(symbols = symbols))
+ assertEquals("-${symbol}$specAmount", withSpec.toString(symbols = symbols, negative = true))
+ } else {
+ assertEquals("$specAmount $currency", withSpec.toString(symbols = symbols))
+ assertEquals("-$specAmount $currency", withSpec.toString(symbols = symbols, negative = true))
+ }
+ }
+
+ @Test
+ fun testFromJSONStringAcceptsMaxValuesRejectsAbove() {
+ val maxValue = 4503599627370496
+ val str = "TESTKUDOS123:$maxValue.99999999"
+ val amount = Amount.fromJSONString(str)
+ assertEquals(str, amount.toJSONString())
+ assertEquals("TESTKUDOS123", amount.currency)
+ assertEquals(maxValue, amount.value)
+
+ // longer currency not accepted
+ assertThrows<AmountParserException>("longer currency was accepted") {
+ Amount.fromJSONString("TESTKUDOS1234:$maxValue.99999999")
+ }
+
+ // max value + 1 not accepted
+ assertThrows<AmountParserException>("max value + 1 was accepted") {
+ Amount.fromJSONString("TESTKUDOS123:${maxValue + 1}.99999999")
+ }
+
+ // max fraction + 1 not accepted
+ assertThrows<AmountParserException>("max fraction + 1 was accepted") {
+ Amount.fromJSONString("TESTKUDOS123:$maxValue.999999990")
+ }
+ }
+
+ @Test
+ fun testFromJSONStringRejections() {
+ assertThrows<AmountParserException> {
+ Amount.fromJSONString("TESTKUDOS:0,5")
+ }
+ assertThrows<AmountParserException> {
+ Amount.fromJSONString("+TESTKUDOS:0.5")
+ }
+ assertThrows<AmountParserException> {
+ Amount.fromJSONString("0.5")
+ }
+ assertThrows<AmountParserException> {
+ Amount.fromJSONString(":0.5")
+ }
+ assertThrows<AmountParserException> {
+ Amount.fromJSONString("EUR::0.5")
+ }
+ assertThrows<AmountParserException> {
+ Amount.fromJSONString("EUR:.5")
+ }
+ }
+
+ @Test
+ fun testAddition() {
+ assertEquals(
+ Amount.fromJSONString("EUR:2"),
+ Amount.fromJSONString("EUR:1") + Amount.fromJSONString("EUR:1")
+ )
+ assertEquals(
+ Amount.fromJSONString("EUR:3"),
+ Amount.fromJSONString("EUR:1.5") + Amount.fromJSONString("EUR:1.5")
+ )
+ assertEquals(
+ Amount.fromJSONString("EUR:500000000.00000002"),
+ Amount.fromJSONString("EUR:500000000.00000001") + Amount.fromJSONString("EUR:0.00000001")
+ )
+ assertThrows<AmountOverflowException>("addition didn't overflow") {
+ Amount.fromJSONString("EUR:4503599627370496.99999999") + Amount.fromJSONString("EUR:0.00000001")
+ }
+ assertThrows<AmountOverflowException>("addition didn't overflow") {
+ Amount.fromJSONString("EUR:4000000000000000") + Amount.fromJSONString("EUR:4000000000000000")
+ }
+ }
+
+ @Test
+ fun testTimes() {
+ assertEquals(
+ Amount.fromJSONString("EUR:2"),
+ Amount.fromJSONString("EUR:2") * 1
+ )
+ assertEquals(
+ Amount.fromJSONString("EUR:2"),
+ Amount.fromJSONString("EUR:1") * 2
+ )
+ assertEquals(
+ Amount.fromJSONString("EUR:4.5"),
+ Amount.fromJSONString("EUR:1.5") * 3
+ )
+ assertEquals(Amount.fromJSONString("EUR:0"), Amount.fromJSONString("EUR:1.11") * 0)
+ assertEquals(Amount.fromJSONString("EUR:1.11"), Amount.fromJSONString("EUR:1.11") * 1)
+ assertEquals(Amount.fromJSONString("EUR:2.22"), Amount.fromJSONString("EUR:1.11") * 2)
+ assertEquals(Amount.fromJSONString("EUR:3.33"), Amount.fromJSONString("EUR:1.11") * 3)
+ assertEquals(Amount.fromJSONString("EUR:4.44"), Amount.fromJSONString("EUR:1.11") * 4)
+ assertEquals(Amount.fromJSONString("EUR:5.55"), Amount.fromJSONString("EUR:1.11") * 5)
+ assertEquals(
+ Amount.fromJSONString("EUR:1500000000.00000003"),
+ Amount.fromJSONString("EUR:500000000.00000001") * 3
+ )
+ assertThrows<AmountOverflowException>("times didn't overflow") {
+ Amount.fromJSONString("EUR:4000000000000000") * 2
+ }
+ }
+
+ @Test
+ fun testSubtraction() {
+ assertEquals(
+ Amount.fromJSONString("EUR:0"),
+ Amount.fromJSONString("EUR:1") - Amount.fromJSONString("EUR:1")
+ )
+ assertEquals(
+ Amount.fromJSONString("EUR:1.5"),
+ Amount.fromJSONString("EUR:3") - Amount.fromJSONString("EUR:1.5")
+ )
+ assertEquals(
+ Amount.fromJSONString("EUR:500000000.00000001"),
+ Amount.fromJSONString("EUR:500000000.00000002") - Amount.fromJSONString("EUR:0.00000001")
+ )
+ assertThrows<AmountOverflowException>("subtraction didn't underflow") {
+ Amount.fromJSONString("EUR:23.42") - Amount.fromJSONString("EUR:42.23")
+ }
+ assertThrows<AmountOverflowException>("subtraction didn't underflow") {
+ Amount.fromJSONString("EUR:0.5") - Amount.fromJSONString("EUR:0.50000001")
+ }
+ }
+
+ @Test
+ fun testIsZero() {
+ assertTrue(Amount.zero("EUR").isZero())
+ assertTrue(Amount.fromJSONString("EUR:0").isZero())
+ assertTrue(Amount.fromJSONString("EUR:0.0").isZero())
+ assertTrue(Amount.fromJSONString("EUR:0.00000").isZero())
+ assertTrue((Amount.fromJSONString("EUR:1.001") - Amount.fromJSONString("EUR:1.001")).isZero())
+
+ assertFalse(Amount.fromJSONString("EUR:0.00000001").isZero())
+ assertFalse(Amount.fromJSONString("EUR:1.0").isZero())
+ assertFalse(Amount.fromJSONString("EUR:0001.0").isZero())
+ }
+
+ @Test
+ fun testComparison() {
+ assertTrue(Amount.fromJSONString("EUR:0") <= Amount.fromJSONString("EUR:0"))
+ assertTrue(Amount.fromJSONString("EUR:0") <= Amount.fromJSONString("EUR:0.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:0") < Amount.fromJSONString("EUR:0.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:0") < Amount.fromJSONString("EUR:1"))
+ assertEquals(Amount.fromJSONString("EUR:0"), Amount.fromJSONString("EUR:0"))
+ assertEquals(Amount.fromJSONString("EUR:42"), Amount.fromJSONString("EUR:42"))
+ assertEquals(
+ Amount.fromJSONString("EUR:42.00000001"),
+ Amount.fromJSONString("EUR:42.00000001")
+ )
+ assertTrue(Amount.fromJSONString("EUR:42.00000001") >= Amount.fromJSONString("EUR:42.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:42.00000002") >= Amount.fromJSONString("EUR:42.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:42.00000002") > Amount.fromJSONString("EUR:42.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:0.00000002") > Amount.fromJSONString("EUR:0.00000001"))
+ assertTrue(Amount.fromJSONString("EUR:0.00000001") > Amount.fromJSONString("EUR:0"))
+ assertTrue(Amount.fromJSONString("EUR:2") > Amount.fromJSONString("EUR:1"))
+
+ assertThrows<IllegalStateException>("could compare amounts with different currencies") {
+ Amount.fromJSONString("EUR:0.5") < Amount.fromJSONString("USD:0.50000001")
+ }
+ }
+
+}
diff --git a/taler-kotlin-android/src/test/java/net/taler/common/ContractTermsTest.kt b/taler-kotlin-android/src/test/java/net/taler/common/ContractTermsTest.kt
index 3a2cdb4..3e1ebc4 100644
--- a/taler-kotlin-android/src/test/java/net/taler/common/ContractTermsTest.kt
+++ b/taler-kotlin-android/src/test/java/net/taler/common/ContractTermsTest.kt
@@ -18,7 +18,6 @@ package net.taler.common
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
-import net.taler.lib.common.Timestamp
import org.junit.Assert.assertEquals
import org.junit.Test
@@ -38,14 +37,14 @@ class ContractTermsTest {
},
"fulfillment_url":"https://shop.test.taler.net/essay/1._The_Free_Software_Definition",
"summary":"Essay: 1. The Free Software Definition",
- "refund_deadline":{"t_ms":"never"},
- "wire_transfer_deadline":{"t_ms":1596128564000},
+ "refund_deadline":{"t_s":"never"},
+ "wire_transfer_deadline":{"t_s":1596128564},
"products":[],
"h_wire":"KV40K023N8EC1F5100TYNS23C4XN68Y1Z3PTJSWFGTMCNYD54KT4S791V2VQ91SZANN86VDAA369M4VEZ0KR6DN71EVRRZA71K681M0",
"wire_method":"x-taler-bank",
"order_id":"2020.212-01M9VKEAPF76C",
- "timestamp":{"t_ms":1596128114000},
- "pay_deadline":{"t_ms":"never"},
+ "timestamp":{"t_s":1596128114},
+ "pay_deadline":{"t_s":"never"},
"max_wire_fee":"TESTKUDOS:1",
"max_fee":"TESTKUDOS:1",
"wire_fee_amortization":3,
diff --git a/taler-kotlin-android/src/test/java/net/taler/common/TalerUriTest.kt b/taler-kotlin-android/src/test/java/net/taler/common/TalerUriTest.kt
new file mode 100644
index 0000000..128f707
--- /dev/null
+++ b/taler-kotlin-android/src/test/java/net/taler/common/TalerUriTest.kt
@@ -0,0 +1,65 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import net.taler.common.TalerUri.parseWithdrawUri
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Test
+
+class TalerUriTest {
+
+ @Test
+ fun testParseWithdrawUri() {
+ // correct parsing
+ var uri = "taler://withdraw/bank.example.com/12345"
+ var expected = TalerUri.WithdrawUriResult("https://bank.example.com/", "12345")
+ assertEquals(expected, parseWithdrawUri(uri))
+
+ // correct parsing with insecure http
+ uri = "taler+http://withdraw/bank.example.org/foo"
+ expected = TalerUri.WithdrawUriResult("http://bank.example.org/", "foo")
+ assertEquals(expected, parseWithdrawUri(uri))
+
+ // correct parsing with long path
+ uri = "taler://withdraw/bank.example.com/foo/bar/23/42/1337/1234567890"
+ expected =
+ TalerUri.WithdrawUriResult("https://bank.example.com/foo/bar/23/42/1337", "1234567890")
+ assertEquals(expected, parseWithdrawUri(uri))
+
+ // rejects incorrect scheme
+ uri = "talerx://withdraw/bank.example.com/12345"
+ assertNull(parseWithdrawUri(uri))
+
+ // rejects incorrect authority
+ uri = "taler://withdrawx/bank.example.com/12345"
+ assertNull(parseWithdrawUri(uri))
+
+ // rejects incorrect authority with insecure http
+ uri = "taler+http://withdrawx/bank.example.com/12345"
+ assertNull(parseWithdrawUri(uri))
+
+ // rejects empty withdrawalId
+ uri = "taler://withdraw/bank.example.com//"
+ assertNull(parseWithdrawUri(uri))
+
+ // rejects empty path and withdrawalId
+ uri = "taler://withdraw/bank.example.com////"
+ assertNull(parseWithdrawUri(uri))
+ }
+
+}
diff --git a/taler-kotlin-android/src/test/java/net/taler/common/TestUtils.kt b/taler-kotlin-android/src/test/java/net/taler/common/TestUtils.kt
new file mode 100644
index 0000000..b0f191d
--- /dev/null
+++ b/taler-kotlin-android/src/test/java/net/taler/common/TestUtils.kt
@@ -0,0 +1,40 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import kotlin.random.Random
+import org.junit.Assert.assertTrue
+import org.junit.Assert.fail
+
+private val charPool: List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
+fun getRandomString(minLength: Int = 1, maxLength: Int = Random.nextInt(0, 1337)) =
+ (minLength..maxLength)
+ .map { Random.nextInt(0, charPool.size) }
+ .map(charPool::get)
+ .joinToString("")
+
+inline fun <reified T : Throwable> assertThrows(
+ msg: String? = null,
+ function: () -> Any
+) {
+ try {
+ function.invoke()
+ fail(msg)
+ } catch (e: Exception) {
+ assertTrue(e is T)
+ }
+}
diff --git a/taler-kotlin-android/src/test/java/net/taler/common/TimeTest.kt b/taler-kotlin-android/src/test/java/net/taler/common/TimeTest.kt
new file mode 100644
index 0000000..4049940
--- /dev/null
+++ b/taler-kotlin-android/src/test/java/net/taler/common/TimeTest.kt
@@ -0,0 +1,46 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+
+import kotlinx.serialization.json.Json.Default.decodeFromString
+import kotlinx.serialization.json.Json.Default.encodeToString
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import kotlin.random.Random
+
+// TODO test other functionality of Timestamp and Duration
+class TimeTest {
+
+ @Test
+ fun testSerialize() {
+ for (i in 0 until 42) {
+ val t = Random.nextLong()
+ assertEquals("""{"t_s":$t}""", encodeToString(Timestamp.serializer(), Timestamp(t)))
+ }
+ assertEquals("""{"t_s":"never"}""", encodeToString(Timestamp.serializer(), Timestamp.never()))
+ }
+
+ @Test
+ fun testDeserialize() {
+ for (i in 0 until 42) {
+ val t = Random.nextLong()
+ assertEquals(Timestamp(t), decodeFromString(Timestamp.serializer(), """{ "t_s": $t }"""))
+ }
+ assertEquals(Timestamp.never(), decodeFromString(Timestamp.serializer(), """{ "t_s": "never" }"""))
+ }
+
+}
diff --git a/taler-kotlin-android/src/test/java/net/taler/common/VersionTest.kt b/taler-kotlin-android/src/test/java/net/taler/common/VersionTest.kt
new file mode 100644
index 0000000..d8d7149
--- /dev/null
+++ b/taler-kotlin-android/src/test/java/net/taler/common/VersionTest.kt
@@ -0,0 +1,65 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2020 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+package net.taler.common
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertNull
+import org.junit.Test
+
+
+class VersionTest {
+
+ @Test
+ fun testParse() {
+ assertNull(Version.parse(""))
+ assertNull(Version.parse("foo"))
+ assertNull(Version.parse("foo:bar:foo"))
+ assertNull(Version.parse("0:0:0:"))
+ assertNull(Version.parse("0:0:"))
+ assertEquals(Version(0, 0, 0), Version.parse("0:0:0"))
+ assertEquals(Version(1, 2, 3), Version.parse("1:2:3"))
+ assertEquals(Version(1337, 42, 23), Version.parse("1337:42:23"))
+ }
+
+ @Test
+ fun testComparision() {
+ assertEquals(
+ Version.VersionMatchResult(true, 0),
+ Version.parse("0:0:0")!!.compare(Version.parse("0:0:0"))
+ )
+ assertEquals(
+ Version.VersionMatchResult(true, -1),
+ Version.parse("0:0:0")!!.compare(Version.parse("1:0:1"))
+ )
+ assertEquals(
+ Version.VersionMatchResult(true, -1),
+ Version.parse("0:0:0")!!.compare(Version.parse("1:5:1"))
+ )
+ assertEquals(
+ Version.VersionMatchResult(false, -1),
+ Version.parse("0:0:0")!!.compare(Version.parse("1:5:0"))
+ )
+ assertEquals(
+ Version.VersionMatchResult(false, 1),
+ Version.parse("1:0:0")!!.compare(Version.parse("0:5:0"))
+ )
+ assertEquals(
+ Version.VersionMatchResult(true, 0),
+ Version.parse("1:0:1")!!.compare(Version.parse("1:5:1"))
+ )
+ }
+
+}