[K/N] Migrate runtime/text tests to new testing infra ^KT-61259

This commit is contained in:
Alexander Shabalin
2023-10-23 16:11:12 +02:00
committed by Space Team
parent e9983a947f
commit 17dc60aac9
22 changed files with 693 additions and 1240 deletions
@@ -63,10 +63,59 @@ class CharNativeTest {
assertEquals("\u0069\u0307", '\u0130'.lowercase())
}
@Test
fun titlecase() {
// titlecase = titlecaseChar = char != uppercaseChar
assertEquals('\u10F0'.titlecaseChar().toString(), '\u10F0'.titlecase())
assertEquals('\u10F0', '\u10F0'.titlecaseChar())
assertNotEquals('\u10F0', '\u10F0'.uppercaseChar())
}
@Test
fun testIsSupplementaryCodePoint() {
assertFalse(Char.isSupplementaryCodePoint(-1))
for (c in 0..0xFFFF) {
assertFalse(Char.isSupplementaryCodePoint(c.toInt()))
}
for (c in 0xFFFF + 1..0x10FFFF) {
assertTrue(Char.isSupplementaryCodePoint(c))
}
assertFalse(Char.isSupplementaryCodePoint(0x10FFFF + 1))
}
@Test
fun isSurrogatePair() {
assertFalse(Char.isSurrogatePair('\u0000', '\u0000'))
assertFalse(Char.isSurrogatePair('\u0000', '\uDC00'))
assertTrue( Char.isSurrogatePair('\uD800', '\uDC00'))
assertTrue( Char.isSurrogatePair('\uD800', '\uDFFF'))
assertTrue( Char.isSurrogatePair('\uDBFF', '\uDFFF'))
assertFalse(Char.isSurrogatePair('\uDBFF', '\uF000'))
}
@Test
fun toChars() {
assertContentEquals(Char.toChars(0x010000), charArrayOf('\uD800', '\uDC00'))
assertContentEquals(Char.toChars(0x010001), charArrayOf('\uD800', '\uDC01'))
assertContentEquals(Char.toChars(0x010401), charArrayOf('\uD801', '\uDC01'))
assertContentEquals(Char.toChars(0x10FFFF), charArrayOf('\uDBFF', '\uDFFF'))
assertFailsWith<IllegalArgumentException> { Char.toChars(Int.MAX_VALUE) }
}
@Test
fun toCodePoint() {
assertEquals(0x010000, Char.toCodePoint('\uD800', '\uDC00'))
assertEquals(0x010001, Char.toCodePoint('\uD800', '\uDC01'))
assertEquals(0x010401, Char.toCodePoint('\uD801', '\uDC01'))
assertEquals(0x10FFFF, Char.toCodePoint('\uDBFF', '\uDFFF'))
}
@Test
fun category() {
assertTrue('<' in CharCategory.MATH_SYMBOL)
assertTrue(';' in CharCategory.OTHER_PUNCTUATION)
assertTrue('_' in CharCategory.CONNECTOR_PUNCTUATION)
assertTrue('$' in CharCategory.CURRENCY_SYMBOL)
}
}
@@ -0,0 +1,218 @@
/*
* Copyright 2010-2023 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.text
import kotlin.test.*
// Native-specific part of stdlib/test/text/StringBuilderTest.kt
class StringBuilderNativeTest {
@Test
fun insertCharSequence() {
StringBuilder("my insert CharSequence test").let { sb ->
sb.insert(0, null as CharSequence?)
assertEquals("nullmy insert CharSequence test", sb.toString())
sb.insert(2, null as CharSequence?)
assertEquals("nunullllmy insert CharSequence test", sb.toString())
sb.insert(sb.length, null as CharSequence?)
assertEquals("nunullllmy insert CharSequence testnull", sb.toString())
sb.insert(2, "12" as CharSequence)
assertEquals("nu12nullllmy insert CharSequence testnull", sb.toString())
sb.insert(sb.length, "12" as CharSequence)
assertEquals("nu12nullllmy insert CharSequence testnull12", sb.toString())
}
}
@Test
fun insertString() {
StringBuilder("my insert String test").let { sb ->
sb.insertRange(0, "1234", 0, 0)
assertEquals("my insert String test", sb.toString())
sb.insertRange(0, "1234", 0, 1)
assertEquals("1my insert String test", sb.toString())
sb.insertRange(0, "1234", 1, 3)
assertEquals("231my insert String test", sb.toString())
sb.insertRange(2, "1234", 0, 0)
assertEquals("231my insert String test", sb.toString())
sb.insertRange(2, "1234", 0, 1)
assertEquals("2311my insert String test", sb.toString())
sb.insertRange(2, "1234", 1, 3)
assertEquals("232311my insert String test", sb.toString())
sb.insertRange(sb.length, "1234", 0, 0)
assertEquals("232311my insert String test", sb.toString())
sb.insertRange(sb.length, "1234", 0, 1)
assertEquals("232311my insert String test1", sb.toString())
sb.insertRange(sb.length, "1234", 1, 3)
assertEquals("232311my insert String test123", sb.toString())
assertFailsWith<IndexOutOfBoundsException> { sb.insert(-1, "_") }
assertFailsWith<IndexOutOfBoundsException> { sb.insert(sb.length + 1, "_") }
assertFails { sb.insertRange(0, "null", -1, 0) }
assertFails { sb.insertRange(0, "null", 0, 5) }
assertFails { sb.insertRange(0, "null", 2, 1) }
}
}
@Test
fun insertByte() {
StringBuilder().let { sb ->
sb.insert(0, 42.toByte())
assertEquals("42", sb.toString())
sb.insert(0, 13.toByte())
assertEquals("1342", sb.toString())
sb.insert(3, -1.toByte())
assertEquals("134-12", sb.toString())
assertFailsWith<IndexOutOfBoundsException> { sb.insert(-1, 42.toByte()) }
assertFailsWith<IndexOutOfBoundsException> { sb.insert(sb.length + 1, 42.toByte()) }
}
}
@Test
fun insertShort() {
StringBuilder().let { sb ->
sb.insert(0, 42.toShort())
assertEquals("42", sb.toString())
sb.insert(0, 13.toShort())
assertEquals("1342", sb.toString())
sb.insert(3, -1.toShort())
assertEquals("134-12", sb.toString())
assertFailsWith<IndexOutOfBoundsException> { sb.insert(-1, 42.toShort()) }
assertFailsWith<IndexOutOfBoundsException> { sb.insert(sb.length + 1, 42.toShort()) }
}
}
@Test
fun insertInt() {
StringBuilder().let { sb ->
sb.insert(0, 42.toInt())
assertEquals("42", sb.toString())
sb.insert(0, 13.toInt())
assertEquals("1342", sb.toString())
sb.insert(3, -1.toInt())
assertEquals("134-12", sb.toString())
assertFailsWith<IndexOutOfBoundsException> { sb.insert(-1, 42.toInt()) }
assertFailsWith<IndexOutOfBoundsException> { sb.insert(sb.length + 1, 42.toInt()) }
}
}
@Test
fun insertLong() {
StringBuilder().let { sb ->
sb.insert(0, 42.toLong())
assertEquals("42", sb.toString())
sb.insert(0, 13.toLong())
assertEquals("1342", sb.toString())
sb.insert(3, -1.toLong())
assertEquals("134-12", sb.toString())
assertFailsWith<IndexOutOfBoundsException> { sb.insert(-1, 42.toLong()) }
assertFailsWith<IndexOutOfBoundsException> { sb.insert(sb.length + 1, 42.toLong()) }
}
}
@Test
fun insertFloat() {
StringBuilder().let { sb ->
sb.insert(0, 42.2.toFloat())
assertEquals("42.2", sb.toString())
sb.insert(0, 13.1.toFloat())
assertEquals("13.142.2", sb.toString())
sb.insert(3, -1.toFloat())
assertEquals("13.-1.0142.2", sb.toString())
assertFailsWith<IndexOutOfBoundsException> { sb.insert(-1, 42.2.toFloat()) }
assertFailsWith<IndexOutOfBoundsException> { sb.insert(sb.length + 1, 42.2.toFloat()) }
}
}
@Test
fun insertDouble() {
StringBuilder().let { sb ->
sb.insert(0, 42.2.toDouble())
assertEquals("42.2", sb.toString())
sb.insert(0, 13.1.toDouble())
assertEquals("13.142.2", sb.toString())
sb.insert(3, -1.toDouble())
assertEquals("13.-1.0142.2", sb.toString())
assertFailsWith<IndexOutOfBoundsException> { sb.insert(-1, 42.2.toDouble()) }
assertFailsWith<IndexOutOfBoundsException> { sb.insert(sb.length + 1, 42.2.toDouble()) }
}
}
@Test
fun testReverse() {
val sb = StringBuilder("123456")
assertTrue(sb === sb.reverse())
assertEquals("654321", sb.toString())
sb.setLength(1)
assertEquals("6", sb.toString())
sb.setLength(0)
assertEquals("", sb.toString())
}
@Test
fun testDoubleReverse() {
fun assertReversed(original: String, reversed: String, reversedBack: String = original) {
assertEquals(reversed, StringBuilder(original).reverse().toString())
assertEquals(reversedBack, StringBuilder(reversed).reverse().toString())
}
assertReversed("a", "a")
assertReversed("ab", "ba")
assertReversed("abcdef", "fedcba")
assertReversed("abcdefg", "gfedcba")
assertReversed("\ud800\udc00", "\ud800\udc00")
assertReversed("\udc00\ud800", "\ud800\udc00", "\ud800\udc00")
assertReversed("a\ud800\udc00", "\ud800\udc00a")
assertReversed("ab\ud800\udc00", "\ud800\udc00ba")
assertReversed("abc\ud800\udc00", "\ud800\udc00cba")
assertReversed("\ud800\udc00\udc01\ud801\ud802\udc02", "\ud802\udc02\ud801\udc01\ud800\udc00", "\ud800\udc00\ud801\udc01\ud802\udc02")
assertReversed("\ud800\udc00\ud801\udc01\ud802\udc02", "\ud802\udc02\ud801\udc01\ud800\udc00")
assertReversed("\ud800\udc00\udc01\ud801a", "a\ud801\udc01\ud800\udc00", "\ud800\udc00\ud801\udc01a")
assertReversed("a\ud800\udc00\ud801\udc01", "\ud801\udc01\ud800\udc00a")
assertReversed("\ud800\udc00\udc01\ud801ab", "ba\ud801\udc01\ud800\udc00", "\ud800\udc00\ud801\udc01ab")
assertReversed("ab\ud800\udc00\ud801\udc01", "\ud801\udc01\ud800\udc00ba")
assertReversed("\ud800\udc00\ud801\udc01", "\ud801\udc01\ud800\udc00")
assertReversed("a\ud800\udc00z\ud801\udc01", "\ud801\udc01z\ud800\udc00a")
assertReversed("a\ud800\udc00bz\ud801\udc01", "\ud801\udc01zb\ud800\udc00a")
assertReversed("abc\ud802\udc02\ud801\udc01\ud800\udc00", "\ud800\udc00\ud801\udc01\ud802\udc02cba")
assertReversed("abcd\ud802\udc02\ud801\udc01\ud800\udc00", "\ud800\udc00\ud801\udc01\ud802\udc02dcba")
}
@Test
fun appendLong() {
val times = 100
val expected = (12345678L until (12345678L + times)).fold("") { res, idx -> res + idx }
val sb = StringBuilder()
repeat(times) { sb.append(12345678L + it) }
assertEquals(expected, sb.toString())
val cornerCase = listOf(0L, -1L, Long.MIN_VALUE, Long.MAX_VALUE)
val expectedCornerCase = cornerCase.fold("") { res, e -> res + e }
for (v in cornerCase) sb.append(v)
assertEquals(expected + expectedCornerCase, sb.toString())
}
@Test
fun appendNullCharSequence() {
val sb = StringBuilder()
sb.append(null as CharSequence?)
assertEquals("null", sb.toString())
}
@Test
fun appendLine() {
val sb = StringBuilder()
sb.appendLine("abc").appendLine(42).appendLine(0.1)
assertEquals("abc\n42\n0.1\n", sb.toString())
}
}
@@ -6,7 +6,216 @@
package test.text
import kotlin.reflect.KClass
import kotlin.test.*
import kotlinx.cinterop.toKString
import test.assertArrayContentEquals
internal actual val surrogateCodePointDecoding: String = "\uFFFD".repeat(3)
internal actual val surrogateCharEncoding: ByteArray = byteArrayOf(0xEF.toByte(), 0xBF.toByte(), 0xBD.toByte())
// Native-specific part of stdlib/test/text/StringEncodingTest.kt
class StringEncodingTestNative {
private fun bytes(vararg elements: Int) = ByteArray(elements.size) {
val v = elements[it]
require(v in Byte.MIN_VALUE..Byte.MAX_VALUE)
v.toByte()
}
private fun testEncoding(isWellFormed: Boolean, expected: ByteArray, string: String) {
assertArrayContentEquals(expected, string.encodeToByteArray())
if (!isWellFormed) {
assertFailsWith<CharacterCodingException> { string.encodeToByteArray(throwOnInvalidSequence = true) }
} else {
assertArrayContentEquals(expected, string.encodeToByteArray(throwOnInvalidSequence = true))
assertEquals(string, string.encodeToByteArray(throwOnInvalidSequence = true).decodeToString())
}
}
private fun testEncoding(isWellFormed: Boolean, expected: ByteArray, string: String, startIndex: Int, endIndex: Int) {
assertArrayContentEquals(expected, string.encodeToByteArray(startIndex, endIndex))
if (!isWellFormed) {
assertFailsWith<CharacterCodingException> { string.encodeToByteArray(startIndex, endIndex, true) }
} else {
assertArrayContentEquals(expected, string.encodeToByteArray(startIndex, endIndex, true))
string.encodeToByteArray(startIndex, endIndex, true).decodeToString()
}
}
@Test
fun encodeToByteArray() {
// Valid strings.
testEncoding(true, bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()), "Hello")
testEncoding(true, bytes(-48, -97, -47, -128, -48, -72, -48, -78, -48, -75, -47, -126), "Привет")
// Different kinds of input
testEncoding(false, bytes(-16, -112, -128, -128, '1'.toInt(), -17, -65, -67, -17, -65, -67), "\uD800\uDC001\uDC00\uD800")
// Lone surrogate
testEncoding(false, bytes(-17, -65, -67, '1'.toInt(), '2'.toInt()), "\uD80012", )
testEncoding(false, bytes(-17, -65, -67, '1'.toInt(), '2'.toInt()), "\uDC0012")
testEncoding(false, bytes('1'.toInt(), '2'.toInt(), -17, -65, -67), "12\uD800")
}
@Test
fun encodeToByteArraySlice() {
// Valid strings.
testEncoding(true, bytes(-16, -112, -128, -128, -16, -112, -128, -128), "\uD800\uDC00\uD800\uDC00\uD800\uDC00\uD800\uDC00", 0, 4)
testEncoding(true, bytes(-16, -112, -128, -128, -16, -112, -128, -128), "\uD800\uDC00\uD800\uDC00\uD800\uDC00\uD800\uDC00", 2, 6)
testEncoding(true, bytes(-16, -112, -128, -128, -16, -112, -128, -128), "\uD800\uDC00\uD800\uDC00\uD800\uDC00\uD800\uDC00", 4, 8)
// Illegal surrogate pair
testEncoding(false, bytes(-17, -65, -67, -17, -65, -67, '1'.toInt()), "\uDC00\uD80012", 0, 3)
testEncoding(false, bytes(-17, -65, -67, -17, -65, -67, '2'.toInt()), "1\uDC00\uD8002", 1, 4)
testEncoding(false, bytes('2'.toInt(), -17, -65, -67, -17, -65, -67), "12\uDC00\uD800", 1, 4)
// Lone surrogate
testEncoding(false, bytes('1'.toInt(), -17, -65, -67), "1\uD800\uDC002", 0, 2)
testEncoding(false, bytes(-17, -65, -67, '2'.toInt()), "1\uD800\uDC002", 2, 4)
}
private fun testDecoding(isWellFormed: Boolean, expected: String, bytes: ByteArray) {
assertEquals(expected, bytes.decodeToString())
if (!isWellFormed) {
assertFailsWith<CharacterCodingException> { bytes.decodeToString(throwOnInvalidSequence = true) }
} else {
assertEquals(expected, bytes.decodeToString(throwOnInvalidSequence = true))
assertArrayContentEquals(bytes, bytes.decodeToString(throwOnInvalidSequence = true).encodeToByteArray())
}
}
private fun testDecoding(isWellFormed: Boolean, expected: String, bytes: ByteArray, startIndex: Int, endIndex: Int) {
assertEquals(expected, bytes.decodeToString(startIndex, endIndex))
if (!isWellFormed) {
assertFailsWith<CharacterCodingException> { bytes.decodeToString(startIndex, endIndex, true) }
} else {
assertEquals(expected, bytes.decodeToString(startIndex, endIndex, true))
assertArrayContentEquals(
bytes.sliceArray(startIndex until endIndex),
bytes.decodeToString(startIndex, endIndex, true).encodeToByteArray()
)
}
}
@Test
fun decodeToString() {
// Valid strings.
testDecoding(true, "Hello", bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()))
testDecoding(true, "Привет", bytes(-48, -97, -47, -128, -48, -72, -48, -78, -48, -75, -47, -126))
testDecoding(true, "\uD800\uDC00", bytes(-16, -112, -128, -128))
// Incorrect UTF-8 lead character.
testDecoding(false, "\uFFFD1", bytes(-1, '1'.toInt()))
// Incomplete codepoint.
testDecoding(false, "\uFFFD1", bytes(-16, -97, -104, '1'.toInt()))
testDecoding(false, "\uFFFD1\uFFFD", bytes(-16, -97, -104, '1'.toInt(), -16, -97, -104))
}
@Test
fun decodeToStringSlice() {
// Valid strings.
testDecoding(true, "\uD800\uDC00\uD800\uDC00", bytes(-16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128), 0, 8)
testDecoding(true, "\uD800\uDC00\uD800\uDC00", bytes(-16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128), 4, 12)
testDecoding(true, "\uD800\uDC00\uD800\uDC00", bytes(-16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128), 8, 16)
// Incorrect UTF-8 lead character.
testDecoding(false, "\uFFFD1", bytes(-1, '1'.toInt(), '2'.toInt()), 0, 2)
testDecoding(false, "\uFFFD2", bytes('1'.toInt(), -1, '2'.toInt(), '3'.toInt()), 1, 3)
testDecoding(false, "2\uFFFD", bytes('1'.toInt(), '2'.toInt(), -1), 1, 3)
// Incomplete codepoint.
testDecoding(false, "\uFFFD1", bytes(-16, -97, -104, '1'.toInt(), '2'.toInt()), 0, 4)
testDecoding(false, "\uFFFD2", bytes('1'.toInt(), -16, -97, -104, '2'.toInt(), '3'.toInt()), 1, 5)
testDecoding(false, "2\uFFFD", bytes('1'.toInt(), '2'.toInt(), -16, -97, -104), 1, 5)
}
private fun testToKString(isWellFormed: Boolean, expected: String, bytes: ByteArray) {
assertEquals(expected, bytes.toKString())
assertEquals(expected, bytes.copyOf(bytes.size + 1).toKString())
if (!isWellFormed) {
assertFailsWith<CharacterCodingException> { bytes.toKString(throwOnInvalidSequence = true) }
assertFailsWith<CharacterCodingException> { bytes.copyOf(bytes.size + 1).toKString(throwOnInvalidSequence = true) }
} else {
assertEquals(expected, bytes.toKString(throwOnInvalidSequence = true))
assertEquals(expected, bytes.copyOf(bytes.size + 1).toKString(throwOnInvalidSequence = true))
}
}
private fun testToKString(isWellFormed: Boolean, expected: String, bytes: ByteArray, startIndex: Int, endIndex: Int) {
assertEquals(expected, bytes.toKString(startIndex, endIndex))
assertEquals(expected, bytes.copyOf(bytes.size + 1).toKString(startIndex, endIndex))
if (!isWellFormed) {
assertFailsWith<CharacterCodingException> { bytes.toKString(startIndex, endIndex, true) }
assertFailsWith<CharacterCodingException> { bytes.copyOf(bytes.size + 1).toKString(startIndex, endIndex, true) }
} else {
assertEquals(expected, bytes.toKString(startIndex, endIndex, true))
assertEquals(expected, bytes.copyOf(bytes.size + 1).toKString(startIndex, endIndex, true))
}
}
@Test
fun toKString() {
// Valid strings.
testToKString(true, "Hello", bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()))
testToKString(true, "Hell", bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 0, 'o'.toInt()))
testToKString(true, "Привет", bytes(-48, -97, -47, -128, -48, -72, -48, -78, -48, -75, -47, -126))
testToKString(true, "При", bytes(-48, -97, -47, -128, -48, -72, 0, -48, -78, 0, -48, -75, -47, -126))
testToKString(true, "\uD800\uDC00", bytes(-16, -112, -128, -128))
testToKString(true, "\uD800\uDC00", bytes(-16, -112, -128, -128, 0, -16, -112, -128, -128))
testToKString(true, "", bytes())
testToKString(true, "", bytes(0, 'H'.toInt()))
// Incorrect UTF-8 lead character.
testToKString(false, "\uFFFD1", bytes(-1, '1'.toInt()))
testToKString(false, "\uFFFD", bytes(-1, 0, '1'.toInt()))
// Incomplete codepoint.
testToKString(false, "\uFFFD1", bytes(-16, -97, -104, '1'.toInt()))
testToKString(false, "\uFFFD", bytes(-16, -97, -104, 0, '1'.toInt()))
testToKString(false, "\uFFFD1\uFFFD", bytes(-16, -97, -104, '1'.toInt(), -16, -97, -104))
testToKString(false, "\uFFFD1", bytes(-16, -97, -104, '1'.toInt(), 0, -16, -97, -104))
}
@Test
fun toKStringSlice() {
assertFailsWith<IndexOutOfBoundsException> { bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()).toKString(-1, 3) }
assertFailsWith<IndexOutOfBoundsException> { bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()).toKString(5, 15) }
assertFailsWith<IndexOutOfBoundsException> { bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()).toKString(2, 12) }
assertFailsWith<IndexOutOfBoundsException> { bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()).toKString(10, 10) }
assertFailsWith<IllegalArgumentException> { bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()).toKString(3, 1) }
assertFailsWith<IndexOutOfBoundsException> { bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0).toKString(-1, 3) }
assertFailsWith<IndexOutOfBoundsException> { bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0).toKString(8, 18) }
assertFailsWith<IndexOutOfBoundsException> { bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0).toKString(2, 12) }
assertFailsWith<IndexOutOfBoundsException> { bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0).toKString(10, 10) }
assertFailsWith<IllegalArgumentException> { bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0).toKString(3, 1) }
// Valid strings.
testToKString(true, "He", bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()), 0, 2)
testToKString(true, "ll", bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()), 2, 4)
testToKString(true, "lo", bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()), 3, 5)
testToKString(true, "", bytes('H'.toInt(), 'e'.toInt(), 'l'.toInt(), 'l'.toInt(), 'o'.toInt()), 0, 0)
testToKString(true, "\uD800\uDC00\uD800\uDC00", bytes(-16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128), 0, 8)
testToKString(true, "\uD800\uDC00\uD800\uDC00", bytes(-16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128), 4, 12)
testToKString(true, "\uD800\uDC00\uD800\uDC00", bytes(-16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128, -16, -112, -128, -128), 8, 16)
testToKString(true, "aaa", bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0), 0, 5)
testToKString(true, "a", bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0), 2, 4)
testToKString(true, "", bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0), 3, 5)
testToKString(true, "bb", bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0), 4, 6)
testToKString(true, "bbb", bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0), 4, 7)
testToKString(true, "bbb", bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0), 4, 8)
testToKString(true, "bb", bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0), 5, 8)
testToKString(true, "b", bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0), 6, 8)
testToKString(true, "", bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0), 7, 8)
testToKString(true, "", bytes('a'.toInt(), 'a'.toInt(), 'a'.toInt(), 0, 'b'.toInt(), 'b'.toInt(), 'b'.toInt(), 0), 8, 8)
// Incorrect UTF-8 lead character.
testToKString(false, "\uFFFD1", bytes(-1, '1'.toInt(), '2'.toInt()), 0, 2)
testToKString(false, "\uFFFD2", bytes('1'.toInt(), -1, '2'.toInt(), '3'.toInt()), 1, 3)
testToKString(false, "2\uFFFD", bytes('1'.toInt(), '2'.toInt(), -1), 1, 3)
// Incomplete codepoint.
testToKString(false, "\uFFFD1", bytes(-16, -97, -104, '1'.toInt(), '2'.toInt()), 0, 4)
testToKString(false, "\uFFFD2", bytes('1'.toInt(), -16, -97, -104, '2'.toInt(), '3'.toInt()), 1, 5)
testToKString(false, "2\uFFFD", bytes('1'.toInt(), '2'.toInt(), -16, -97, -104), 1, 5)
}
}
@@ -16,6 +16,8 @@ class StringNativeTest {
// Surrogate pairs
assertEquals("\uD801\uDC4F\uD806\uDCD0\uD81B\uDE7F", "\uD801\uDC27\uD806\uDCB0\uD81B\uDE5F".lowercase())
assertEquals("\ud801\udc28", "\ud801\udc28".lowercase())
assertEquals("\ud801\udc28", "\ud801\udc00".lowercase())
// Special Casing
// LATIN CAPITAL LETTER I WITH DOT ABOVE
@@ -102,5 +104,51 @@ class StringNativeTest {
fun uppercase() {
// Non-ASCII
assertEquals("\u00DE\u03A9\u0403\uA779", "\u00FE\u03A9\u0453\uA77A".uppercase())
// Surrogate pairs
assertEquals("\ud801\udc00", "\ud801\udc28".uppercase())
assertEquals("\ud801\udc00", "\ud801\udc00".uppercase())
}
@Test
fun capitalize() {
// Non-ASCII
assertEquals("\u00DE\u03A9\u0453\uA77A", "\u00FE\u03A9\u0453\uA77A".capitalize())
}
@Test fun indexOfString() {
assertEquals(1, "bceded".indexOf("ced", -1))
assertEquals(-1, "bceded".indexOf("e", 7))
assertEquals(-1, "bceded".indexOf("e", Int.MAX_VALUE))
assertEquals(6, "bceded".indexOf("", Int.MAX_VALUE))
assertEquals(-1, "".indexOf("a", -3))
assertEquals(0, "".indexOf("", 0))
}
@Test
fun indexOfChar() {
assertEquals(-1, "bcedef".indexOf('e', 5))
assertEquals(-1, "".indexOf('a', -3))
assertEquals(-1, "".indexOf('a', 10))
assertEquals(-1, "".indexOf(0.toChar(), -3))
assertEquals(-1, "".indexOf(0.toChar(), 10))
}
@Test
fun equalsIgnoreCase() {
assertTrue("hello".equals("HElLo", true))
assertTrue("Привет".equals("прИВет", true))
}
@Test
fun trim() {
assertEquals(expected = "String", actual = "\u0020 \u202FString\u2028\u2029".trim(),
message = "Trim special whitespaces")
assertEquals(expected = "\u1FFFString", actual = "\u00A0 \u1FFFString".trim(),
message = "Trim special whitespace but should left a unicode symbol")
}
}
@@ -0,0 +1,130 @@
/*
* Copyright 2010-2023 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.text
import kotlin.test.*
// Native-specific part of stdlib/test/text/StringNumberConversionTest.kt
class StringNumberConversionNativeTest {
@Test
fun toDouble() {
assertEquals(0.5, "0.5".toDouble())
assertEquals(-5000000000.0, "-00000000000000000000.5e10".toDouble())
assertEquals(-0.005, "-00000000000000000000.5e-2".toDouble())
assertEquals(50000000000.0, "+5e10".toDouble())
assertEquals(50000000000.0, " +5e10 ".toDouble())
assertEquals(520.0, "+5.2e2d".toDouble())
assertEquals(0.052, "+5.2e-2d".toDouble())
assertEquals(52340000000.0, "+5.234e+10d".toDouble())
assertEquals(5.234E123, "+5.234e+123d".toDouble())
assertEquals(5.234E123, "+5.234e+123f".toDouble())
assertEquals(5.234E123, "+5.234e+123".toDouble())
assertEquals(5.5, "5.5f".toDouble())
assertEquals(2.71, "\u0009 \u000A 2.71 \u000D".toDouble())
assertEquals(42.3, "\n 42.3 ".toDouble())
assertFailsWith<NumberFormatException> {
"+-5.0".toDouble()
}
assertFailsWith<NumberFormatException> {
"d".toDouble()
}
assertFailsWith<NumberFormatException> {
"5.5.3e123d".toDouble()
}
// regression of incorrect processing of long lines - such values returned Infinity
assertFailsWith<NumberFormatException> {
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".toDouble()
}
assertFailsWith<NumberFormatException> {
"+-my free text with different letters $3213#. e ".toDouble()
}
assertFailsWith<NumberFormatException> {
"eeeeeEEEEEeeeeeee".toDouble()
}
assertFailsWith<NumberFormatException> {
"InfinityN".toDouble()
}
assertFailsWith<NumberFormatException> {
"NaNPICEZy".toDouble()
}
assertFailsWith<NumberFormatException> { "\u20293.14".toDouble() }
assertFailsWith<NumberFormatException> { "3.14\u200B".toDouble() }
assertFailsWith<NumberFormatException> { "3.14\u200B ABC".toDouble() }
// Illegal surrogate pair
assertFailsWith<NumberFormatException> { "\uDC00\uD800".toDouble() }
// Different kinds of input (including illegal one)
assertFailsWith<NumberFormatException> { "\uD800\uDC001\uDC00\uD800".toDouble() }
// Lone surrogate
assertFailsWith<NumberFormatException> { "\uD80012".toDouble() }
assertFailsWith<NumberFormatException> { "\uDC0012".toDouble() }
assertFailsWith<NumberFormatException> { "12\uD800".toDouble() }
}
@Test
fun toFloat() {
assertEquals(0.5f, "0.5".toFloat())
assertEquals(-5000000000f, "-00000000000000000000.5e10f".toFloat())
assertEquals(-0.005f, "-00000000000000000000.5e-2f".toFloat())
assertEquals(50000000000f, "+5e10".toFloat())
assertEquals(50000000000f, " +5e10 ".toFloat())
assertEquals(0.052f, "+5.2e-2f".toFloat())
assertEquals(520f, "+5.2e2f".toFloat())
assertEquals(0.052f, "+5.2e-2f".toFloat())
assertEquals(52340000000f, "+5.234e+10f".toFloat())
assertEquals(Float.POSITIVE_INFINITY, "+5.234e+123f".toFloat())
assertEquals(7.15f, "\u0019 7.15 ".toFloat())
assertEquals(2.71f, "\u0009 \u000A 2.71 \u000D".toFloat())
assertFailsWith<NumberFormatException> {
"+-5.0f".toFloat()
}
assertFailsWith<NumberFormatException> {
"f".toFloat()
}
assertFailsWith<NumberFormatException> {
"5.5.3e123f".toFloat()
}
// regression of incorrect processing of long lines - such values returned Infinity
assertFailsWith<NumberFormatException> {
// should be more than 38 symbols
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".toFloat()
}
assertFailsWith<NumberFormatException> {
// should be more than 38 symbols
"this string is not a numb3r, am I right?????????????".toFloat()
}
assertFailsWith<NumberFormatException> {
// should be more than 38 symbols
"+-my free text with different letters $3213#. e ".toFloat()
}
assertFailsWith<NumberFormatException> {
// should be more than 38 symbols
"eeeeeEEEEEeeeeeee".toFloat()
}
assertFailsWith<NumberFormatException> {
"InfinityN".toFloat()
}
assertFailsWith<NumberFormatException> {
"NaNPICEZy".toFloat()
}
assertFailsWith<NumberFormatException> { "\u202F3.14".toFloat() }
// Illegal surrogate pair
assertFailsWith<NumberFormatException> { "\uDC00\uD800".toFloat() }
// Different kinds of input (including illegal one)
assertFailsWith<NumberFormatException> { "\uD800\uDC001\uDC00\uD800".toFloat() }
// Lone surrogate
assertFailsWith<NumberFormatException> { "\uD80012".toFloat() }
assertFailsWith<NumberFormatException> { "\uDC0012".toFloat() }
assertFailsWith<NumberFormatException> { "12\uD800".toFloat() }
}
}