blob: 37f9d4cbc3503917fa52b9e23c71401492cd499f [file]
/*
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package test.time
import kotlin.test.*
import kotlin.time.*
class DurationParserTest {
@Test
fun testLongParserBasicParsing() {
val parser = LongParser.default
// Test basic positive numbers
var result = parser.parse("123", 0) { endIndex, sign, hasOverflow ->
assertEquals(3, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(123L, result)
// Test with leading zeros
result = parser.parse("000456", 0) { endIndex, sign, hasOverflow ->
assertEquals(6, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(456L, result)
// Test zero
result = parser.parse("0", 0) { endIndex, sign, hasOverflow ->
assertEquals(1, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(0L, result)
// Test multiple zeros
result = parser.parse("0000", 0) { endIndex, sign, hasOverflow ->
assertEquals(4, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(0L, result)
}
@Test
fun testLongParserWithSign() {
val parser = LongParser.iso
// Test positive sign
var result = parser.parse("+123", 0) { endIndex, sign, hasOverflow ->
assertEquals(4, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(123L, result)
// Test negative sign
result = parser.parse("-456", 0) { endIndex, sign, hasOverflow ->
assertEquals(4, endIndex)
assertEquals(-1, sign)
assertFalse(hasOverflow)
}
assertEquals(456L, result)
// Test negative zero
result = parser.parse("-0", 0) { endIndex, sign, hasOverflow ->
assertEquals(2, endIndex)
assertEquals(-1, sign)
assertFalse(hasOverflow)
}
assertEquals(0L, result)
}
@Test
fun testLongParserPartialParsing() {
val parser = LongParser.default
// Test parsing stops at non-digit
var result = parser.parse("123abc", 0) { endIndex, sign, hasOverflow ->
assertEquals(3, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(123L, result)
// Test parsing with a decimal point
result = parser.parse("456.789", 0) { endIndex, sign, hasOverflow ->
assertEquals(3, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(456L, result)
// Test parsing with space
result = parser.parse("789 123", 0) { endIndex, sign, hasOverflow ->
assertEquals(3, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(789L, result)
}
@Test
fun testLongParserOverflow() {
val parser = LongParser.default
// Test maximum value without overflow
var result = parser.parse("9223372036854775807", 0) { endIndex, sign, hasOverflow ->
assertEquals(19, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(Long.MAX_VALUE, result)
// Test overflow detection
result = parser.parse("9223372036854775808", 0) { endIndex, sign, hasOverflow ->
assertEquals(19, endIndex)
assertEquals(1, sign)
assertTrue(hasOverflow)
}
assertEquals(Long.MAX_VALUE, result)
// Test significant overflow
result = parser.parse("99999999999999999999", 0) { endIndex, sign, hasOverflow ->
assertEquals(20, endIndex)
assertEquals(1, sign)
assertTrue(hasOverflow)
}
assertEquals(Long.MAX_VALUE, result)
// Test negative overflow with iso parser (supports signs)
val isoParser = LongParser.iso
result = isoParser.parse("-${MAX_MILLIS + 1}", 0) { endIndex, sign, hasOverflow ->
assertEquals(20, endIndex)
assertEquals(-1, sign)
assertTrue(hasOverflow)
}
assertEquals(MAX_MILLIS, result)
}
@Test
fun testLongParserStartIndex() {
val parser = LongParser.default
// Test parsing from a middle of string
var result = parser.parse("prefix123suffix", 6) { endIndex, sign, hasOverflow ->
assertEquals(9, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(123L, result)
// Test with sign from the middle (using iso parser)
val isoParser = LongParser.iso
result = isoParser.parse("text-456end", 4) { endIndex, sign, hasOverflow ->
assertEquals(8, endIndex)
assertEquals(-1, sign)
assertFalse(hasOverflow)
}
assertEquals(456L, result)
}
@Test
fun testLongParserEdgeCases() {
val parser = LongParser.iso
// Test empty number after sign
var result = parser.parse("+", 0) { endIndex, sign, hasOverflow ->
assertEquals(1, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(0L, result)
// Test single digit with the default parser
val defaultParser = LongParser.default
result = defaultParser.parse("5", 0) { endIndex, sign, hasOverflow ->
assertEquals(1, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(5L, result)
// Test leading zeros with significant digits
result = defaultParser.parse("000000000000000000001", 0) { endIndex, sign, hasOverflow ->
assertEquals(21, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(1L, result)
// Test multiple consecutive signs - these should stop at the first invalid character
result = parser.parse("+-123", 0) { endIndex, sign, hasOverflow ->
assertEquals(1, endIndex) // Stops after '+' since '-' is not a digit
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(0L, result)
result = parser.parse("++123", 0) { endIndex, sign, hasOverflow ->
assertEquals(1, endIndex) // Stops after the first '+' since the second '+' is not a digit
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(0L, result)
result = parser.parse("--123", 0) { endIndex, sign, hasOverflow ->
assertEquals(1, endIndex) // Stops after the first '-' since the second '-' is not a digit
assertEquals(-1, sign)
assertFalse(hasOverflow)
}
assertEquals(0L, result)
// Test parsing from index 1 with multiple signs
result = parser.parse("+-123", 1) { endIndex, sign, hasOverflow ->
assertEquals(5, endIndex)
assertEquals(-1, sign)
assertFalse(hasOverflow)
}
assertEquals(123L, result)
result = parser.parse("++123", 1) { endIndex, sign, hasOverflow ->
assertEquals(5, endIndex)
assertEquals(1, sign)
assertFalse(hasOverflow)
}
assertEquals(123L, result)
result = parser.parse("--123", 1) { endIndex, sign, hasOverflow ->
assertEquals(5, endIndex)
assertEquals(-1, sign)
assertFalse(hasOverflow)
}
assertEquals(123L, result)
}
@Test
fun testFractionalParserBasicParsing() {
// Test single-digit fraction
var result = FractionalParser.parse("5", 0) { endIndex ->
assertEquals(1, endIndex)
}
assertEquals(500_000_000_000_000L, result)
// Test two-digit fraction
result = FractionalParser.parse("25", 0) { endIndex ->
assertEquals(2, endIndex)
}
assertEquals(250_000_000_000_000L, result)
// Test three-digit fraction
result = FractionalParser.parse("125", 0) { endIndex ->
assertEquals(3, endIndex)
}
assertEquals(125_000_000_000_000L, result)
}
@Test
fun testFractionalParserFullPrecision() {
// Test exactly 15 digits
var result = FractionalParser.parse("123456789012345", 0) { endIndex ->
assertEquals(15, endIndex)
}
assertEquals(123456789012345L, result)
// Test 9 digits (boundary between high and low precision)
result = FractionalParser.parse("123456789", 0) { endIndex ->
assertEquals(9, endIndex)
}
assertEquals(123456789000000L, result)
// Test 10 digits (crosses boundary)
result = FractionalParser.parse("1234567891", 0) { endIndex ->
assertEquals(10, endIndex)
}
assertEquals(123456789100000L, result)
}
@Test
fun testFractionalParserOverflow() {
// Test more than 15 digits (should skip excess)
val result = FractionalParser.parse("1234567890123456789", 0) { endIndex ->
assertEquals(19, endIndex)
}
assertEquals(123456789012345L, result)
}
@Test
fun testFractionalParserPartialParsing() {
// Test parsing stops at non-digit
var result = FractionalParser.parse("123abc", 0) { endIndex ->
assertEquals(3, endIndex)
}
assertEquals(123_000_000_000_000L, result)
// Test parsing with unit suffix
result = FractionalParser.parse("5s", 0) { endIndex ->
assertEquals(1, endIndex)
}
assertEquals(500_000_000_000_000L, result)
// Test parsing with space
result = FractionalParser.parse("789 123", 0) { endIndex ->
assertEquals(3, endIndex)
}
assertEquals(789_000_000_000_000L, result)
}
@Test
fun testFractionalParserStartIndex() {
// Test parsing from a middle of string
var result = FractionalParser.parse("prefix123suffix", 6) { endIndex ->
assertEquals(9, endIndex)
}
assertEquals(123_000_000_000_000L, result)
result = FractionalParser.parse("1.5s", 2) { endIndex ->
assertEquals(3, endIndex)
}
assertEquals(500_000_000_000_000L, result)
}
@Test
fun testFractionalParserLeadingZeros() {
// Test fraction with leading zeros
var result = FractionalParser.parse("005", 0) { endIndex ->
assertEquals(3, endIndex)
}
assertEquals(5_000_000_000_000L, result)
// Test all zeros
result = FractionalParser.parse("000000000000000", 0) { endIndex ->
assertEquals(15, endIndex)
}
assertEquals(0L, result)
}
@Test
fun testFractionalParserEdgeCases() {
// Test empty string case (would need to handle in real code)
var result = FractionalParser.parse("s", 0) { endIndex ->
assertEquals(0, endIndex)
}
assertEquals(0L, result)
// Test very small fraction
result = FractionalParser.parse("000000000000001", 0) { endIndex ->
assertEquals(15, endIndex)
}
assertEquals(1L, result)
// Test maximum precision value
result = FractionalParser.parse("999999999999999", 0) { endIndex ->
assertEquals(15, endIndex)
}
assertEquals(999999999999999L, result)
}
}