| /* |
| * Copyright 2010-2017 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package test.text |
| |
| import kotlin.test.* |
| import test.* |
| import test.collections.behaviors.iteratorBehavior |
| import test.collections.compare |
| |
| |
| fun createString(content: String): CharSequence = content |
| fun createStringBuilder(content: String): CharSequence = StringBuilder((content as Any).toString()) // required for Rhino JS |
| |
| |
| val charSequenceBuilders = listOf(::createString, ::createStringBuilder) |
| |
| fun withOneCharSequenceArg(f: ((String) -> CharSequence) -> Unit) { |
| for (arg1Builder in charSequenceBuilders) f(arg1Builder) |
| } |
| |
| fun withOneCharSequenceArg(arg1: String, f: (CharSequence) -> Unit) |
| = withOneCharSequenceArg { arg1Builder -> f(arg1Builder(arg1)) } |
| |
| fun withTwoCharSequenceArgs(f: ((String) -> CharSequence, (String) -> CharSequence) -> Unit) { |
| for (arg1Builder in charSequenceBuilders) |
| for (arg2Builder in charSequenceBuilders) |
| f(arg1Builder, arg2Builder) |
| } |
| |
| fun assertContentEquals(expected: String, actual: CharSequence, message: String? = null) { |
| assertEquals(expected, actual.toString(), message) |
| } |
| |
| // helper predicates available on both platforms |
| fun Char.isAsciiDigit() = this in '0'..'9' |
| fun Char.isAsciiLetter() = this in 'A'..'Z' || this in 'a'..'z' |
| fun Char.isAsciiUpperCase() = this in 'A'..'Z' |
| |
| class StringTest { |
| |
| @Test fun isEmptyAndBlank() = withOneCharSequenceArg { arg1 -> |
| class Case(val value: String?, val isNull: Boolean = false, val isEmpty: Boolean = false, val isBlank: Boolean = false) |
| |
| val cases = listOf( |
| Case(null, isNull = true), |
| Case("", isEmpty = true, isBlank = true), |
| Case(" \r\n\t\u00A0", isBlank = true), |
| Case(" Some ") |
| ) |
| |
| for (case in cases) { |
| val value = case.value?.let { arg1(it) } |
| assertEquals(case.isNull || case.isEmpty, value.isNullOrEmpty(), "failed for case '$value'") |
| assertEquals(case.isNull || case.isBlank, value.isNullOrBlank(), "failed for case '$value'") |
| if (value != null) |
| { |
| assertEquals(case.isEmpty, value.isEmpty(), "failed for case '$value'") |
| assertEquals(case.isBlank, value.isBlank(), "failed for case '$value'") |
| } |
| } |
| } |
| |
| @Test fun orEmpty() { |
| val s: String? = "hey" |
| val ns: String? = null |
| |
| assertEquals("hey", s.orEmpty()) |
| assertEquals("", ns.orEmpty()) |
| } |
| |
| @Test fun startsWithString() { |
| assertTrue("abcd".startsWith("ab")) |
| assertTrue("abcd".startsWith("abcd")) |
| assertTrue("abcd".startsWith("a")) |
| assertFalse("abcd".startsWith("abcde")) |
| assertFalse("abcd".startsWith("b")) |
| assertFalse("".startsWith("a")) |
| assertTrue("some".startsWith("")) |
| assertTrue("".startsWith("")) |
| |
| assertFalse("abcd".startsWith("aB", ignoreCase = false)) |
| assertTrue("abcd".startsWith("aB", ignoreCase = true)) |
| } |
| |
| @Test fun startsWithStringForCharSequence() = withTwoCharSequenceArgs { arg1, arg2 -> |
| fun String.startsWithCs(prefix: String, ignoreCase: Boolean = false): Boolean = |
| arg1(this).startsWith(arg2(prefix), ignoreCase) |
| |
| assertTrue("abcd".startsWithCs("ab")) |
| assertTrue("abcd".startsWithCs("abcd")) |
| assertTrue("abcd".startsWithCs("a")) |
| assertFalse("abcd".startsWithCs("abcde")) |
| assertFalse("abcd".startsWithCs("b")) |
| assertFalse("".startsWithCs("a")) |
| assertTrue("some".startsWithCs("")) |
| assertTrue("".startsWithCs("")) |
| |
| assertFalse("abcd".startsWithCs("aB", ignoreCase = false)) |
| assertTrue("abcd".startsWithCs("aB", ignoreCase = true)) |
| } |
| |
| @Test fun endsWithString() { |
| assertTrue("abcd".endsWith("d")) |
| assertTrue("abcd".endsWith("abcd")) |
| assertFalse("abcd".endsWith("b")) |
| assertFalse("strö".endsWith("RÖ", ignoreCase = false)) |
| assertTrue("strö".endsWith("RÖ", ignoreCase = true)) |
| assertFalse("".endsWith("a")) |
| assertTrue("some".endsWith("")) |
| assertTrue("".endsWith("")) |
| } |
| |
| @Test fun endsWithStringForCharSequence() = withTwoCharSequenceArgs { arg1, arg2 -> |
| fun String.endsWithCs(suffix: String, ignoreCase: Boolean = false): Boolean = |
| arg1(this).endsWith(arg2(suffix), ignoreCase) |
| |
| assertTrue("abcd".endsWithCs("d")) |
| assertTrue("abcd".endsWithCs("abcd")) |
| assertFalse("abcd".endsWithCs("b")) |
| assertFalse("strö".endsWithCs("RÖ", ignoreCase = false)) |
| assertTrue("strö".endsWithCs("RÖ", ignoreCase = true)) |
| assertFalse("".endsWithCs("a")) |
| assertTrue("some".endsWithCs("")) |
| assertTrue("".endsWithCs("")) |
| } |
| |
| @Test fun startsWithChar() = withOneCharSequenceArg { arg1 -> |
| fun String.startsWith(char: Char, ignoreCase: Boolean = false): Boolean = |
| arg1(this).startsWith(char, ignoreCase) |
| |
| assertTrue("abcd".startsWith('a')) |
| assertFalse("abcd".startsWith('b')) |
| assertFalse("abcd".startsWith('A', ignoreCase = false)) |
| assertTrue("abcd".startsWith('A', ignoreCase = true)) |
| assertFalse("".startsWith('a')) |
| } |
| |
| @Test fun endsWithChar() = withOneCharSequenceArg { arg1 -> |
| fun String.endsWith(char: Char, ignoreCase: Boolean = false): Boolean = |
| arg1(this).endsWith(char, ignoreCase) |
| |
| assertTrue("abcd".endsWith('d')) |
| assertFalse("abcd".endsWith('b')) |
| assertFalse("strö".endsWith('Ö', ignoreCase = false)) |
| assertTrue("strö".endsWith('Ö', ignoreCase = true)) |
| assertFalse("".endsWith('a')) |
| } |
| |
| @Test fun commonPrefix() = withTwoCharSequenceArgs { arg1, arg2 -> |
| fun String.commonPrefixWith(other: String, ignoreCase: Boolean = false): String = |
| arg1(this).commonPrefixWith(arg2(other), ignoreCase) |
| |
| assertEquals("", "".commonPrefixWith("")) |
| assertEquals("", "any".commonPrefixWith("")) |
| assertEquals("", "".commonPrefixWith("any")) |
| assertEquals("", "some".commonPrefixWith("any")) |
| |
| assertEquals("an", "annual".commonPrefixWith("any")) |
| assertEquals("an", "annual".commonPrefixWith("Any", ignoreCase = true)) |
| assertEquals("", "annual".commonPrefixWith("Any", ignoreCase = false)) |
| // surrogate pairs |
| val dth54 = "\uD83C\uDC58" // domino tile horizontal 5-4 |
| val dth55 = "\uD83C\uDC59" // domino tile horizontal 5-5 |
| assertEquals("", dth54.commonPrefixWith(dth55)) |
| assertEquals(dth54, "$dth54$dth54".commonPrefixWith("$dth54$dth55")) |
| } |
| |
| @Test fun commonSuffix() = withTwoCharSequenceArgs { arg1, arg2 -> |
| fun String.commonSuffixWith(other: String, ignoreCase: Boolean = false): String = |
| arg1(this).commonSuffixWith(arg2(other), ignoreCase) |
| |
| assertEquals("", "".commonSuffixWith("")) |
| assertEquals("", "any".commonSuffixWith("")) |
| assertEquals("", "".commonSuffixWith("any")) |
| assertEquals("", "some".commonSuffixWith("any")) |
| |
| assertEquals("ly", "yearly".commonSuffixWith("monthly")) |
| assertEquals("strö", "strö".commonSuffixWith("BISTRÖ", ignoreCase = true)) |
| assertEquals("", "yearly".commonSuffixWith("HARDLY", ignoreCase = false)) |
| // surrogate pairs |
| val dth54 = "\uD83C\uDC58" // domino tile horizontal 5-4 |
| val kimono = "\uD83D\uDC58" // kimono |
| assertEquals("", dth54.commonSuffixWith(kimono)) |
| assertEquals("$dth54", "d$dth54".commonSuffixWith("s$dth54")) |
| } |
| |
| @Test fun capitalize() { |
| assertEquals("A", "A".capitalize()) |
| assertEquals("A", "a".capitalize()) |
| assertEquals("Abcd", "abcd".capitalize()) |
| assertEquals("Abcd", "Abcd".capitalize()) |
| } |
| |
| @Test fun decapitalize() { |
| assertEquals("a", "A".decapitalize()) |
| assertEquals("a", "a".decapitalize()) |
| assertEquals("abcd", "abcd".decapitalize()) |
| assertEquals("abcd", "Abcd".decapitalize()) |
| assertEquals("uRL", "URL".decapitalize()) |
| } |
| |
| @Test fun slice() { |
| val iter = listOf(4, 3, 0, 1) |
| // abcde |
| // 01234 |
| assertEquals("bcd", "abcde".substring(1..3)) |
| assertEquals("dcb", "abcde".slice(3 downTo 1)) |
| assertEquals("edab", "abcde".slice(iter)) |
| } |
| |
| @Test fun sliceCharSequence() = withOneCharSequenceArg { arg1 -> |
| val iter = listOf(4, 3, 0, 1) |
| |
| val data = arg1("ABCDabcd") |
| // ABCDabcd |
| // 01234567 |
| assertEquals("BCDabc", data.slice(1..6).toString()) |
| assertEquals("baD", data.slice(5 downTo 3).toString()) |
| assertEquals("aDAB", data.slice(iter).toString()) |
| } |
| |
| @Test fun reverse() { |
| assertEquals("dcba", "abcd".reversed()) |
| assertEquals("4321", "1234".reversed()) |
| assertEquals("", "".reversed()) |
| } |
| |
| @Test fun reverseCharSequence() = withOneCharSequenceArg { arg1 -> |
| fun String.reversedCs(): CharSequence = arg1(this).reversed() |
| |
| assertContentEquals("dcba", "abcd".reversedCs()) |
| assertContentEquals("4321", "1234".reversedCs()) |
| assertContentEquals("", "".reversedCs()) |
| } |
| |
| @Test fun indices() = withOneCharSequenceArg { arg1 -> |
| fun String.indices(): IntRange = arg1(this).indices |
| |
| assertEquals(0..4, "abcde".indices()) |
| assertEquals(0..0, "a".indices()) |
| assertTrue("".indices().isEmpty()) |
| } |
| |
| @Test fun replaceRange() = withTwoCharSequenceArgs { arg1, arg2 -> |
| val s = arg1("sample text") |
| val replacement = arg2("??") |
| |
| assertContentEquals("sa??e text", s.replaceRange(2, 5, replacement)) |
| assertContentEquals("sa?? text", s.replaceRange(2..5, replacement)) |
| assertFails { |
| s.replaceRange(5..2, replacement) |
| } |
| assertFails { |
| s.replaceRange(5, 2, replacement) |
| } |
| |
| // symmetry with indices |
| assertContentEquals(replacement.toString(), s.replaceRange(s.indices, replacement)) |
| } |
| |
| @Test fun removeRange() = withOneCharSequenceArg("sample text") { s -> |
| assertContentEquals("sae text", s.removeRange(2, 5)) |
| assertContentEquals("sa text", s.removeRange(2..5)) |
| |
| assertContentEquals(s.toString(), s.removeRange(2,2)) |
| |
| // symmetry with indices |
| assertContentEquals("", s.removeRange(s.indices)) |
| |
| // symmetry with replaceRange |
| assertContentEquals(s.toString().replaceRange(2, 5, ""), s.removeRange(2, 5)) |
| assertContentEquals(s.toString().replaceRange(2..5, ""), s.removeRange(2..5)) |
| } |
| |
| @Test fun substringDelimited() { |
| val s = "-1,22,3+" |
| // chars |
| assertEquals("22,3+", s.substringAfter(',')) |
| assertEquals("3+", s.substringAfterLast(',')) |
| assertEquals("-1", s.substringBefore(',')) |
| assertEquals("-1,22", s.substringBeforeLast(',')) |
| |
| // strings |
| assertEquals("22,3+", s.substringAfter(",")) |
| assertEquals("3+", s.substringAfterLast(",")) |
| assertEquals("-1", s.substringBefore(",")) |
| assertEquals("-1,22", s.substringBeforeLast(",")) |
| |
| // non-existing delimiter |
| assertEquals("", s.substringAfter("+")) |
| assertEquals("", s.substringBefore("-")) |
| assertEquals(s, s.substringBefore("=")) |
| assertEquals(s, s.substringAfter("=")) |
| assertEquals("xxx", s.substringBefore("=", "xxx")) |
| assertEquals("xxx", s.substringAfter("=", "xxx")) |
| |
| } |
| |
| @Test fun replaceDelimited() { |
| val s = "/user/folder/file.extension" |
| // chars |
| assertEquals("/user/folder/file.doc", s.replaceAfter('.', "doc")) |
| assertEquals("/user/folder/another.doc", s.replaceAfterLast('/', "another.doc")) |
| assertEquals("new name.extension", s.replaceBefore('.', "new name")) |
| assertEquals("/new/path/file.extension", s.replaceBeforeLast('/', "/new/path")) |
| |
| // strings |
| assertEquals("/user/folder/file.doc", s.replaceAfter(".", "doc")) |
| assertEquals("/user/folder/another.doc", s.replaceAfterLast("/", "another.doc")) |
| assertEquals("new name.extension", s.replaceBefore(".", "new name")) |
| assertEquals("/new/path/file.extension", s.replaceBeforeLast("/", "/new/path")) |
| |
| // non-existing delimiter |
| assertEquals("/user/folder/file.extension", s.replaceAfter("=", "doc")) |
| assertEquals("/user/folder/file.extension", s.replaceAfterLast("=", "another.doc")) |
| assertEquals("/user/folder/file.extension", s.replaceBefore("=", "new name")) |
| assertEquals("/user/folder/file.extension", s.replaceBeforeLast("=", "/new/path")) |
| assertEquals("xxx", s.replaceBefore("=", "new name", "xxx")) |
| assertEquals("xxx", s.replaceBeforeLast("=", "/new/path", "xxx")) |
| } |
| |
| @Test fun repeat() = withOneCharSequenceArg { arg1 -> |
| fun String.repeat(n: Int): String = arg1(this).repeat(n) |
| |
| assertFails { "foo".repeat(-1) } |
| assertEquals("", "foo".repeat(0)) |
| assertEquals("foo", "foo".repeat(1)) |
| assertEquals("foofoo", "foo".repeat(2)) |
| assertEquals("foofoofoo", "foo".repeat(3)) |
| |
| assertEquals("", "".repeat(Int.MAX_VALUE)) |
| assertEquals("aaaaaaaaaaaaa", "a".repeat(13)) |
| } |
| |
| @Test fun stringIterator() = withOneCharSequenceArg("239") { data -> |
| var sum = 0 |
| for(c in data) |
| sum += (c - '0') |
| assertTrue(sum == 14) |
| } |
| |
| @Test fun trimStart() = withOneCharSequenceArg { arg1 -> |
| fun String.trimStartCS(): CharSequence = arg1(this).trimStart() |
| assertContentEquals("", "".trimStartCS()) |
| assertContentEquals("a", "a".trimStartCS()) |
| assertContentEquals("a", " a".trimStartCS()) |
| assertContentEquals("a", " a".trimStartCS()) |
| assertContentEquals("a ", " a ".trimStartCS()) |
| assertContentEquals("a b", " a b".trimStartCS()) |
| assertContentEquals("a b ", " a b ".trimStartCS()) |
| assertContentEquals("a", " \u00A0 a".trimStartCS()) |
| |
| assertContentEquals("a", "\ta".trimStartCS()) |
| assertContentEquals("a", "\t\ta".trimStartCS()) |
| assertContentEquals("a", "\ra".trimStartCS()) |
| assertContentEquals("a", "\na".trimStartCS()) |
| |
| assertContentEquals("a=", arg1("-=-=a=").trimStart('-','=')) |
| assertContentEquals("123a", arg1("ab123a").trimStart { !it.isAsciiDigit() }) |
| } |
| |
| @Test fun trimEnd() = withOneCharSequenceArg { arg1 -> |
| fun String.trimEndCS(): CharSequence = arg1(this).trimEnd() |
| assertContentEquals("", "".trimEndCS()) |
| assertContentEquals("a", "a".trimEndCS()) |
| assertContentEquals("a", "a ".trimEndCS()) |
| assertContentEquals("a", "a ".trimEndCS()) |
| assertContentEquals(" a", " a ".trimEndCS()) |
| assertContentEquals("a b", "a b ".trimEndCS()) |
| assertContentEquals(" a b", " a b ".trimEndCS()) |
| assertContentEquals("a", "a \u00A0 ".trimEndCS()) |
| |
| assertContentEquals("a", "a\t".trimEndCS()) |
| assertContentEquals("a", "a\t\t".trimEndCS()) |
| assertContentEquals("a", "a\r".trimEndCS()) |
| assertContentEquals("a", "a\n".trimEndCS()) |
| |
| assertContentEquals("=a", arg1("=a=-=-").trimEnd('-','=')) |
| assertContentEquals("ab123", arg1("ab123a").trimEnd { !it.isAsciiDigit() }) |
| } |
| |
| @Test fun trimStartAndEnd() = withOneCharSequenceArg { arg1 -> |
| val examples = arrayOf("a", |
| " a ", |
| " a ", |
| " a b ", |
| "\ta\tb\t", |
| "\t\ta\t\t", |
| "\ra\r", |
| "\na\n", |
| " \u00A0 a \u00A0 " |
| ) |
| |
| for ((source, example) in examples.map { it to arg1(it) }) { |
| assertContentEquals(source.trimEnd().trimStart(), example.trim()) |
| assertContentEquals(source.trimStart().trimEnd(), example.trim()) |
| } |
| |
| val examplesForPredicate = arrayOf("123", |
| "-=123=-" |
| ) |
| |
| val trimChars = charArrayOf('-', '=') |
| val trimPredicate = { it: Char -> !it.isAsciiDigit() } |
| for ((source, example) in examplesForPredicate.map { it to arg1(it) }) { |
| assertContentEquals(source.trimStart(*trimChars).trimEnd(*trimChars), example.trim(*trimChars)) |
| assertContentEquals(source.trimStart(trimPredicate).trimEnd(trimPredicate), example.trim(trimPredicate)) |
| } |
| } |
| |
| @Test fun padStart() = withOneCharSequenceArg { arg1 -> |
| val s = arg1("s") |
| assertContentEquals("s", s.padStart(0)) |
| assertContentEquals("s", s.padStart(1)) |
| assertContentEquals("--s", s.padStart(3, '-')) |
| assertContentEquals(" ", arg1("").padStart(2)) |
| assertFails { |
| s.padStart(-1) |
| } |
| } |
| |
| @Test fun padEnd() = withOneCharSequenceArg { arg1 -> |
| val s = arg1("s") |
| assertContentEquals("s", s.padEnd(0)) |
| assertContentEquals("s", s.padEnd(1)) |
| assertContentEquals("s--", s.padEnd(3, '-')) |
| assertContentEquals(" ", arg1("").padEnd(2)) |
| assertFails { |
| s.padEnd(-1) |
| } |
| } |
| |
| @Test fun removePrefix() = withOneCharSequenceArg("pre") { prefix -> |
| assertEquals("fix", "prefix".removePrefix(prefix), "Removes prefix") |
| assertEquals("prefix", "preprefix".removePrefix(prefix), "Removes prefix once") |
| assertEquals("sample", "sample".removePrefix(prefix)) |
| assertEquals("sample", "sample".removePrefix("")) |
| } |
| |
| @Test fun removeSuffix() = withOneCharSequenceArg("fix") { suffix -> |
| assertEquals("suf", "suffix".removeSuffix(suffix), "Removes suffix") |
| assertEquals("suffix", "suffixfix".removeSuffix(suffix), "Removes suffix once") |
| assertEquals("sample", "sample".removeSuffix(suffix)) |
| assertEquals("sample", "sample".removeSuffix("")) |
| } |
| |
| @Test fun removeSurrounding() = withOneCharSequenceArg { arg1 -> |
| val pre = arg1("<") |
| val post = arg1(">") |
| assertEquals("value", "<value>".removeSurrounding(pre, post)) |
| assertEquals("<value>", "<<value>>".removeSurrounding(pre, post), "Removes surrounding once") |
| assertEquals("<value", "<value".removeSurrounding(pre, post), "Only removes surrounding when both prefix and suffix present") |
| assertEquals("value>", "value>".removeSurrounding(pre, post), "Only removes surrounding when both prefix and suffix present") |
| assertEquals("value", "value".removeSurrounding(pre, post)) |
| |
| assertEquals("<->", "<->".removeSurrounding(arg1("<-"), arg1("->")), "Does not remove overlapping prefix and suffix") |
| } |
| |
| @Test fun removePrefixCharSequence() = withTwoCharSequenceArgs { arg1, arg2 -> |
| fun String.removePrefix(prefix: String) = arg1(this).removePrefix(arg2(prefix)) |
| val prefix = "pre" |
| |
| assertContentEquals("fix", "prefix".removePrefix(prefix), "Removes prefix") |
| assertContentEquals("prefix", "preprefix".removePrefix(prefix), "Removes prefix once") |
| assertContentEquals("sample", "sample".removePrefix(prefix)) |
| assertContentEquals("sample", "sample".removePrefix("")) |
| } |
| |
| @Test fun removeSuffixCharSequence() = withTwoCharSequenceArgs { arg1, arg2 -> |
| fun String.removeSuffix(suffix: String) = arg1(this).removeSuffix(arg2(suffix)) |
| val suffix = "fix" |
| |
| assertContentEquals("suf", "suffix".removeSuffix(suffix), "Removes suffix") |
| assertContentEquals("suffix", "suffixfix".removeSuffix(suffix), "Removes suffix once") |
| assertContentEquals("sample", "sample".removeSuffix(suffix)) |
| assertContentEquals("sample", "sample".removeSuffix("")) |
| } |
| |
| @Test fun removeSurroundingCharSequence() = withTwoCharSequenceArgs { arg1, arg2 -> |
| fun String.removeSurrounding(prefix: String, postfix: String) = arg1(this).removeSurrounding(arg2(prefix), arg2(postfix)) |
| |
| assertContentEquals("value", "<value>".removeSurrounding("<", ">")) |
| assertContentEquals("<value>", "<<value>>".removeSurrounding("<", ">"), "Removes surrounding once") |
| assertContentEquals("<value", "<value".removeSurrounding("<", ">"), "Only removes surrounding when both prefix and suffix present") |
| assertContentEquals("value>", "value>".removeSurrounding("<", ">"), "Only removes surrounding when both prefix and suffix present") |
| assertContentEquals("value", "value".removeSurrounding("<", ">")) |
| |
| assertContentEquals("<->", "<->".removeSurrounding("<-", "->"), "Does not remove overlapping prefix and suffix") |
| } |
| |
| /* |
| // unit test commented out until rangesDelimitiedBy would become public |
| |
| test fun rangesDelimitedBy() { |
| assertEquals(listOf(0..2, 4..3, 5..7), "abc--def".rangesDelimitedBy('-').toList()) |
| assertEquals(listOf(0..2, 5..7, 9..10), "abc--def-xy".rangesDelimitedBy("--", "-").toList()) |
| assertEquals(listOf(0..2, 7..9, 14..16), "123<br>456<BR>789".rangesDelimitedBy("<br>", ignoreCase = true).toList()) |
| assertEquals(listOf(2..2, 4..6), "a=b=c=d".rangesDelimitedBy("=", startIndex = 2, limit = 2).toList()) |
| |
| val s = "sample" |
| assertEquals(listOf(s.indices), s.rangesDelimitedBy("-").toList()) |
| assertEquals(listOf(s.indices), s.rangesDelimitedBy("-", startIndex = -1).toList()) |
| assertTrue(s.rangesDelimitedBy("-", startIndex = s.length).single().isEmpty()) |
| } |
| */ |
| |
| |
| @Test fun split() = withOneCharSequenceArg { arg1 -> |
| operator fun String.unaryPlus(): CharSequence = arg1(this) |
| |
| assertEquals(listOf(""), (+"").split(";")) |
| assertEquals(listOf("test"), (+"test").split(*charArrayOf()), "empty list of delimiters, none matched -> entire string returned") |
| assertEquals(listOf("test"), (+"test").split(*arrayOf<String>()), "empty list of delimiters, none matched -> entire string returned") |
| |
| assertEquals(listOf("abc", "def", "123;456"), (+"abc;def,123;456").split(';', ',', limit = 3)) |
| assertEquals(listOf("abc", "def", "123", "456"), (+"abc<BR>def<br>123<bR>456").split("<BR>", ignoreCase = true)) |
| |
| assertEquals(listOf("abc", "def", "123", "456"), (+"abc=-def==123=456").split("==", "=-", "=")) |
| |
| assertEquals(listOf("", "a", "b", "c", ""), (+"abc").split("")) |
| assertEquals(listOf("", "a", "b", "b", "a", ""), (+"abba").split("", "a")) |
| assertEquals(listOf("", "", "b", "b", "", ""), (+"abba").split("a", "")) |
| } |
| |
| @Test fun splitToLines() = withOneCharSequenceArg { arg1 -> |
| val string = arg1("first line\rsecond line\nthird line\r\nlast line") |
| assertEquals(listOf("first line", "second line", "third line", "last line"), string.lines()) |
| |
| |
| val singleLine = arg1("single line") |
| assertEquals(listOf(singleLine.toString()), singleLine.lines()) |
| } |
| |
| |
| @Test fun indexOfAnyChar() = withOneCharSequenceArg("abracadabra") { string -> |
| val chars = charArrayOf('d', 'b') |
| assertEquals(1, string.indexOfAny(chars)) |
| assertEquals(6, string.indexOfAny(chars, startIndex = 2)) |
| assertEquals(-1, string.indexOfAny(chars, startIndex = 9)) |
| |
| assertEquals(8, string.lastIndexOfAny(chars)) |
| assertEquals(6, string.lastIndexOfAny(chars, startIndex = 7)) |
| assertEquals(-1, string.lastIndexOfAny(chars, startIndex = 0)) |
| |
| assertEquals(-1, string.indexOfAny(charArrayOf())) |
| } |
| |
| @Test fun indexOfAnyCharIgnoreCase() = withOneCharSequenceArg("abraCadabra") { string -> |
| val chars = charArrayOf('B', 'c') |
| assertEquals(1, string.indexOfAny(chars, ignoreCase = true)) |
| assertEquals(4, string.indexOfAny(chars, startIndex = 2, ignoreCase = true)) |
| assertEquals(-1, string.indexOfAny(chars, startIndex = 9, ignoreCase = true)) |
| |
| assertEquals(8, string.lastIndexOfAny(chars, ignoreCase = true)) |
| assertEquals(4, string.lastIndexOfAny(chars, startIndex = 7, ignoreCase = true)) |
| assertEquals(-1, string.lastIndexOfAny(chars, startIndex = 0, ignoreCase = true)) |
| } |
| |
| @Test fun indexOfAnyString() = withOneCharSequenceArg("abracadabra") { string -> |
| val substrings = listOf("rac", "ra") |
| assertEquals(2, string.indexOfAny(substrings)) |
| assertEquals(9, string.indexOfAny(substrings, startIndex = 3)) |
| assertEquals(2, string.indexOfAny(substrings.reversed())) |
| assertEquals(-1, string.indexOfAny(substrings, 10)) |
| |
| assertEquals(9, string.lastIndexOfAny(substrings)) |
| assertEquals(2, string.lastIndexOfAny(substrings, startIndex = 8)) |
| assertEquals(2, string.lastIndexOfAny(substrings.reversed(), startIndex = 8)) |
| assertEquals(-1, string.lastIndexOfAny(substrings, 1)) |
| |
| assertEquals(0, string.indexOfAny(listOf("dab", "")), "empty strings are not ignored") |
| assertEquals(-1, string.indexOfAny(listOf())) |
| } |
| |
| @Test fun indexOfAnyStringIgnoreCase() = withOneCharSequenceArg("aBraCadaBrA") { string -> |
| val substrings = listOf("rAc", "Ra") |
| |
| assertEquals(2, string.indexOfAny(substrings, ignoreCase = true)) |
| assertEquals(9, string.indexOfAny(substrings, startIndex = 3, ignoreCase = true)) |
| assertEquals(-1, string.indexOfAny(substrings, startIndex = 10, ignoreCase = true)) |
| |
| assertEquals(9, string.lastIndexOfAny(substrings, ignoreCase = true)) |
| assertEquals(2, string.lastIndexOfAny(substrings, startIndex = 8, ignoreCase = true)) |
| assertEquals(-1, string.lastIndexOfAny(substrings, startIndex = 1, ignoreCase = true)) |
| } |
| |
| @Test fun findAnyOfStrings() = withOneCharSequenceArg("abracadabra") { string -> |
| val substrings = listOf("rac", "ra") |
| assertEquals(2 to "rac", string.findAnyOf(substrings)) |
| assertEquals(9 to "ra", string.findAnyOf(substrings, startIndex = 3)) |
| assertEquals(2 to "ra", string.findAnyOf(substrings.reversed())) |
| assertEquals(null, string.findAnyOf(substrings, 10)) |
| |
| assertEquals(9 to "ra", string.findLastAnyOf(substrings)) |
| assertEquals(2 to "rac", string.findLastAnyOf(substrings, startIndex = 8)) |
| assertEquals(2 to "ra", string.findLastAnyOf(substrings.reversed(), startIndex = 8)) |
| assertEquals(null, string.findLastAnyOf(substrings, 1)) |
| |
| assertEquals(0 to "", string.findAnyOf(listOf("dab", "")), "empty strings are not ignored") |
| assertEquals(null, string.findAnyOf(listOf())) |
| } |
| |
| @Test fun findAnyOfStringsIgnoreCase() = withOneCharSequenceArg("aBraCadaBrA") { string -> |
| val substrings = listOf("rAc", "Ra") |
| |
| assertEquals(2 to substrings[0], string.findAnyOf(substrings, ignoreCase = true)) |
| assertEquals(9 to substrings[1], string.findAnyOf(substrings, startIndex = 3, ignoreCase = true)) |
| assertEquals(null, string.findAnyOf(substrings, startIndex = 10, ignoreCase = true)) |
| |
| assertEquals(9 to substrings[1], string.findLastAnyOf(substrings, ignoreCase = true)) |
| assertEquals(2 to substrings[0], string.findLastAnyOf(substrings, startIndex = 8, ignoreCase = true)) |
| assertEquals(null, string.findLastAnyOf(substrings, startIndex = 1, ignoreCase = true)) |
| } |
| |
| @Test fun indexOfChar() = withOneCharSequenceArg("bcedef") { string -> |
| assertEquals(-1, string.indexOf('a')) |
| assertEquals(2, string.indexOf('e')) |
| assertEquals(2, string.indexOf('e', 2)) |
| assertEquals(4, string.indexOf('e', 3)) |
| assertEquals(4, string.lastIndexOf('e')) |
| assertEquals(2, string.lastIndexOf('e', 3)) |
| |
| for (startIndex in -1..string.length+1) { |
| assertEquals(string.indexOfAny(charArrayOf('e'), startIndex), string.indexOf('e', startIndex)) |
| assertEquals(string.lastIndexOfAny(charArrayOf('e'), startIndex), string.lastIndexOf('e', startIndex)) |
| } |
| |
| } |
| |
| @Test fun indexOfCharIgnoreCase() = withOneCharSequenceArg("bCEdef") { string -> |
| assertEquals(-1, string.indexOf('a', ignoreCase = true)) |
| assertEquals(2, string.indexOf('E', ignoreCase = true)) |
| assertEquals(2, string.indexOf('e', 2, ignoreCase = true)) |
| assertEquals(4, string.indexOf('E', 3, ignoreCase = true)) |
| assertEquals(4, string.lastIndexOf('E', ignoreCase = true)) |
| assertEquals(2, string.lastIndexOf('e', 3, ignoreCase = true)) |
| |
| |
| for (startIndex in -1..string.length+1){ |
| assertEquals(string.indexOfAny(charArrayOf('e'), startIndex, ignoreCase = true), string.indexOf('E', startIndex, ignoreCase = true)) |
| assertEquals(string.lastIndexOfAny(charArrayOf('E'), startIndex, ignoreCase = true), string.lastIndexOf('e', startIndex, ignoreCase = true)) |
| } |
| } |
| |
| @Test fun indexOfString() = withOneCharSequenceArg("bceded") { string -> |
| for (index in string.indices) |
| assertEquals(index, string.indexOf("", index)) |
| assertEquals(1, string.indexOf("ced")) |
| assertEquals(4, string.indexOf("ed", 3)) |
| assertEquals(-1, string.indexOf("abcdefgh")) |
| } |
| |
| @Test fun indexOfStringIgnoreCase() = withOneCharSequenceArg("bceded") { string -> |
| for (index in string.indices) |
| assertEquals(index, string.indexOf("", index, ignoreCase = true)) |
| assertEquals(1, string.indexOf("cEd", ignoreCase = true)) |
| assertEquals(4, string.indexOf("Ed", 3, ignoreCase = true)) |
| assertEquals(-1, string.indexOf("abcdefgh", ignoreCase = true)) |
| } |
| |
| |
| @Test fun contains() = withTwoCharSequenceArgs { arg1, arg2 -> |
| operator fun String.contains(other: String): Boolean = arg1(this).contains(arg2(other)) |
| operator fun String.contains(other: Char): Boolean = arg1(this).contains(other) |
| |
| assertTrue("pl" in "sample") |
| assertFalse("PL" in "sample") |
| assertTrue(arg1("sömple").contains(arg2("Ö"), ignoreCase = true)) |
| |
| assertTrue("" in "sample") |
| assertTrue("" in "") |
| |
| assertTrue('ö' in "sömple") |
| assertFalse('Ö' in "sömple") |
| assertTrue(arg1("sömple").contains('Ö', ignoreCase = true)) |
| } |
| |
| @Test fun equalsIgnoreCase() { |
| assertFalse("sample".equals("Sample", ignoreCase = false)) |
| assertTrue("sample".equals("Sample", ignoreCase = true)) |
| assertFalse("sample".equals(null, ignoreCase = false)) |
| assertFalse("sample".equals(null, ignoreCase = true)) |
| assertTrue(null.equals(null, ignoreCase = true)) |
| assertTrue(null.equals(null, ignoreCase = false)) |
| } |
| |
| |
| @Test fun replace() { |
| val input = "abbAb" |
| assertEquals("abb${'$'}b", input.replace('A', '$')) |
| assertEquals("/bb/b", input.replace('A', '/', ignoreCase = true)) |
| |
| assertEquals("${'$'}bAb", input.replace("ab", "$")) |
| assertEquals("/b/", input.replace("ab", "/", ignoreCase = true)) |
| |
| assertEquals("-a-b-b-A-b-", input.replace("", "-")) |
| } |
| |
| @Test fun replaceFirst() { |
| val input = "AbbabA" |
| assertEquals("Abb${'$'}bA", input.replaceFirst('a','$')) |
| assertEquals("${'$'}bbabA", input.replaceFirst('a','$', ignoreCase = true)) |
| // doesn't pass in Rhino JS |
| // assertEquals("schrodinger", "schrÖdinger".replaceFirst('ö', 'o', ignoreCase = true)) |
| |
| assertEquals("Abba${'$'}", input.replaceFirst("bA", "$")) |
| assertEquals("Ab${'$'}bA", input.replaceFirst("bA", "$", ignoreCase = true)) |
| |
| assertEquals("-test", "test".replaceFirst("", "-")) |
| } |
| |
| @Test fun count() = withOneCharSequenceArg("hello there\tfoo\nbar") { text -> |
| val whitespaceCount = text.count { it.isWhitespace() } |
| assertEquals(3, whitespaceCount) |
| } |
| |
| @Test fun testSplitByChar() = withOneCharSequenceArg("ab\n[|^$&\\]^cd") { s -> |
| s.split('b').let { list -> |
| assertEquals(2, list.size) |
| assertEquals("a", list[0]) |
| assertEquals("\n[|^$&\\]^cd", list[1]) |
| } |
| s.split('^').let { list -> |
| assertEquals(3, list.size) |
| assertEquals("cd", list[2]) |
| } |
| s.split('.').let { list -> |
| assertEquals(1, list.size) |
| assertEquals(s.toString(), list[0]) |
| } |
| } |
| |
| @Test fun forEach() = withOneCharSequenceArg("abcd1234") { data -> |
| var count = 0 |
| val sb = StringBuilder() |
| data.forEach { |
| count++ |
| sb.append(it) |
| } |
| assertEquals(data.length, count) |
| assertEquals(data.toString(), sb.toString()) |
| } |
| |
| @Test |
| fun onEach() = withOneCharSequenceArg("abcd") { data -> |
| val result = StringBuilder() |
| val newData = data.onEach { result.append(it + 1) } |
| assertEquals("bcde", result.toString()) |
| assertTrue(data === newData) |
| |
| // static types test |
| assertStaticTypeIs<String>("x".onEach { }) |
| assertStaticTypeIs<StringBuilder>(result.onEach { }) |
| } |
| |
| |
| @Test fun filter() { |
| assertEquals("acdca", ("abcdcba").filter { !it.equals('b') }) |
| assertEquals("1234", ("a1b2c3d4").filter { it.isAsciiDigit() }) |
| } |
| |
| @Test fun filterCharSequence() = withOneCharSequenceArg { arg1 -> |
| assertContentEquals("acdca", arg1("abcdcba").filter { !it.equals('b') }) |
| assertContentEquals("1234", arg1("a1b2c3d4").filter { it.isAsciiDigit() }) |
| } |
| |
| @Test fun filterNot() { |
| assertEquals("acdca", ("abcdcba").filterNot { it.equals('b') }) |
| assertEquals("abcd", ("a1b2c3d4").filterNot { it.isAsciiDigit() }) |
| } |
| |
| @Test fun filterNotCharSequence() = withOneCharSequenceArg { arg1 -> |
| assertContentEquals("acdca", arg1("abcdcba").filterNot { it.equals('b') }) |
| assertContentEquals("abcd", arg1("a1b2c3d4").filterNot { it.isAsciiDigit() }) |
| } |
| |
| @Test fun filterIndexed() { |
| val data = "abedcf" |
| assertEquals("abdf", data.filterIndexed { index, c -> c == 'a' + index }) |
| } |
| |
| @Test fun filterIndexedCharSequence() = withOneCharSequenceArg("abedcf") { data -> |
| assertContentEquals("abdf", data.filterIndexed { index, c -> c == 'a' + index }) |
| } |
| |
| @Test fun all() = withOneCharSequenceArg("AbCd") { data -> |
| assertTrue { |
| data.all { it.isAsciiLetter() } |
| } |
| assertFalse { |
| data.all { it.isAsciiUpperCase() } |
| } |
| } |
| |
| @Test fun any() = withOneCharSequenceArg("a1bc") { data -> |
| assertTrue { |
| data.any() { it.isAsciiDigit() } |
| } |
| assertFalse { |
| data.any() { it.isAsciiUpperCase() } |
| } |
| } |
| |
| @Test fun find() = withOneCharSequenceArg("a1b2c3") { data -> |
| assertEquals('1', data.first { it.isAsciiDigit() }) |
| assertNull(data.firstOrNull { it.isAsciiUpperCase() }) |
| } |
| |
| @Test fun findNot() = withOneCharSequenceArg("1a2b3c") { data -> |
| assertEquals('a', data.filterNot { it.isAsciiDigit() }.firstOrNull()) |
| assertNull(data.filterNot { it.isAsciiLetter() || it.isAsciiDigit() }.firstOrNull()) |
| } |
| |
| @Test fun partition() { |
| val data = "a1b2c3" |
| val pair = data.partition { it.isAsciiDigit() } |
| assertEquals("123", pair.first, "pair.first") |
| assertEquals("abc", pair.second, "pair.second") |
| } |
| |
| @Test fun partitionCharSequence() = withOneCharSequenceArg("a1b2c3") { data -> |
| val pair = data.partition { it.isAsciiDigit() } |
| assertContentEquals("123", pair.first, "pair.first") |
| assertContentEquals("abc", pair.second, "pair.second") |
| } |
| |
| @Test fun zipWithNext() = withOneCharSequenceArg { arg1 -> |
| assertEquals(listOf("ab", "bc"), arg1("abc").zipWithNext { a: Char, b: Char -> a.toString() + b }) |
| assertTrue(arg1("").zipWithNext { a: Char, b: Char -> a.toString() + b }.isEmpty()) |
| assertTrue(arg1("a").zipWithNext { a: Char, b: Char -> a.toString() + b }.isEmpty()) |
| } |
| |
| @Test fun zipWithNextPairs() = withOneCharSequenceArg { arg1 -> |
| assertEquals(listOf('a' to 'b', 'b' to 'c'), arg1("abc").zipWithNext()) |
| assertTrue(arg1("").zipWithNext().isEmpty()) |
| assertTrue(arg1("a").zipWithNext().isEmpty()) |
| } |
| |
| |
| @Test |
| fun chunked() = withOneCharSequenceArg { arg1 -> |
| val size = 7 |
| val data = arg1("abcdefg") |
| val result = data.chunked(4) |
| assertEquals(listOf("abcd", "efg"), result) |
| |
| val result2 = data.chunked(3) { it.reversed().toString() } |
| assertEquals(listOf("cba", "fed", "g"), result2) |
| |
| data.toString().let { expectedSingleChunk -> |
| assertEquals(expectedSingleChunk, data.chunked(size).single()) |
| assertEquals(expectedSingleChunk, data.chunked(size + 3).single()) |
| } |
| |
| assertTrue(arg1("").chunked(3).isEmpty()) |
| |
| for (illegalValue in listOf(Int.MIN_VALUE, -1, 0)) { |
| assertFailsWith<IllegalArgumentException>("size $illegalValue") { data.chunked(illegalValue) } |
| } |
| |
| for (chunkSize in 1..size + 1) { |
| compare(data.chunked(chunkSize).iterator(), data.chunkedSequence(chunkSize).iterator()) { iteratorBehavior() } |
| } |
| } |
| |
| |
| @Test |
| fun windowed() = withOneCharSequenceArg { arg1 -> |
| val size = 7 |
| val data = arg1("abcdefg") |
| val result = data.windowed(4, 2) |
| assertEquals(listOf("abcd", "cdef"), result) |
| |
| val resultPartial = data.windowed(4, 2, partialWindows = true) |
| assertEquals(listOf("abcd", "cdef", "efg", "g"), resultPartial) |
| |
| val result2 = data.windowed(2, 3) { it.reversed().toString() } |
| assertEquals(listOf("ba", "ed"), result2) |
| val result2partial = data.windowed(2, 3, partialWindows = true) { it.reversed().toString() } |
| assertEquals(listOf("ba", "ed", "g"), result2partial) |
| |
| assertEquals(data.chunked(2), data.windowed(2, 2, partialWindows = true)) |
| |
| assertEquals(data.take(2), data.windowed(2, size).single()) |
| assertEquals(data.take(3), data.windowed(3, size + 3).single()) |
| |
| |
| assertEquals(data.toString(), data.windowed(size, 1).single()) |
| assertTrue(data.windowed(size + 1, 1).isEmpty()) |
| |
| val result3partial = data.windowed(size, 1, partialWindows = true) |
| result3partial.forEachIndexed { index, window -> |
| assertEquals(size - index, window.length, "size of window#$index") |
| } |
| |
| assertTrue(arg1("").windowed(3, 2).isEmpty()) |
| |
| for (illegalValue in listOf(Int.MIN_VALUE, -1, 0)) { |
| assertFailsWith<IllegalArgumentException>("size $illegalValue") { data.windowed(illegalValue, 1) } |
| assertFailsWith<IllegalArgumentException>("step $illegalValue") { data.windowed(1, illegalValue) } |
| } |
| |
| for (window in 1..size + 1) { |
| for (step in 1..size + 1) { |
| compare(data.windowed(window, step).iterator(), data.windowedSequence(window, step).iterator()) { iteratorBehavior() } |
| compare(data.windowed(window, step, partialWindows = true).iterator(), |
| data.windowedSequence(window, step, partialWindows = true).iterator()) { iteratorBehavior() } |
| } |
| } |
| } |
| |
| @Test fun map() = withOneCharSequenceArg { arg1 -> |
| assertEquals(listOf('a', 'b', 'c'), arg1("abc").map { it }) |
| |
| assertEquals(listOf(true, false, true), arg1("AbC").map { it.isAsciiUpperCase() }) |
| |
| assertEquals(listOf<Boolean>(), arg1("").map { it.isAsciiUpperCase() }) |
| |
| assertEquals(listOf(97, 98, 99), arg1("abc").map { it.toInt() }) |
| } |
| |
| @Test fun mapTo() = withOneCharSequenceArg { arg1 -> |
| val result1 = arrayListOf<Char>() |
| val return1 = arg1("abc").mapTo(result1, { it }) |
| assertEquals(result1, return1) |
| assertEquals(arrayListOf('a', 'b', 'c'), result1) |
| |
| val result2 = arrayListOf<Boolean>() |
| val return2 = arg1("AbC").mapTo(result2, { it.isAsciiUpperCase() }) |
| assertEquals(result2, return2) |
| assertEquals(arrayListOf(true, false, true), result2) |
| |
| val result3 = arrayListOf<Boolean>() |
| val return3 = arg1("").mapTo(result3, { it.isAsciiUpperCase() }) |
| assertEquals(result3, return3) |
| assertEquals(arrayListOf<Boolean>(), result3) |
| |
| val result4 = arrayListOf<Int>() |
| val return4 = arg1("abc").mapTo(result4, { it.toInt() }) |
| assertEquals(result4, return4) |
| assertEquals(arrayListOf(97, 98, 99), result4) |
| } |
| |
| @Test fun flatMap() = withOneCharSequenceArg("abcd") { data -> |
| val result = data.flatMap { ('a'..it) + ' ' } |
| assertEquals("a ab abc abcd ".toList(), result) |
| } |
| |
| @Test fun fold() = withOneCharSequenceArg { arg1 -> |
| // calculate number of digits in the string |
| val data = arg1("a1b2c3def") |
| val result = data.fold(0, { digits, c -> if(c.isAsciiDigit()) digits + 1 else digits } ) |
| assertEquals(3, result) |
| |
| //simulate all method |
| assertEquals(true, arg1("ABCD").fold(true, { r, c -> r && c.isAsciiUpperCase() })) |
| |
| //get string back |
| assertEquals(data.toString(), data.fold("", { s, c -> s + c })) |
| } |
| |
| @Test fun foldRight() = withOneCharSequenceArg { arg1 -> |
| // calculate number of digits in the string |
| val data = arg1("a1b2c3def") |
| val result = data.foldRight(0, { c, digits -> if(c.isAsciiDigit()) digits + 1 else digits }) |
| assertEquals(3, result) |
| |
| //simulate all method |
| assertEquals(true, arg1("ABCD").foldRight(true, { c, r -> r && c.isAsciiUpperCase() })) |
| |
| //get string back |
| assertEquals(data.toString(), data.foldRight("", { s, c -> "" + s + c })) |
| } |
| |
| @Test fun reduceIndexed() = withOneCharSequenceArg { arg1 -> |
| // get the 3rd character |
| assertEquals('c', arg1("bacfd").reduceIndexed { index, v, c -> if (index == 2) c else v }) |
| |
| expect('c') { |
| "ab".reduceIndexed { index, acc, e -> |
| assertEquals(1, index) |
| assertEquals('a', acc) |
| assertEquals('b', e) |
| e + (e - acc) |
| } |
| } |
| |
| assertFailsWith<UnsupportedOperationException> { |
| arg1("").reduceIndexed { _, _, _ -> '\n' } |
| } |
| } |
| |
| @Test fun reduceRightIndexed() = withOneCharSequenceArg { arg1 -> |
| // get the 3rd character |
| assertEquals('c', arg1("bacfd").reduceRightIndexed { index, c, v -> if (index == 2) c else v }) |
| |
| expect('c') { |
| "ab".reduceRightIndexed { index, e, acc -> |
| assertEquals(0, index) |
| assertEquals('b', acc) |
| assertEquals('a', e) |
| acc + (acc - e) |
| } |
| } |
| |
| assertFailsWith<UnsupportedOperationException> { |
| arg1("").reduceRightIndexed { _, _, _ -> '\n' } |
| } |
| } |
| |
| @Test fun reduce() = withOneCharSequenceArg { arg1 -> |
| // get the smallest character(by char value) |
| assertEquals('a', arg1("bacfd").reduce { v, c -> if (v > c) c else v }) |
| |
| assertFailsWith<UnsupportedOperationException> { |
| arg1("").reduce { _, _ -> '\n' } |
| } |
| } |
| |
| @Test fun reduceRight() = withOneCharSequenceArg { arg1 -> |
| // get the smallest character(by char value) |
| assertEquals('a', arg1("bacfd").reduceRight { c, v -> if (v > c) c else v }) |
| |
| assertFailsWith<UnsupportedOperationException> { |
| arg1("").reduceRight { _, _ -> '\n' } |
| } |
| } |
| |
| @Test fun groupBy() = withOneCharSequenceArg("abAbaABcD") { data -> |
| // group characters by their case |
| val result = data.groupBy { it.isAsciiUpperCase() } |
| assertEquals(2, result.size) |
| assertEquals(listOf('a','b','b','a','c'), result[false]) |
| assertEquals(listOf('A','A','B','D'), result[true]) |
| } |
| |
| @Test fun joinToString() { |
| val data = "abcd".toList() |
| val result = data.joinToString("_", "(", ")") |
| assertEquals("(a_b_c_d)", result) |
| |
| val data2 = "verylongstring".toList() |
| val result2 = data2.joinToString("-", "[", "]", 11, "oops") |
| assertEquals("[v-e-r-y-l-o-n-g-s-t-r-oops]", result2) |
| |
| val data3 = "a1/b".toList() |
| val result3 = data3.joinToString() { it.toUpperCase().toString() } |
| assertEquals("A, 1, /, B", result3) |
| } |
| |
| @Test fun joinTo() { |
| val data = "kotlin".toList() |
| val sb = StringBuilder() |
| data.joinTo(sb, "^", "<", ">") |
| assertEquals("<k^o^t^l^i^n>", sb.toString()) |
| } |
| |
| |
| @Test fun dropWhile() { |
| val data = "ab1cd2" |
| assertEquals("1cd2", data.dropWhile { it.isAsciiLetter() }) |
| assertEquals("", data.dropWhile { true }) |
| assertEquals("ab1cd2", data.dropWhile { false }) |
| } |
| |
| @Test fun dropWhileCharSequence() = withOneCharSequenceArg("ab1cd2") { data -> |
| assertContentEquals("1cd2", data.dropWhile { it.isAsciiLetter() }) |
| assertContentEquals("", data.dropWhile { true }) |
| assertContentEquals("ab1cd2", data.dropWhile { false }) |
| } |
| |
| |
| @Test fun drop() { |
| val data = "abcd1234" |
| assertEquals("d1234", data.drop(3)) |
| assertFails { |
| data.drop(-2) |
| } |
| assertEquals("", data.drop(data.length + 5)) |
| } |
| |
| @Test fun dropCharSequence() = withOneCharSequenceArg("abcd1234") { data -> |
| assertContentEquals("d1234", data.drop(3)) |
| assertFails { |
| data.drop(-2) |
| } |
| assertContentEquals("", data.drop(data.length + 5)) |
| } |
| |
| @Test fun takeWhile() { |
| val data = "ab1cd2" |
| assertEquals("ab", data.takeWhile { it.isAsciiLetter() }) |
| assertEquals("", data.takeWhile { false }) |
| assertEquals("ab1cd2", data.takeWhile { true }) |
| } |
| |
| @Test fun takeWhileCharSequence() = withOneCharSequenceArg("ab1cd2") { data -> |
| assertContentEquals("ab", data.takeWhile { it.isAsciiLetter() }) |
| assertContentEquals("", data.takeWhile { false }) |
| assertContentEquals("ab1cd2", data.takeWhile { true }) |
| } |
| |
| @Test fun take() { |
| val data = "abcd1234" |
| assertEquals("abc", data.take(3)) |
| assertFails { |
| data.take(-7) |
| } |
| assertEquals(data, data.take(data.length + 42)) |
| } |
| |
| @Test fun takeCharSequence() = withOneCharSequenceArg("abcd1234") { data -> |
| assertEquals("abc", data.take(3)) |
| assertFails { |
| data.take(-7) |
| } |
| assertContentEquals(data.toString(), data.take(data.length + 42)) |
| } |
| |
| |
| @Test fun testReplaceAllClosure() = withOneCharSequenceArg("test123zzz") { s -> |
| val result = s.replace("\\d+".toRegex()) { mr -> |
| "[" + mr.value + "]" |
| } |
| assertEquals("test[123]zzz", result) |
| } |
| |
| @Test fun testReplaceAllClosureAtStart() = withOneCharSequenceArg("123zzz") { s -> |
| val result = s.replace("\\d+".toRegex()) { mr -> |
| "[" + mr.value + "]" |
| } |
| assertEquals("[123]zzz", result) |
| } |
| |
| @Test fun testReplaceAllClosureAtEnd() = withOneCharSequenceArg("test123") { s -> |
| val result = s.replace("\\d+".toRegex()) { mr -> |
| "[" + mr.value + "]" |
| } |
| assertEquals("test[123]", result) |
| } |
| |
| @Test fun testReplaceAllClosureEmpty() = withOneCharSequenceArg("") { s -> |
| val result = s.replace("\\d+".toRegex()) { _ -> |
| "x" |
| } |
| assertEquals("", result) |
| |
| } |
| |
| @Test fun trimMargin() { |
| // WARNING |
| // DO NOT REFORMAT AS TESTS MAY FAIL DUE TO INDENTATION CHANGE |
| |
| assertEquals("ABC\n123\n456", """ABC |
| |123 |
| |456""".trimMargin()) |
| |
| assertEquals("ABC\n 123\n 456", """ABC |
| |123 |
| |456""".replaceIndentByMargin(newIndent = " ")) |
| |
| assertEquals("ABC \n123\n456", """ABC${" "} |
| |123 |
| |456""".trimMargin()) |
| |
| assertEquals(" ABC\n123\n456", """ ABC |
| >>123 |
| ${"\t"}>>456""".trimMargin(">>")) |
| |
| assertEquals("", "".trimMargin()) |
| |
| assertEquals("", """ |
| """.trimMargin()) |
| |
| assertEquals("", """ |
| |""".trimMargin()) |
| |
| assertEquals("", """ |
| | |
| """.trimMargin()) |
| |
| assertEquals(" a", """ |
| | a |
| """.trimMargin()) |
| |
| assertEquals(" a", """ |
| | a""".trimMargin()) |
| |
| assertEquals(" a", """ | a |
| """.trimMargin()) |
| |
| assertEquals(" a", """ | a""".trimMargin()) |
| |
| assertEquals("\u0000|ABC", "${"\u0000"}|ABC".trimMargin()) |
| } |
| |
| @Test fun trimIndent() { |
| // WARNING |
| // DO NOT REFORMAT AS TESTS MAY FAIL DUE TO INDENTATION CHANGE |
| |
| assertEquals("123", """ |
| 123 |
| """.trimIndent()) |
| |
| assertEquals("123\n 456", """ |
| 123 |
| 456 |
| """.trimIndent()) |
| |
| assertEquals(" 123\n456", """ |
| 123 |
| 456 |
| """.trimIndent()) |
| |
| assertEquals(" 123\n 456", """ |
| 123 |
| 456 |
| """.replaceIndent(newIndent = " ")) |
| |
| assertEquals(" 123\n456", """ |
| 123 |
| 456""".trimIndent()) |
| |
| assertEquals(" ", """ |
| ${" "} |
| """.trimIndent()) |
| |
| val deindented = """ |
| ,. |
| ,. _ oo. `88P |
| ]88b ,o. d88. ]88b ' |
| 888 _ Y888o888 d88P _ _ |
| 888 ,888 `Y88888o_ ,888 d88b d88._____ |
| 888,888P ,oooooo. ;888888b.]88P 888' d888888888p |
| 888888P d88888888. J88b'YPP ]88b ,888 d888P'''888. |
| 8888P' ]88P `888 d88[ d88P ]88b 888' Y88b |
| 8888p ]88b 888 888 d88[ 888 888. `888 |
| ,88888b 888[ 888 888. d88[ 888. Y88b Y88[ |
| d88PY88b `888L,d88P Y88b Y88b ]88b `888 888' |
| 888 Y88b Y88888P 888. 888. 888. Y88b `88P |
| d88P 888 `'P' Y888. `888. `88P `Y8P ' |
| Y8P' ' `YP Y8P' ' |
| |
| ____ dXp _ _ _________ |
| ddXXXXXp XXP ,XX dXb Yo.XXXXXX ,oooooo. |
| X'L_oXXP XX' XX[ dXb dXb YPPPPXXX' |
| XYXXXXX ]XX dXb dXb dX8Xooooo dXXP |
| XXb`YYXXo. YXXo_ dXP dXP YXb'''''' ,XXP' |
| `XX `YYXb `YXXXXP XX[ ]XX ,XX' |
| YXb YXb `'' XXXXooL `XX._____ `XXXXXXXXooooo. |
| `XP ' '''''' YPXXXXXX' ''''''`''YPPP |
| """.trimIndent() |
| |
| assertEquals(23, deindented.lines().size) |
| val indents = deindented.lines().map { "^\\s*".toRegex().find(it)!!.value.length } |
| assertEquals(0, indents.min()) |
| assertEquals(42, indents.max()) |
| assertEquals(1, deindented.lines().count { it.isEmpty() }) |
| } |
| |
| @Test fun testIndent() { |
| assertEquals(" ABC\n 123", "ABC\n123".prependIndent(" ")) |
| assertEquals(" ABC\n \n 123", "ABC\n\n123".prependIndent(" ")) |
| assertEquals(" ABC\n \n 123", "ABC\n \n123".prependIndent(" ")) |
| assertEquals(" ABC\n \n 123", "ABC\n \n123".prependIndent(" ")) |
| assertEquals(" ", "".prependIndent(" ")) |
| } |
| } |