/* * Copyright 2010-2020 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.* class StringNativeTest { @Test fun lowercase() { // Non-ASCII assertEquals("\u214E\uA7B5\u2CEF", "\u2132\uA7B4\u2CEF".lowercase()) // 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 assertEquals("\u0069\u0307", "\u0130".lowercase()) assertEquals("a\u0069\u0307z", "a\u0130Z".lowercase()) // Final_Sigma run { fun caseIgnorable(length: Int): String { return listOf( "\u0483", // COMBINING CYRILLIC TITLO; Mn "\u20DF", // COMBINING ENCLOSING DIAMOND; Me "\uD804\uDCBD", // 110BD; KAITHI NUMBER SIGN; Cf "\u2C7D", // MODIFIER LETTER CAPITAL V; Lm "\uD83C\uDFFD", // 1F3FD; EMOJI MODIFIER FITZPATRICK TYPE-4; Sk "\u003A", // COLON; Po; Word_Break=MidLetter "\uFF0E", // FULLWIDTH FULL STOP; Po; Word_Break=MidNumLet "\u0027" // APOSTROPHE; Po; Word_Break=Single_Quote ).shuffled().take(length).joinToString(separator = "") } fun cased(): String { return listOf( "\u0041", // LATIN CAPITAL LETTER A; Lu "\uD81B\uDE63", // 16E63; MEDEFAIDRIN SMALL LETTER W; Ll "\u01CB", // LATIN CAPITAL LETTER N WITH SMALL LETTER J; Lt "\u217A", // SMALL ROMAN NUMERAL ELEVEN; Nl; Other_Lowercase "\uD83C\uDD50" // 1F150; NEGATIVE CIRCLED LATIN CAPITAL LETTER A; So; Other_Uppercase ).random() } fun other(): String { return listOf( "\u0000", // ; Cc "\u0030", // DIGIT ZERO; Nd "\uD838\uDEC6" // 1E2C6; WANCHO LETTER YA; Lo ).random() } fun Char.hex(): String { return code.toString(16).padStart(4, '0') } val sigma = '\u03A3' val lowerSigma = '\u03C3' val specialLowerSigma = '\u03C2' // Build a string of the form: [cased][other](caseIgnorable*)(sigma)(caseIgnorable*)[other][cased] for (precedingCaseIgnorable in 0..5) { for (succeedingCaseIgnorable in 0..5) { val caseIgnorableBefore = caseIgnorable(precedingCaseIgnorable) val caseIgnorableAfter = caseIgnorable(succeedingCaseIgnorable) val sigmaNearby = caseIgnorableBefore + sigma + caseIgnorableAfter val lowerSigmaNearby = caseIgnorableBefore + lowerSigma + caseIgnorableAfter val specialSigmaNearby = caseIgnorableBefore + specialLowerSigma + caseIgnorableAfter for (mask in 0 until (1 shl 4)) { val casedBefore = cased().repeat((mask shr 0) and 1) val casedAfter = cased().repeat((mask shr 1) and 1) val otherBefore = other().repeat((mask shr 2) and 1) val otherAfter = other().repeat((mask shr 3) and 1) val resultSigmaNearby = if (otherBefore.isEmpty() && casedBefore.isNotEmpty() && (otherAfter.isNotEmpty() || casedAfter.isEmpty())) specialSigmaNearby else lowerSigmaNearby val actual = (casedBefore + otherBefore + sigmaNearby + otherAfter + casedAfter).lowercase() val expected = casedBefore.lowercase() + otherBefore + resultSigmaNearby + otherAfter + casedAfter.lowercase() assertEquals( expected, actual, "Expected <$expected>${expected.map { it.hex() }}, Actual <$actual>${actual.map { it.hex() }}" ) } } } } } @Test 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") } @Test fun subSequence() { assertEquals("ello", "Hello world".subSequence(1, 5).toString()) assertEquals("", "Hello world".subSequence(1, 1).toString()) } }