From 612876e44de35cdbd563ac2ce40dcd1d4e397bc5 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Tue, 18 Aug 2020 11:35:28 -0300 Subject: Include Taler common Kotlin library as a submodule --- taler-kotlin-common/.gitignore | 1 - taler-kotlin-common/.gitlab-ci.yml | 7 - taler-kotlin-common/build.gradle | 82 -------- .../commonMain/kotlin/net/taler/common/Amount.kt | 198 ----------------- .../src/commonMain/kotlin/net/taler/common/Time.kt | 106 ---------- .../commonMain/kotlin/net/taler/common/Version.kt | 70 ------ .../kotlin/net/taler/common/AmountTest.kt | 234 --------------------- .../kotlin/net/taler/common/TestUtils.kt | 26 --- .../commonTest/kotlin/net/taler/common/TimeTest.kt | 49 ----- .../kotlin/net/taler/common/VersionTest.kt | 65 ------ .../src/jsMain/kotlin/net/taler/common/Time.kt | 23 -- .../src/jvmMain/kotlin/net/taler/common/Time.kt | 21 -- .../src/nativeMain/kotlin/net/taler/common/Time.kt | 23 -- 13 files changed, 905 deletions(-) delete mode 100644 taler-kotlin-common/.gitignore delete mode 100644 taler-kotlin-common/.gitlab-ci.yml delete mode 100644 taler-kotlin-common/build.gradle delete mode 100644 taler-kotlin-common/src/commonMain/kotlin/net/taler/common/Amount.kt delete mode 100644 taler-kotlin-common/src/commonMain/kotlin/net/taler/common/Time.kt delete mode 100644 taler-kotlin-common/src/commonMain/kotlin/net/taler/common/Version.kt delete mode 100644 taler-kotlin-common/src/commonTest/kotlin/net/taler/common/AmountTest.kt delete mode 100644 taler-kotlin-common/src/commonTest/kotlin/net/taler/common/TestUtils.kt delete mode 100644 taler-kotlin-common/src/commonTest/kotlin/net/taler/common/TimeTest.kt delete mode 100644 taler-kotlin-common/src/commonTest/kotlin/net/taler/common/VersionTest.kt delete mode 100644 taler-kotlin-common/src/jsMain/kotlin/net/taler/common/Time.kt delete mode 100644 taler-kotlin-common/src/jvmMain/kotlin/net/taler/common/Time.kt delete mode 100644 taler-kotlin-common/src/nativeMain/kotlin/net/taler/common/Time.kt (limited to 'taler-kotlin-common') diff --git a/taler-kotlin-common/.gitignore b/taler-kotlin-common/.gitignore deleted file mode 100644 index 796b96d..0000000 --- a/taler-kotlin-common/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/taler-kotlin-common/.gitlab-ci.yml b/taler-kotlin-common/.gitlab-ci.yml deleted file mode 100644 index c241e31..0000000 --- a/taler-kotlin-common/.gitlab-ci.yml +++ /dev/null @@ -1,7 +0,0 @@ -taler_kotlin_common_test: - stage: test - only: - changes: - - taler-kotlin-common/**/* - - build.gradle - script: ./gradlew :taler-kotlin-common:jvmTest diff --git a/taler-kotlin-common/build.gradle b/taler-kotlin-common/build.gradle deleted file mode 100644 index 129881d..0000000 --- a/taler-kotlin-common/build.gradle +++ /dev/null @@ -1,82 +0,0 @@ -plugins { - id 'org.jetbrains.kotlin.multiplatform' - id 'kotlinx-serialization' -} - -group 'net.taler' -version '0.0.1' - -apply plugin: 'maven-publish' - -kotlin { - jvm() - // This is for iPhone simulator - // Switch here to iosArm64 (or iosArm32) to build library for iPhone device - iosX64("ios") { - binaries { - framework() - } - } - linuxX64("linux") - js { - browser { - } - nodejs { - } - } - sourceSets { - def serialization_version = "0.20.0" - commonMain { - dependencies { - implementation kotlin('stdlib-common') - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version" - } - } - commonTest { - dependencies { - implementation kotlin('test-common') - implementation kotlin('test-annotations-common') - } - } - jvmMain { - dependencies { - implementation kotlin('stdlib-jdk8') - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version" - } - } - jvmTest { - dependencies { - implementation kotlin('test') - implementation kotlin('test-junit') - } - } - jsMain { - dependencies { - implementation kotlin('stdlib-js') - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-js:$serialization_version" - } - } - jsTest { - dependencies { - implementation kotlin('test-js') - } - } - nativeMain { - dependsOn commonMain - dependencies { - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime-native:$serialization_version" - } - } - nativeTest { - dependsOn commonTest - } - configure([targets.linux, targets.ios]) { - compilations.main.source(sourceSets.nativeMain) - compilations.test.source(sourceSets.nativeTest) - } - } -} - -configurations { - compileClasspath -} diff --git a/taler-kotlin-common/src/commonMain/kotlin/net/taler/common/Amount.kt b/taler-kotlin-common/src/commonMain/kotlin/net/taler/common/Amount.kt deleted file mode 100644 index 84d10c5..0000000 --- a/taler-kotlin-common/src/commonMain/kotlin/net/taler/common/Amount.kt +++ /dev/null @@ -1,198 +0,0 @@ -/* - * 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 - */ - -package net.taler.common - -import kotlinx.serialization.Decoder -import kotlinx.serialization.Encoder -import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.Serializer -import kotlin.math.floor -import kotlin.math.pow -import kotlin.math.roundToInt - -class AmountParserException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause) -class AmountOverflowException(msg: String? = null, cause: Throwable? = null) : Exception(msg, cause) - -@Serializable(with = KotlinXAmountSerializer::class) -data class Amount( - /** - * name of the currency using either a three-character ISO 4217 currency code, - * or a regional currency identifier starting with a "*" followed by at most 10 characters. - * ISO 4217 exponents in the name are not supported, - * although the "fraction" is corresponds to an ISO 4217 exponent of 6. - */ - val currency: String, - - /** - * The integer part may be at most 2^52. - * Note that "1" here would correspond to 1 EUR or 1 USD, depending on currency, not 1 cent. - */ - val value: Long, - - /** - * Unsigned 32 bit fractional value to be added to value representing - * an additional currency fraction, in units of one hundred millionth (1e-8) - * of the base currency value. For example, a fraction - * of 50_000_000 would correspond to 50 cents. - */ - val fraction: Int -) : Comparable { - - companion object { - - private const val FRACTIONAL_BASE: Int = 100000000 // 1e8 - - private val REGEX_CURRENCY = Regex("""^[-_*A-Za-z0-9]{1,12}$""") - val MAX_VALUE = 2.0.pow(52).toLong() - private const val MAX_FRACTION_LENGTH = 8 - const val MAX_FRACTION = 99_999_999 - - fun zero(currency: String): Amount { - return Amount(checkCurrency(currency), 0, 0) - } - - fun fromJSONString(str: String): Amount { - val split = str.split(":") - if (split.size != 2) throw AmountParserException("Invalid Amount Format") - return fromString(split[0], split[1]) - } - - fun fromString(currency: String, str: String): Amount { - // value - val valueSplit = str.split(".") - val value = checkValue(valueSplit[0].toLongOrNull()) - // fraction - val fraction: Int = if (valueSplit.size > 1) { - val fractionStr = valueSplit[1] - if (fractionStr.length > MAX_FRACTION_LENGTH) - throw AmountParserException("Fraction $fractionStr too long") - val fraction = "0.$fractionStr".toDoubleOrNull() - ?.times(FRACTIONAL_BASE) - ?.roundToInt() - checkFraction(fraction) - } else 0 - return Amount(checkCurrency(currency), value, fraction) - } - - fun min(currency: String): Amount = Amount(currency, 0, 1) - fun max(currency: String): Amount = Amount(currency, MAX_VALUE, MAX_FRACTION) - - - internal fun checkCurrency(currency: String): String { - if (!REGEX_CURRENCY.matches(currency)) - throw AmountParserException("Invalid currency: $currency") - return currency - } - - internal fun checkValue(value: Long?): Long { - if (value == null || value > MAX_VALUE) - throw AmountParserException("Value $value greater than $MAX_VALUE") - return value - } - - internal fun checkFraction(fraction: Int?): Int { - if (fraction == null || fraction > MAX_FRACTION) - throw AmountParserException("Fraction $fraction greater than $MAX_FRACTION") - return fraction - } - - } - - val amountStr: String - get() = if (fraction == 0) "$value" else { - var f = fraction - var fractionStr = "" - while (f > 0) { - fractionStr += f / (FRACTIONAL_BASE / 10) - f = (f * 10) % FRACTIONAL_BASE - } - "$value.$fractionStr" - } - - operator fun plus(other: Amount): Amount { - check(currency == other.currency) { "Can only subtract from same currency" } - val resultValue = value + other.value + floor((fraction + other.fraction).toDouble() / FRACTIONAL_BASE).toLong() - if (resultValue > MAX_VALUE) - throw AmountOverflowException() - val resultFraction = (fraction + other.fraction) % FRACTIONAL_BASE - return Amount(currency, resultValue, resultFraction) - } - - operator fun times(factor: Int): Amount { - // TODO consider replacing with a faster implementation - if (factor == 0) return zero(currency) - var result = this - for (i in 1 until factor) result += this - return result - } - - operator fun minus(other: Amount): Amount { - check(currency == other.currency) { "Can only subtract from same currency" } - var resultValue = value - var resultFraction = fraction - if (resultFraction < other.fraction) { - if (resultValue < 1L) - throw AmountOverflowException() - resultValue-- - resultFraction += FRACTIONAL_BASE - } - check(resultFraction >= other.fraction) - resultFraction -= other.fraction - if (resultValue < other.value) - throw AmountOverflowException() - resultValue -= other.value - return Amount(currency, resultValue, resultFraction) - } - - fun isZero(): Boolean { - return value == 0L && fraction == 0 - } - - fun toJSONString(): String { - return "$currency:$amountStr" - } - - override fun toString(): String { - return "$amountStr $currency" - } - - override fun compareTo(other: Amount): Int { - check(currency == other.currency) { "Can only compare amounts with the same currency" } - when { - value == other.value -> { - if (fraction < other.fraction) return -1 - if (fraction > other.fraction) return 1 - return 0 - } - value < other.value -> return -1 - else -> return 1 - } - } - -} - -@Serializer(forClass = Amount::class) -object KotlinXAmountSerializer: KSerializer { - override fun serialize(encoder: Encoder, value: Amount) { - encoder.encodeString(value.toJSONString()) - } - - override fun deserialize(decoder: Decoder): Amount { - return Amount.fromJSONString(decoder.decodeString()) - } -} diff --git a/taler-kotlin-common/src/commonMain/kotlin/net/taler/common/Time.kt b/taler-kotlin-common/src/commonMain/kotlin/net/taler/common/Time.kt deleted file mode 100644 index 37b6606..0000000 --- a/taler-kotlin-common/src/commonMain/kotlin/net/taler/common/Time.kt +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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 - */ - -package net.taler.common - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.builtins.serializer -import kotlinx.serialization.json.JsonElement -import kotlinx.serialization.json.JsonPrimitive -import kotlinx.serialization.json.JsonTransformingSerializer -import kotlinx.serialization.json.contentOrNull -import kotlinx.serialization.json.longOrNull -import net.taler.common.Duration.Companion.FOREVER -import kotlin.math.max - -expect fun nowMillis(): Long - -@Serializable -data class Timestamp( - @SerialName("t_ms") - @Serializable(NeverSerializer::class) - val ms: Long -) : Comparable { - - companion object { - const val NEVER: Long = -1 - fun now(): Timestamp = Timestamp(nowMillis()) - } - - /** - * Returns a copy of this [Timestamp] rounded to seconds. - */ - fun truncateSeconds(): Timestamp { - if (ms == NEVER) return Timestamp(ms) - return Timestamp((ms / 1000L) * 1000L) - } - - operator fun minus(other: Timestamp): Duration = when { - ms == NEVER -> Duration(FOREVER) - other.ms == NEVER -> throw Error("Invalid argument for timestamp comparision") - ms < other.ms -> Duration(0) - else -> Duration(ms - other.ms) - } - - operator fun minus(other: Duration): Timestamp = when { - ms == NEVER -> this - other.ms == FOREVER -> Timestamp(0) - else -> Timestamp(max(0, ms - other.ms)) - } - - override fun compareTo(other: Timestamp): Int { - return if (ms == NEVER) { - if (other.ms == NEVER) 0 - else 1 - } else { - if (other.ms == NEVER) -1 - else ms.compareTo(other.ms) - } - } - -} - -@Serializable -data class Duration( - /** - * Duration in milliseconds. - */ - @SerialName("d_ms") - @Serializable(ForeverSerializer::class) - val ms: Long -) { - companion object { - const val FOREVER: Long = -1 - } -} - -abstract class MinusOneSerializer(private val keyword: String) : - JsonTransformingSerializer(Long.serializer(), keyword) { - - override fun readTransform(element: JsonElement): JsonElement { - return if (element.contentOrNull == keyword) return JsonPrimitive(-1) - else super.readTransform(element) - } - - override fun writeTransform(element: JsonElement): JsonElement { - return if (element.longOrNull == -1L) return JsonPrimitive(keyword) - else element - } -} - -object NeverSerializer : MinusOneSerializer("never") -object ForeverSerializer : MinusOneSerializer("forever") diff --git a/taler-kotlin-common/src/commonMain/kotlin/net/taler/common/Version.kt b/taler-kotlin-common/src/commonMain/kotlin/net/taler/common/Version.kt deleted file mode 100644 index 8774115..0000000 --- a/taler-kotlin-common/src/commonMain/kotlin/net/taler/common/Version.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 - */ - -package net.taler.common - -import kotlin.math.sign - -/** - * Semantic versioning, but libtool-style. - * See https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html - */ -data class Version( - val current: Int, - val revision: Int, - val age: Int -) { - companion object { - fun parse(v: String): Version? { - val elements = v.split(":") - if (elements.size != 3) return null - val (currentStr, revisionStr, ageStr) = elements - val current = currentStr.toIntOrNull() - val revision = revisionStr.toIntOrNull() - val age = ageStr.toIntOrNull() - if (current == null || revision == null || age == null) return null - return Version(current, revision, age) - } - } - - /** - * Compare two libtool-style versions. - * - * Returns a [VersionMatchResult] or null if the given version was null. - */ - fun compare(other: Version?): VersionMatchResult? { - if (other == null) return null - val compatible = current - age <= other.current && - current >= other.current - other.age - val currentCmp = sign((current - other.current).toDouble()).toInt() - return VersionMatchResult(compatible, currentCmp) - } - - /** - * Result of comparing two libtool versions. - */ - data class VersionMatchResult( - /** - * Is the first version compatible with the second? - */ - val compatible: Boolean, - /** - * Is the first version older (-1), newer (+1) or identical (0)? - */ - val currentCmp: Int - ) - -} diff --git a/taler-kotlin-common/src/commonTest/kotlin/net/taler/common/AmountTest.kt b/taler-kotlin-common/src/commonTest/kotlin/net/taler/common/AmountTest.kt deleted file mode 100644 index e184307..0000000 --- a/taler-kotlin-common/src/commonTest/kotlin/net/taler/common/AmountTest.kt +++ /dev/null @@ -1,234 +0,0 @@ -/* - * 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 - */ - -package net.taler.common - -import kotlin.random.Random -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue -import kotlin.test.fail - -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) - assertEquals("23.42 TESTKUDOS", amount.toString()) - - str = "EUR:500000000.00000001" - amount = Amount.fromJSONString(str) - assertEquals(str, amount.toJSONString()) - assertEquals("EUR", amount.currency) - assertEquals(500000000, amount.value) - assertEquals(1, amount.fraction) - assertEquals("500000000.00000001 EUR", amount.toString()) - - str = "EUR:1500000000.00000003" - amount = Amount.fromJSONString(str) - assertEquals(str, amount.toJSONString()) - assertEquals("EUR", amount.currency) - assertEquals(1500000000, amount.value) - assertEquals(3, amount.fraction) - assertEquals("1500000000.00000003 EUR", amount.toString()) - } - - @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) - assertEquals("$maxValue.99999999 TESTKUDOS123", amount.toString()) - - // longer currency not accepted - assertThrows("longer currency was accepted") { - Amount.fromJSONString("TESTKUDOS1234:$maxValue.99999999") - } - - // max value + 1 not accepted - assertThrows("max value + 1 was accepted") { - Amount.fromJSONString("TESTKUDOS123:${maxValue + 1}.99999999") - } - - // max fraction + 1 not accepted - assertThrows("max fraction + 1 was accepted") { - Amount.fromJSONString("TESTKUDOS123:$maxValue.999999990") - } - } - - @Test - fun testFromJSONStringRejections() { - assertThrows { - Amount.fromJSONString("TESTKUDOS:0,5") - } - assertThrows { - Amount.fromJSONString("+TESTKUDOS:0.5") - } - assertThrows { - Amount.fromJSONString("0.5") - } - assertThrows { - Amount.fromJSONString(":0.5") - } - assertThrows { - Amount.fromJSONString("EUR::0.5") - } - assertThrows { - 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("addition didn't overflow") { - Amount.fromJSONString("EUR:4503599627370496.99999999") + Amount.fromJSONString("EUR:0.00000001") - } - assertThrows("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("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("subtraction didn't underflow") { - Amount.fromJSONString("EUR:23.42") - Amount.fromJSONString("EUR:42.23") - } - assertThrows("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 testComparision() { - 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("could compare amounts with different currencies") { - Amount.fromJSONString("EUR:0.5") < Amount.fromJSONString("USD:0.50000001") - } - } - - private inline fun assertThrows( - msg: String? = null, - function: () -> Any - ) { - try { - function.invoke() - fail(msg) - } catch (e: Exception) { - assertTrue(e is T) - } - } - -} diff --git a/taler-kotlin-common/src/commonTest/kotlin/net/taler/common/TestUtils.kt b/taler-kotlin-common/src/commonTest/kotlin/net/taler/common/TestUtils.kt deleted file mode 100644 index e3a6c17..0000000 --- a/taler-kotlin-common/src/commonTest/kotlin/net/taler/common/TestUtils.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 - */ - -package net.taler.common - -import kotlin.random.Random - -private val charPool: List = ('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("") diff --git a/taler-kotlin-common/src/commonTest/kotlin/net/taler/common/TimeTest.kt b/taler-kotlin-common/src/commonTest/kotlin/net/taler/common/TimeTest.kt deleted file mode 100644 index 3ee0a99..0000000 --- a/taler-kotlin-common/src/commonTest/kotlin/net/taler/common/TimeTest.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 - */ - -package net.taler.common - -import kotlinx.serialization.UnstableDefault -import kotlinx.serialization.json.Json.Default.parse -import kotlinx.serialization.json.Json.Default.stringify -import net.taler.common.Timestamp.Companion.NEVER -import kotlin.random.Random -import kotlin.test.Test -import kotlin.test.assertEquals - -// TODO test other functionality of Timestamp and Duration -@UnstableDefault -class TimeTest { - - @Test - fun testSerialize() { - for (i in 0 until 42) { - val t = Random.nextLong() - assertEquals("""{"t_ms":$t}""", stringify(Timestamp.serializer(), Timestamp(t))) - } - assertEquals("""{"t_ms":"never"}""", stringify(Timestamp.serializer(), Timestamp(NEVER))) - } - - @Test - fun testDeserialize() { - for (i in 0 until 42) { - val t = Random.nextLong() - assertEquals(Timestamp(t), parse(Timestamp.serializer(), """{ "t_ms": $t }""")) - } - assertEquals(Timestamp(NEVER), parse(Timestamp.serializer(), """{ "t_ms": "never" }""")) - } - -} diff --git a/taler-kotlin-common/src/commonTest/kotlin/net/taler/common/VersionTest.kt b/taler-kotlin-common/src/commonTest/kotlin/net/taler/common/VersionTest.kt deleted file mode 100644 index f4f17ea..0000000 --- a/taler-kotlin-common/src/commonTest/kotlin/net/taler/common/VersionTest.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 - */ - -package net.taler.common - -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNull - -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")) - ) - } - -} diff --git a/taler-kotlin-common/src/jsMain/kotlin/net/taler/common/Time.kt b/taler-kotlin-common/src/jsMain/kotlin/net/taler/common/Time.kt deleted file mode 100644 index b114022..0000000 --- a/taler-kotlin-common/src/jsMain/kotlin/net/taler/common/Time.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - */ - -package net.taler.common - -import kotlin.js.Date - -actual fun nowMillis(): Long { - return Date().getMilliseconds().toLong() -} diff --git a/taler-kotlin-common/src/jvmMain/kotlin/net/taler/common/Time.kt b/taler-kotlin-common/src/jvmMain/kotlin/net/taler/common/Time.kt deleted file mode 100644 index 6cd9040..0000000 --- a/taler-kotlin-common/src/jvmMain/kotlin/net/taler/common/Time.kt +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 - */ - -package net.taler.common - -actual fun nowMillis(): Long { - return System.currentTimeMillis() -} diff --git a/taler-kotlin-common/src/nativeMain/kotlin/net/taler/common/Time.kt b/taler-kotlin-common/src/nativeMain/kotlin/net/taler/common/Time.kt deleted file mode 100644 index 8a4091a..0000000 --- a/taler-kotlin-common/src/nativeMain/kotlin/net/taler/common/Time.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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 - */ - -package net.taler.common - -import kotlin.system.getTimeMillis - -actual fun nowMillis(): Long { - return getTimeMillis() -} -- cgit v1.2.3