diff --git a/examples/folio/app/shared/src/commonMain/kotlin/app/folio/util/Format.kt b/examples/folio/app/shared/src/commonMain/kotlin/app/folio/util/Format.kt index d40c9d4..bb0cb29 100644 --- a/examples/folio/app/shared/src/commonMain/kotlin/app/folio/util/Format.kt +++ b/examples/folio/app/shared/src/commonMain/kotlin/app/folio/util/Format.kt @@ -54,9 +54,8 @@ fun parseCents(input: String): Long? { val fracPadded = (frac + "00").substring(0, 2) val wholeLong = whole.toLongOrNull() ?: return null val fracLong = fracPadded.toLongOrNull() ?: return null - val total = wholeLong * 100 + fracLong - if (total < 0) return null - return total + if (wholeLong > (Long.MAX_VALUE - fracLong) / 100) return null + return wholeLong * 100 + fracLong } fun signedAmount(t: Transaction): Long = if (t.type == TxnType.credit) t.amount else -t.amount diff --git a/examples/folio/app/shared/src/commonTest/kotlin/app/folio/util/ParseCentsTest.kt b/examples/folio/app/shared/src/commonTest/kotlin/app/folio/util/ParseCentsTest.kt new file mode 100644 index 0000000..1580a34 --- /dev/null +++ b/examples/folio/app/shared/src/commonTest/kotlin/app/folio/util/ParseCentsTest.kt @@ -0,0 +1,38 @@ +package app.folio.util + +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNull + +class ParseCentsTest { + @Test + fun parsesEverydayAmountsExactly() { + assertEquals(1L, parseCents("0.01")) + assertEquals(1234L, parseCents("12.34")) + assertEquals(1250L, parseCents("12.5")) + assertEquals(1200L, parseCents("12.0")) + assertEquals(100000L, parseCents("1000")) + assertEquals(123456L, parseCents("1,234.56")) + } + + @Test + fun rejectsEighteenDigitWholeThatWrapsToAPositiveLong() { + assertNull(parseCents("999999999999999999")) + } + + @Test + fun rejectsSeventeenDigitWholeThatWrapsToANegativeLong() { + assertNull(parseCents("99999999999999999")) + } + + @Test + fun rejectsNineteenDigitWholeThatNoLongerFitsALong() { + assertNull(parseCents("9999999999999999999")) + } + + @Test + fun acceptsTheLargestRepresentableAmountAndRejectsOneCentMore() { + assertEquals(Long.MAX_VALUE, parseCents("92233720368547758.07")) + assertNull(parseCents("92233720368547758.08")) + } +}