/* * 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. */ @file:Suppress("SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED") package test.collections import test.assertStaticTypeIs import test.assertTypeEquals import test.collections.behaviors.* import test.comparisons.STRING_CASE_INSENSITIVE_ORDER import test.text.isAsciiLetter import kotlin.test.* import kotlin.random.Random fun assertArrayNotSameButEquals(expected: Array, actual: Array, message: String = "") { assertTrue(expected !== actual && expected contentEquals actual, message) } fun assertArrayNotSameButEquals(expected: IntArray, actual: IntArray, message: String = "") { assertTrue(expected !== actual && expected contentEquals actual, message) } fun assertArrayNotSameButEquals(expected: LongArray, actual: LongArray, message: String = "") { assertTrue(expected !== actual && expected contentEquals actual, message) } fun assertArrayNotSameButEquals(expected: ShortArray, actual: ShortArray, message: String = "") { assertTrue(expected !== actual && expected contentEquals actual, message) } fun assertArrayNotSameButEquals(expected: ByteArray, actual: ByteArray, message: String = "") { assertTrue(expected !== actual && expected contentEquals actual, message) } fun assertArrayNotSameButEquals(expected: DoubleArray, actual: DoubleArray, message: String = "") { assertTrue(expected !== actual && expected contentEquals actual, message) } fun assertArrayNotSameButEquals(expected: FloatArray, actual: FloatArray, message: String = "") { assertTrue(expected !== actual && expected contentEquals actual, message) } fun assertArrayNotSameButEquals(expected: CharArray, actual: CharArray, message: String = "") { assertTrue(expected !== actual && expected contentEquals actual, message) } fun assertArrayNotSameButEquals(expected: BooleanArray, actual: BooleanArray, message: String = "") { assertTrue(expected !== actual && expected contentEquals actual, message) } class ArraysTest { data class Value(val value: Int) { override fun hashCode(): Int = value } @Test fun orEmptyNull() { val x: Array? = null val y: Array? = null val xArray = x.orEmpty() val yArray = y.orEmpty() expect(0) { xArray.size } expect(0) { yArray.size } } @Test fun orEmptyNotNull() { val x: Array? = arrayOf("1", "2") val xArray = x.orEmpty() expect(2) { xArray.size } expect("1") { xArray[0] } expect("2") { xArray[1] } } @Test fun emptyArrayLastIndex() { val arr1 = IntArray(0) assertEquals(-1, arr1.lastIndex) val arr2 = emptyArray() assertEquals(-1, arr2.lastIndex) } @Test fun arrayLastIndex() { val arr1 = intArrayOf(0, 1, 2, 3, 4) assertEquals(4, arr1.lastIndex) assertEquals(4, arr1[arr1.lastIndex]) val arr2 = Array(5, { "$it" }) assertEquals(4, arr2.lastIndex) assertEquals("4", arr2[arr2.lastIndex]) } @Test fun byteArray() { val arr = ByteArray(2) val expected: Byte = 0 assertEquals(arr.size, 2) assertEquals(expected, arr[0]) assertEquals(expected, arr[1]) } @Test fun byteArrayInit() { val arr = ByteArray(2) { it.toByte() } assertEquals(2, arr.size) assertEquals(0.toByte(), arr[0]) assertEquals(1.toByte(), arr[1]) } @Test fun shortArray() { val arr = ShortArray(2) val expected: Short = 0 assertEquals(arr.size, 2) assertEquals(expected, arr[0]) assertEquals(expected, arr[1]) } @Test fun shortArrayInit() { val arr = ShortArray(2) { it.toShort() } assertEquals(2, arr.size) assertEquals(0.toShort(), arr[0]) assertEquals(1.toShort(), arr[1]) } @Test fun intArray() { val arr = IntArray(2) assertEquals(arr.size, 2) assertEquals(0, arr[0]) assertEquals(0, arr[1]) } @Test fun intArrayInit() { val arr = IntArray(2) { it.toInt() } assertEquals(2, arr.size) assertEquals(0.toInt(), arr[0]) assertEquals(1.toInt(), arr[1]) } @Test fun longArray() { val arr = LongArray(2) val expected: Long = 0 assertEquals(arr.size, 2) assertEquals(expected, arr[0]) assertEquals(expected, arr[1]) } @Test fun longArrayInit() { val arr = LongArray(2) { it.toLong() } assertEquals(2, arr.size) assertEquals(0.toLong(), arr[0]) assertEquals(1.toLong(), arr[1]) } @Test fun floatArray() { val arr = FloatArray(2) val expected: Float = 0.0F assertEquals(arr.size, 2) assertEquals(expected, arr[0]) assertEquals(expected, arr[1]) } @Test fun floatArrayInit() { val arr = FloatArray(2) { it.toFloat() } assertEquals(2, arr.size) assertEquals(0.toFloat(), arr[0]) assertEquals(1.toFloat(), arr[1]) } @Test fun doubleArray() { val arr = DoubleArray(2) assertEquals(arr.size, 2) assertEquals(0.0, arr[0]) assertEquals(0.0, arr[1]) } @Test fun doubleArrayInit() { val arr = DoubleArray(2) { it.toDouble() } assertEquals(2, arr.size) assertEquals(0.toDouble(), arr[0]) assertEquals(1.toDouble(), arr[1]) } @Test fun charArray() { val arr = CharArray(2) val expected: Char = '\u0000' assertEquals(arr.size, 2) assertEquals(expected, arr[0]) assertEquals(expected, arr[1]) } @Test fun charArrayInit() { val arr = CharArray(2) { 'a' + it } assertEquals(2, arr.size) assertEquals('a', arr[0]) assertEquals('b', arr[1]) } @Test fun booleanArray() { val arr = BooleanArray(2) assertEquals(arr.size, 2) assertEquals(false, arr[0]) assertEquals(false, arr[1]) } @Test fun booleanArrayInit() { val arr = BooleanArray(2) { it % 2 == 0 } assertEquals(2, arr.size) assertEquals(true, arr[0]) assertEquals(false, arr[1]) } @Test fun contentEquals() { fun checkArray(array: T, copy: T.() -> T, toList: T.() -> List<*>, check: (T, T) -> Boolean, modify: T.() -> Unit) { val list = toList(array) val array2 = copy(array) val list2 = toList(array2) assertEquals(list, list2) assertNotSame(array, array2) assertTrue(check(array, array2), "Copy of array should have the same content: original $list, modified $list2") modify(array2) val list2m = toList(array2) assertNotEquals(list, list2m) assertFalse(check(array, array2), "Modified array should be different: original $list, modified $list2m") } checkArray(arrayOf("a", 1, null), { copyOf() }, { toList() }, { a1, a2 -> a1 contentEquals a2 }, { reverse() }) checkArray(byteArrayOf(1, 2, 3), { copyOf() }, { toList() }, { a1, a2 -> a1 contentEquals a2 }, { reverse() }) checkArray(intArrayOf(1, 2, 3), { copyOf() }, { toList() }, { a1, a2 -> a1 contentEquals a2 }, { reverse() }) checkArray(longArrayOf(1, 2, 3), { copyOf() }, { toList() }, { a1, a2 -> a1 contentEquals a2 }, { reverse() }) checkArray(doubleArrayOf(Double.NaN, -0.0, 0.0, Double.POSITIVE_INFINITY, 1.0), { copyOf() }, { toList() }, { a1, a2 -> a1 contentEquals a2 }, { this[1] = 0.0 }) assertTrue((null as BooleanArray?) contentEquals null) assertFalse(null contentEquals shortArrayOf(1)) assertFalse((emptyArray() as Array?) contentEquals null) assertFalse(null.contentEquals(arrayOf("0", null))) } @Test fun contentDeepEquals() { val arr1 = arrayOf("a", 1, intArrayOf(2)) val arr2 = arrayOf("a", 1, intArrayOf(2)) val arr3 = arrayOf("a", 1, uintArrayOf(2u)) val arr4 = arrayOf("a", 1, uintArrayOf(2u)) assertFalse(arr1 contentEquals arr2) assertTrue(arr1 contentDeepEquals arr2) assertFalse(arr1 contentDeepEquals arr3) assertTrue(arr3 contentDeepEquals arr4) arr2[2] = arr1 assertFalse(arr1 contentDeepEquals arr2) arr4[2] = arr3 assertFalse(arr3 contentDeepEquals arr4) val arr5 = arrayOf(doubleArrayOf(-0.0, Double.NaN)) val arr6 = arrayOf(doubleArrayOf(0.0, Double.NaN)) assertFalse(arr5 contentDeepEquals arr6) arr5[0][0] = 0.0 assertTrue(arr5 contentDeepEquals arr6) assertTrue((null as Array?) contentDeepEquals null) assertTrue(null contentDeepEquals (null as Array?)) assertFalse(arrayOf("") contentDeepEquals null) assertFalse(null contentDeepEquals arrayOf(null)) } @Test fun contentToString() { arrayOf("a", 1, null).let { arr -> assertEquals(arr.asList().toString(), arr.contentToString()) } charArrayOf('a', 'b', 'd').let { arr -> assertEquals(arr.asList().toString(), arr.contentToString()) } intArrayOf(1, 10, 42).let { arr -> assertEquals(arr.asList().toString(), arr.contentToString()) } longArrayOf(1L, 5L, Long.MAX_VALUE).let { arr -> assertEquals(arr.asList().toString(), arr.contentToString()) } doubleArrayOf(0.0, Double.MAX_VALUE, Double.POSITIVE_INFINITY, Double.NaN).let { arr -> assertEquals(arr.asList().toString(), arr.contentToString()) } (null as ByteArray?).let { arr -> assertEquals(arr?.asList().toString(), arr.contentToString()) } } @Test fun contentDeepToString() { val arr = arrayOf( "aa", 1, null, arrayOf(arrayOf("foo")), charArrayOf('d'), booleanArrayOf(false), intArrayOf(-1), longArrayOf(-1), shortArrayOf(-1), byteArrayOf(-1), uintArrayOf(UInt.MAX_VALUE), ulongArrayOf(ULong.MAX_VALUE), ushortArrayOf(UShort.MAX_VALUE), ubyteArrayOf(UByte.MAX_VALUE), doubleArrayOf(3.14), floatArrayOf(1.25f) ) assertEquals("[aa, 1, null, [[foo]], [d], [false], [-1], [-1], [-1], [-1], [4294967295], [18446744073709551615], [65535], [255], [3.14], [1.25]]", arr.contentDeepToString()) assertEquals("null", (null as Array?).contentDeepToString()) } @Test fun contentDeepToStringNoRecursion() { // a[b[a, b]] val b = arrayOfNulls(2) val a = arrayOf(b) b[0] = a b[1] = b a.toString() assertTrue(true, "toString does not cycle") a.contentToString() assertTrue(true, "contentToString does not cycle") val result = a.contentDeepToString() assertEquals("[[[...], [...]]]", result) } @Test fun contentHashCode() { val arr = arrayOf("a", 1, null, Value(5)) assertEquals(listOf(*arr).hashCode(), arr.contentHashCode()) assertEquals((1*31 + 2)*31 + 3, arrayOf(Value(2), Value(3)).contentHashCode()) longArrayOf(1L, Long.MAX_VALUE, Long.MIN_VALUE).let { assertEquals(it.toList().hashCode(), it.contentHashCode()) } intArrayOf(1, Int.MAX_VALUE, Int.MIN_VALUE).let { assertEquals(it.toList().hashCode(), it.contentHashCode()) } byteArrayOf(1, Byte.MAX_VALUE, Byte.MIN_VALUE).let { assertEquals(it.toList().hashCode(), it.contentHashCode()) } charArrayOf('a', Char.MAX_VALUE, Char.MIN_VALUE).let { assertEquals(it.toList().hashCode(), it.contentHashCode()) } doubleArrayOf(1.0, -0.0, 0.0, Double.NaN, Double.POSITIVE_INFINITY).let { assertEquals(it.toList().hashCode(), it.contentHashCode()) } floatArrayOf(1.0f, -0.0f, 0.0f, Float.NaN, Float.POSITIVE_INFINITY).let { assertEquals(it.toList().hashCode(), it.contentHashCode()) } (null as IntArray?).let { assertEquals(it?.toList().hashCode(), it.contentHashCode()) } } @Test fun contentDeepHashCode() { val arr = arrayOf(null, Value(2), arrayOf(Value(3))) assertEquals(((1*31 + 0)*31 + 2) * 31 + (1 * 31 + 3), arr.contentDeepHashCode()) val intArray2 = arrayOf(intArrayOf(1, 2), intArrayOf(3, 4)) val intList2 = listOf(listOf(1, 2), listOf(3, 4)) assertEquals(intList2.hashCode(), intArray2.contentDeepHashCode()) val doubleArray2 = arrayOf(doubleArrayOf(1.0, Double.NaN), doubleArrayOf(-0.0, 0.0)) val doubleList2 = listOf(listOf(1.0, Double.NaN), listOf(-0.0, 0.0)) assertEquals(doubleList2.hashCode(), doubleArray2.contentDeepHashCode()) val uintArray2 = arrayOf(uintArrayOf(1u, 2u), uintArrayOf(3u, 4u)) val uintList2 = listOf(listOf(1u, 2u), listOf(3u, 4u)) assertEquals(uintList2.hashCode(), uintArray2.contentDeepHashCode()) assertEquals(0, (null as Array?).contentDeepHashCode()) } @Test fun joinToString() { val text = arrayOf("foo", "bar").joinToString("-", "<", ">") assertEquals("", text) val text2 = arrayOf('a', "b", StringBuilder("c"), null, "d", 'e', 'f').joinToString(limit = 4, truncated = "*") assertEquals("a, b, c, null, *", text2) val text3 = intArrayOf(1, 2, 5, 8).joinToString("+", "[", "]") assertEquals("[1+2+5+8]", text3) val text4 = charArrayOf('f', 'o', 'o').joinToString() assertEquals("f, o, o", text4) } @Test fun minOrNull() { expect(null, { arrayOf().minOrNull() }) expect(1, { arrayOf(1).minOrNull() }) expect(2, { arrayOf(2, 3).minOrNull() }) expect(2000000000000, { arrayOf(3000000000000, 2000000000000).minOrNull() }) expect('a', { arrayOf('a', 'b').minOrNull() }) expect("a", { arrayOf("a", "b").minOrNull() }) } @Test fun minOrNullInPrimitiveArrays() { expect(null, { intArrayOf().minOrNull() }) expect(1, { intArrayOf(1).minOrNull() }) expect(2, { intArrayOf(2, 3).minOrNull() }) expect(2000000000000, { longArrayOf(3000000000000, 2000000000000).minOrNull() }) expect(1, { byteArrayOf(1, 3, 2).minOrNull() }) expect(2, { shortArrayOf(3, 2).minOrNull() }) expect(2.0F, { floatArrayOf(3.0F, 2.0F).minOrNull() }) expect(2.0, { doubleArrayOf(2.0, 3.0).minOrNull() }) expect('a', { charArrayOf('a', 'b').minOrNull() }) } @Test fun maxOrNull() { expect(null, { arrayOf().maxOrNull() }) expect(1, { arrayOf(1).maxOrNull() }) expect(3, { arrayOf(2, 3).maxOrNull() }) expect(3000000000000, { arrayOf(3000000000000, 2000000000000).maxOrNull() }) expect('b', { arrayOf('a', 'b').maxOrNull() }) expect("b", { arrayOf("a", "b").maxOrNull() }) } @Test fun maxOrNullInPrimitiveArrays() { expect(null, { intArrayOf().maxOrNull() }) expect(1, { intArrayOf(1).maxOrNull() }) expect(3, { intArrayOf(2, 3).maxOrNull() }) expect(3000000000000, { longArrayOf(3000000000000, 2000000000000).maxOrNull() }) expect(3, { byteArrayOf(1, 3, 2).maxOrNull() }) expect(3, { shortArrayOf(3, 2).maxOrNull() }) expect(3.0F, { floatArrayOf(3.0F, 2.0F).maxOrNull() }) expect(3.0, { doubleArrayOf(2.0, 3.0).maxOrNull() }) expect('b', { charArrayOf('a', 'b').maxOrNull() }) } @Test fun minWithOrNull() { assertEquals(null, arrayOf().minWithOrNull(naturalOrder())) assertEquals("a", arrayOf("a", "B").minWithOrNull(STRING_CASE_INSENSITIVE_ORDER)) } @Test fun minWithOrNullInPrimitiveArrays() { expect(null, { intArrayOf().minWithOrNull(naturalOrder()) }) expect(1, { intArrayOf(1).minWithOrNull(naturalOrder()) }) expect(4, { intArrayOf(2, 3, 4).minWithOrNull(compareBy { it % 4 }) }) } @Test fun maxWithOrNull() { assertEquals(null, arrayOf().maxWithOrNull(naturalOrder())) assertEquals("B", arrayOf("a", "B").maxWithOrNull(STRING_CASE_INSENSITIVE_ORDER)) } @Test fun maxWithOrNullInPrimitiveArrays() { expect(null, { intArrayOf().maxWithOrNull(naturalOrder()) }) expect(1, { intArrayOf(1).maxWithOrNull(naturalOrder()) }) expect(-4, { intArrayOf(2, 3, -4).maxWithOrNull(compareBy { it * it }) }) } @Test fun minByOrNull() { expect(null, { arrayOf().minByOrNull { it } }) expect(1, { arrayOf(1).minByOrNull { it } }) expect(3, { arrayOf(2, 3).minByOrNull { -it } }) expect('a', { arrayOf('a', 'b').minByOrNull { "x$it" } }) expect("b", { arrayOf("b", "abc").minByOrNull { it.length } }) } @Test fun minByOrNullInPrimitiveArrays() { expect(null, { intArrayOf().minByOrNull { it } }) expect(1, { intArrayOf(1).minByOrNull { it } }) expect(3, { intArrayOf(2, 3).minByOrNull { -it } }) expect(2000000000000, { longArrayOf(3000000000000, 2000000000000).minByOrNull { it + 1 } }) expect(1, { byteArrayOf(1, 3, 2).minByOrNull { it * it } }) expect(3, { shortArrayOf(3, 2).minByOrNull { "a" } }) expect(2.0F, { floatArrayOf(3.0F, 2.0F).minByOrNull { it.toString() } }) expect(2.0, { doubleArrayOf(2.0, 3.0).minByOrNull { it * it } }) } @Test fun maxByOrNull() { expect(null, { arrayOf().maxByOrNull { it } }) expect(1, { arrayOf(1).maxByOrNull { it } }) expect(2, { arrayOf(2, 3).maxByOrNull { -it } }) expect('b', { arrayOf('a', 'b').maxByOrNull { "x$it" } }) expect("abc", { arrayOf("b", "abc").maxByOrNull { it.length } }) } @Test fun maxByOrNullInPrimitiveArrays() { expect(null, { intArrayOf().maxByOrNull { it } }) expect(1, { intArrayOf(1).maxByOrNull { it } }) expect(2, { intArrayOf(2, 3).maxByOrNull { -it } }) expect(3000000000000, { longArrayOf(3000000000000, 2000000000000).maxByOrNull { it + 1 } }) expect(3, { byteArrayOf(1, 3, 2).maxByOrNull { it * it } }) expect(3, { shortArrayOf(3, 2).maxByOrNull { "a" } }) expect(3.0F, { floatArrayOf(3.0F, 2.0F).maxByOrNull { it.toString() } }) expect(3.0, { doubleArrayOf(2.0, 3.0).maxByOrNull { it * it } }) } @Test fun minIndex() { val a = intArrayOf(1, 7, 9, -42, 54, 93) expect(3, { a.indices.minByOrNull { a[it] } }) } @Test fun maxIndex() { val a = intArrayOf(1, 7, 9, 239, 54, 93) expect(3, { a.indices.maxByOrNull { a[it] } }) } @Test fun minByEvaluateOnce() { var c = 0 expect(1, { arrayOf(5, 4, 3, 2, 1).minByOrNull { c++; it * it } }) assertEquals(5, c) } @Test fun maxByEvaluateOnce() { var c = 0 expect(5, { arrayOf(5, 4, 3, 2, 1).maxByOrNull { c++; it * it } }) assertEquals(5, c) } @Test fun sum() { expect(0) { arrayOf().sum() } expect(14) { arrayOf(2, 3, 9).sum() } expect(3.0) { arrayOf(1.0, 2.0).sum() } expect(200) { arrayOf(100, 100).sum() } expect(50000) { arrayOf(20000, 30000).sum() } expect(3000000000000) { arrayOf(1000000000000, 2000000000000).sum() } expect(3.0F) { arrayOf(1.0F, 2.0F).sum() } } @Test fun sumInPrimitiveArrays() { expect(0) { intArrayOf().sum() } expect(14) { intArrayOf(2, 3, 9).sum() } expect(3.0) { doubleArrayOf(1.0, 2.0).sum() } expect(200) { byteArrayOf(100, 100).sum() } expect(50000) { shortArrayOf(20000, 30000).sum() } expect(3000000000000) { longArrayOf(1000000000000, 2000000000000).sum() } expect(3.0F) { floatArrayOf(1.0F, 2.0F).sum() } } @Test fun average() { assertTrue() { arrayOf().average().isNaN() } expect(3.8) { arrayOf(1, 2, 5, 8, 3).average() } expect(2.1) { arrayOf(1.6, 2.6, 3.6, 0.6).average() } expect(100.0) { arrayOf(100, 100, 100, 100, 100, 100).average() } expect(0) { arrayOf(1, -1, 2, -2, 3, -3).average().toInt() } // TODO: Property based tests // for each arr with size 1 arr.average() == arr[0] // for each arr with size > 0 arr.average() = arr.sum().toDouble() / arr.size() } @Suppress("DEPRECATION") @Test fun indexOfInPrimitiveArrays() { expect(-1) { byteArrayOf(1, 2, 3).indexOf(0) } expect(0) { byteArrayOf(1, 2, 3).indexOf(1) } expect(1) { byteArrayOf(1, 2, 3).indexOf(2) } expect(2) { byteArrayOf(1, 2, 3).indexOf(3) } expect(-1) { shortArrayOf(1, 2, 3).indexOf(0) } expect(0) { shortArrayOf(1, 2, 3).indexOf(1) } expect(1) { shortArrayOf(1, 2, 3).indexOf(2) } expect(2) { shortArrayOf(1, 2, 3).indexOf(3) } expect(-1) { intArrayOf(1, 2, 3).indexOf(0) } expect(0) { intArrayOf(1, 2, 3).indexOf(1) } expect(1) { intArrayOf(1, 2, 3).indexOf(2) } expect(2) { intArrayOf(1, 2, 3).indexOf(3) } expect(-1) { longArrayOf(1, 2, 3).indexOf(0) } expect(0) { longArrayOf(1, 2, 3).indexOf(1) } expect(1) { longArrayOf(1, 2, 3).indexOf(2) } expect(2) { longArrayOf(1, 2, 3).indexOf(3) } expect(-1) { floatArrayOf(1.0f, 2.0f, 3.0f).indexOf(0f) } expect(0) { floatArrayOf(1.0f, 2.0f, 3.0f).indexOf(1.0f) } expect(1) { floatArrayOf(1.0f, 2.0f, 3.0f).indexOf(2.0f) } expect(2) { floatArrayOf(1.0f, 2.0f, 3.0f).indexOf(3.0f) } expect(-1) { doubleArrayOf(1.0, 2.0, 3.0).indexOf(0.0) } expect(0) { doubleArrayOf(1.0, 2.0, 3.0).indexOf(1.0) } expect(1) { doubleArrayOf(1.0, 2.0, 3.0).indexOf(2.0) } expect(2) { doubleArrayOf(1.0, 2.0, 3.0).indexOf(3.0) } expect(-1) { charArrayOf('a', 'b', 'c').indexOf('z') } expect(0) { charArrayOf('a', 'b', 'c').indexOf('a') } expect(1) { charArrayOf('a', 'b', 'c').indexOf('b') } expect(2) { charArrayOf('a', 'b', 'c').indexOf('c') } expect(0) { booleanArrayOf(true, false).indexOf(true) } expect(1) { booleanArrayOf(true, false).indexOf(false) } expect(-1) { booleanArrayOf(true).indexOf(false) } } @Test fun indexOf() { expect(-1) { arrayOf("cat", "dog", "bird").indexOf("mouse") } expect(0) { arrayOf("cat", "dog", "bird").indexOf("cat") } expect(1) { arrayOf("cat", "dog", "bird").indexOf("dog") } expect(2) { arrayOf("cat", "dog", "bird").indexOf("bird") } expect(0) { arrayOf(null, "dog", null).indexOf(null as String?)} expect(-1) { arrayOf("cat", "dog", "bird").indexOfFirst { it.contains("p") } } expect(0) { arrayOf("cat", "dog", "bird").indexOfFirst { it.startsWith('c') } } expect(1) { arrayOf("cat", "dog", "bird").indexOfFirst { it.startsWith('d') } } expect(2) { arrayOf("cat", "dog", "bird").indexOfFirst { it.endsWith('d') } } expect(-1) { sequenceOf("cat", "dog", "bird").indexOfFirst { it.contains("p") } } expect(0) { sequenceOf("cat", "dog", "bird").indexOfFirst { it.startsWith('c') } } expect(1) { sequenceOf("cat", "dog", "bird").indexOfFirst { it.startsWith('d') } } expect(2) { sequenceOf("cat", "dog", "bird").indexOfFirst { it.endsWith('d') } } } @Test fun lastIndexOf() { expect(-1) { arrayOf("cat", "dog", "bird").lastIndexOf("mouse") } expect(0) { arrayOf("cat", "dog", "bird").lastIndexOf("cat") } expect(1) { arrayOf("cat", "dog", "bird").lastIndexOf("dog") } expect(2) { arrayOf(null, "dog", null).lastIndexOf(null as String?)} expect(3) { arrayOf("cat", "dog", "bird", "dog").lastIndexOf("dog") } expect(-1) { arrayOf("cat", "dog", "bird").indexOfLast { it.contains("p") } } expect(0) { arrayOf("cat", "dog", "bird").indexOfLast { it.startsWith('c') } } expect(2) { arrayOf("cat", "dog", "cap", "bird").indexOfLast { it.startsWith('c') } } expect(2) { arrayOf("cat", "dog", "bird").indexOfLast { it.endsWith('d') } } expect(3) { arrayOf("cat", "dog", "bird", "red").indexOfLast { it.endsWith('d') } } expect(-1) { sequenceOf("cat", "dog", "bird").indexOfLast { it.contains("p") } } expect(0) { sequenceOf("cat", "dog", "bird").indexOfLast { it.startsWith('c') } } expect(2) { sequenceOf("cat", "dog", "cap", "bird").indexOfLast { it.startsWith('c') } } expect(2) { sequenceOf("cat", "dog", "bird").indexOfLast { it.endsWith('d') } } expect(3) { sequenceOf("cat", "dog", "bird", "red").indexOfLast { it.endsWith('d') } } } @Test fun isEmpty() { assertTrue(emptyArray().isEmpty()) assertFalse(arrayOf("").isEmpty()) assertTrue(intArrayOf().isEmpty()) assertFalse(intArrayOf(1).isEmpty()) assertTrue(byteArrayOf().isEmpty()) assertFalse(byteArrayOf(1).isEmpty()) assertTrue(shortArrayOf().isEmpty()) assertFalse(shortArrayOf(1).isEmpty()) assertTrue(longArrayOf().isEmpty()) assertFalse(longArrayOf(1).isEmpty()) assertTrue(charArrayOf().isEmpty()) assertFalse(charArrayOf('a').isEmpty()) assertTrue(floatArrayOf().isEmpty()) assertFalse(floatArrayOf(0.1F).isEmpty()) assertTrue(doubleArrayOf().isEmpty()) assertFalse(doubleArrayOf(0.1).isEmpty()) assertTrue(booleanArrayOf().isEmpty()) assertFalse(booleanArrayOf(false).isEmpty()) } @Test fun isNotEmpty() { assertFalse(intArrayOf().isNotEmpty()) assertTrue(intArrayOf(1).isNotEmpty()) } @Test fun plusInference() { val arrayOfArrays: Array> = arrayOf(arrayOf("s") as Array) val elementArray = arrayOf("a") as Array val arrayPlusElement: Array> = arrayOfArrays.plusElement(elementArray) assertEquals("a", arrayPlusElement[1][0]) // ambiguity // val arrayPlusArray: Array> = arrayOfArrays + arrayOfArrays val arrayOfStringArrays = arrayOf(arrayOf("s")) val arrayPlusArray = arrayOfStringArrays + arrayOfStringArrays assertEquals("s", arrayPlusArray[1][0]) } @Test fun plus() { assertEquals(listOf("1", "2", "3", "4"), listOf("1", "2") + arrayOf("3", "4")) assertArrayNotSameButEquals(arrayOf("1", "2", "3"), arrayOf("1", "2") + "3") assertArrayNotSameButEquals(arrayOf("1", "2", "3", "4"), arrayOf("1", "2") + arrayOf("3", "4")) assertArrayNotSameButEquals(arrayOf("1", "2", "3", "4"), arrayOf("1", "2") + listOf("3", "4")) assertArrayNotSameButEquals(intArrayOf(1, 2, 3), intArrayOf(1, 2) + 3) assertArrayNotSameButEquals(intArrayOf(1, 2, 3, 4), intArrayOf(1, 2) + listOf(3, 4)) assertArrayNotSameButEquals(intArrayOf(1, 2, 3, 4), intArrayOf(1, 2) + intArrayOf(3, 4)) } @Test fun plusVararg() { fun stringOnePlus(vararg a: String) = arrayOf("1") + a fun longOnePlus(vararg a: Long) = longArrayOf(1) + a fun intOnePlus(vararg a: Int) = intArrayOf(1) + a assertArrayNotSameButEquals(arrayOf("1", "2"), stringOnePlus("2"), "Array.plus") assertArrayNotSameButEquals(intArrayOf(1, 2), intOnePlus(2), "IntArray.plus") assertArrayNotSameButEquals(longArrayOf(1, 2), longOnePlus(2), "LongArray.plus") } @Test fun plusAssign() { // lets use a mutable variable var result = arrayOf("a") result += "foo" result += listOf("beer") result += arrayOf("cheese", "wine") assertArrayNotSameButEquals(arrayOf("a", "foo", "beer", "cheese", "wine"), result) } @Test fun first() { expect(1) { arrayOf(1, 2, 3).first() } expect(2) { arrayOf(1, 2, 3).first { it % 2 == 0 } } } @Test fun last() { expect(3) { arrayOf(1, 2, 3).last() } expect(2) { arrayOf(1, 2, 3).last { it % 2 == 0 } } } @Test fun random() { Array(100) { it }.let { array -> val tosses = List(10) { array.random() } assertTrue(tosses.distinct().size > 1, "Should be some distinct elements in $tosses") val seed = Random.nextInt() val random1 = Random(seed) val random2 = Random(seed) val tosses1 = List(10) { array.random(random1) } val tosses2 = List(10) { array.random(random2) } assertEquals(tosses1, tosses2) } arrayOf("x").let { singletonArray -> val tosses = List(10) { singletonArray.random() } assertEquals(singletonArray.toList(), tosses.distinct()) } assertFailsWith { emptyArray().random() } } @Test fun randomOrNull() { Array(100) { it }.let { array -> val tosses = List(10) { array.randomOrNull() } assertTrue(tosses.distinct().size > 1, "Should be some distinct elements in $tosses") val seed = Random.nextInt() val random1 = Random(seed) val random2 = Random(seed) val tosses1 = List(10) { array.randomOrNull(random1) } val tosses2 = List(10) { array.randomOrNull(random2) } assertEquals(tosses1, tosses2) } arrayOf("x").let { singletonArray -> val tosses = List(10) { singletonArray.randomOrNull() } assertEquals(singletonArray.toList(), tosses.distinct()) } assertNull(emptyArray().randomOrNull()) } @Test fun contains() { assertTrue(arrayOf("1", "2", "3", "4").contains("2")) assertTrue("3" in arrayOf("1", "2", "3", "4")) assertTrue("0" !in arrayOf("1", "2", "3", "4")) } @Test fun slice() { val iter: Iterable = listOf(3, 1, 2) assertEquals(listOf("B"), arrayOf("A", "B", "C").slice(1..1)) assertEquals(listOf('E', 'B', 'C'), arrayOf('A', 'B', 'C', 'E').slice(iter)) assertEquals(listOf(), arrayOf().slice(5..4)) assertEquals(listOf(), intArrayOf(1, 2, 3).slice(5..1)) assertEquals(listOf(2, 3, 9), intArrayOf(2, 3, 9, 2, 3, 9).slice(iter)) assertEquals(listOf(2.0, 3.0), doubleArrayOf(2.0, 3.0, 9.0).slice(0..1)) assertEquals(listOf(2f, 3f), floatArrayOf(2f, 3f, 9f).slice(0..1)) assertEquals(listOf(127, 100), byteArrayOf(50, 100, 127).slice(2 downTo 1)) assertEquals(listOf(200, 100), shortArrayOf(50, 100, 200).slice(2 downTo 1)) assertEquals(listOf(100L, 200L, 30L), longArrayOf(50L, 100L, 200L, 30L).slice(1..3)) assertEquals(listOf(true, false, true), booleanArrayOf(true, false, true, true).slice(iter)) for (range in listOf(-1 until 0, 0 until 2, 2..2)) { val bounds = "range: $range" val exClass = IndexOutOfBoundsException::class assertFailsWith(exClass, bounds) { arrayOf("x").slice(range) } assertFailsWith(exClass, bounds) { intArrayOf(1).slice(range) } assertFailsWith(exClass, bounds) { longArrayOf(1L).slice(range) } assertFailsWith(exClass, bounds) { charArrayOf('C').slice(range) } } } @Test fun sliceArray() { val coll: Collection = listOf(3, 1, 2) assertArrayNotSameButEquals(arrayOf("B"), arrayOf("A", "B", "C").sliceArray(1..1)) assertArrayNotSameButEquals(arrayOf("B"), (arrayOf("A", "B", "C") as Array).sliceArray(1..1)) assertArrayNotSameButEquals(arrayOf('E', 'B', 'C'), arrayOf('A', 'B', 'C', 'E').sliceArray(coll)) assertArrayNotSameButEquals(arrayOf(), arrayOf().sliceArray(5..4)) assertArrayNotSameButEquals(intArrayOf(), intArrayOf(1, 2, 3).sliceArray(5..1)) assertArrayNotSameButEquals(intArrayOf(2, 3, 9), intArrayOf(2, 3, 9, 2, 3, 9).sliceArray(coll)) assertArrayNotSameButEquals(doubleArrayOf(2.0, 3.0), doubleArrayOf(2.0, 3.0, 9.0).sliceArray(0..1)) assertArrayNotSameButEquals(floatArrayOf(2f, 3f), floatArrayOf(2f, 3f, 9f).sliceArray(0..1)) // assertArrayNotSameButEquals(byteArrayOf(127, 100), byteArrayOf(50, 100, 127).sliceArray(2 downTo 1)) // assertArrayNotSameButEquals(shortArrayOf(200, 100), shortArrayOf(50, 100, 200).sliceArray(2 downTo 1)) assertArrayNotSameButEquals(longArrayOf(100L, 200L, 30L), longArrayOf(50L, 100L, 200L, 30L).sliceArray(1..3)) assertArrayNotSameButEquals(booleanArrayOf(true, false, true), booleanArrayOf(true, false, true, true).sliceArray(coll)) for (range in listOf(-1 until 0, 0 until 2, 2..2)) { val bounds = "range: $range" val exClass = IndexOutOfBoundsException::class assertFailsWith(exClass, bounds) { arrayOf("x").sliceArray(range) } assertFailsWith(exClass, bounds) { intArrayOf(1).sliceArray(range) } assertFailsWith(exClass, bounds) { longArrayOf(1L).sliceArray(range) } assertFailsWith(exClass, bounds) { charArrayOf('C').sliceArray(range) } } } @Test fun iterators() { fun checkContract(array: T, toList: T.() -> List, iterator: T.() -> Iterator) = compare(array.toList().iterator(), array.iterator()) { iteratorBehavior() } checkContract(arrayOf("a", "b", "c"), { toList() }, { iterator() }) checkContract(intArrayOf(), { toList() }, { iterator() }) checkContract(intArrayOf(1, 2, 3), { toList() }, { iterator() }) checkContract(shortArrayOf(1, 2, 3), { toList() }, { iterator() }) checkContract(byteArrayOf(1, 2, 3), { toList() }, { iterator() }) checkContract(longArrayOf(1L, 2L, 3L), { toList() }, { iterator() }) checkContract(doubleArrayOf(2.0, 3.0, 9.0), { toList() }, { iterator() }) checkContract(floatArrayOf(2f, 3f, 9f), { toList() }, { iterator() }) checkContract(charArrayOf('a', 'b', 'c'), { toList() }, { iterator() }) checkContract(booleanArrayOf(true, false), { toList() }, { iterator() }) } @Test fun asIterable() { val arr1 = intArrayOf(1, 2, 3, 4, 5) val iter1 = arr1.asIterable() assertEquals(arr1.toList(), iter1.toList()) arr1[0] = 0 assertEquals(arr1.toList(), iter1.toList()) val arr2 = arrayOf("one", "two", "three") val iter2 = arr2.asIterable() assertEquals(arr2.toList(), iter2.toList()) arr2[0] = "" assertEquals(arr2.toList(), iter2.toList()) val arr3 = IntArray(0) val iter3 = arr3.asIterable() assertEquals(iter3.toList(), emptyList()) val arr4 = Array(0, { "$it" }) val iter4 = arr4.asIterable() assertEquals(iter4.toList(), emptyList()) } @Test fun asList() { compare(listOf(1, 2, 3), intArrayOf(1, 2, 3).asList()) { listBehavior() } compare(listOf(1, 2, 3), byteArrayOf(1, 2, 3).asList()) { listBehavior() } compare(listOf(true, false), booleanArrayOf(true, false).asList()) { listBehavior() } compare(listOf(1, 2, 3), arrayOf(1, 2, 3).asList()) { listBehavior() } compare(listOf("abc", "def"), arrayOf("abc", "def").asList()) { listBehavior() } val ints = intArrayOf(1, 5, 7) val intsAsList = ints.asList() assertEquals(5, intsAsList[1]) ints[1] = 10 assertEquals(10, intsAsList[1], "Should reflect changes in original array") } @Test fun asListInFloatingPrimitiveArrays() { fun testTotalOrder(expected: List, actual: List, element: T) = compare(expected, actual) { propertyEquals { contains(element) } propertyEquals { indexOf(element) } propertyEquals { lastIndexOf(element) } } testTotalOrder(listOf(Float.NaN), floatArrayOf(Float.NaN).asList(), Float.NaN) testTotalOrder(listOf(-0.0f), floatArrayOf(-0.0f).asList(), -0.0f) testTotalOrder(listOf(-0.0f), floatArrayOf(-0.0f).asList(), 0.0f) testTotalOrder(listOf(0.0f), floatArrayOf(0.0f).asList(), 0.0f) testTotalOrder(listOf(0.0f), floatArrayOf(0.0f).asList(), -0.0f) testTotalOrder(listOf(Double.NaN), doubleArrayOf(Double.NaN).asList(), Double.NaN) testTotalOrder(listOf(-0.0), doubleArrayOf(-0.0).asList(), -0.0) testTotalOrder(listOf(-0.0), doubleArrayOf(-0.0).asList(), 0.0) testTotalOrder(listOf(0.0), doubleArrayOf(0.0).asList(), 0.0) testTotalOrder(listOf(0.0), doubleArrayOf(0.0).asList(), -0.0) } @Test fun toPrimitiveArray() { val genericArray: Array = arrayOf(1, 2, 3) val primitiveArray: IntArray = genericArray.toIntArray() expect(3) { primitiveArray.size } assertEquals(genericArray.asList(), primitiveArray.asList()) val charList = listOf('a', 'b') val charArray: CharArray = charList.toCharArray() assertEquals(charList, charArray.asList()) } @Test fun toTypedArray() { val primitiveArray: LongArray = longArrayOf(1, 2, Long.MAX_VALUE) val genericArray: Array = primitiveArray.toTypedArray() expect(3) { genericArray.size } assertEquals(primitiveArray.asList(), genericArray.asList()) } @Test fun copyOf() { booleanArrayOf(true, false, true).let { assertArrayNotSameButEquals(it, it.copyOf()) } byteArrayOf(0, 1, 2, 3, 4, 5).let { assertArrayNotSameButEquals(it, it.copyOf()) } shortArrayOf(0, 1, 2, 3, 4, 5).let { assertArrayNotSameButEquals(it, it.copyOf()) } intArrayOf(0, 1, 2, 3, 4, 5).let { assertArrayNotSameButEquals(it, it.copyOf()) } longArrayOf(0, 1, 2, 3, 4, 5).let { assertArrayNotSameButEquals(it, it.copyOf()) } floatArrayOf(0F, 1F, 2F, 3F).let { assertArrayNotSameButEquals(it, it.copyOf()) } doubleArrayOf(0.0, 1.0, 2.0, 3.0, 4.0, 5.0).let { assertArrayNotSameButEquals(it, it.copyOf()) } charArrayOf('0', '1', '2', '3', '4', '5').let { assertArrayNotSameButEquals(it, it.copyOf()) } } @Test fun copyAndResize() { assertArrayNotSameButEquals(arrayOf("1", "2"), arrayOf("1", "2", "3").copyOf(2)) assertArrayNotSameButEquals(arrayOf("1", "2", null), arrayOf("1", "2").copyOf(3)) assertArrayNotSameButEquals(longArrayOf(1, 2), longArrayOf(1, 2, 3).copyOf(2)) assertArrayNotSameButEquals(longArrayOf(1, 2, 0), longArrayOf(1, 2).copyOf(3)) assertArrayNotSameButEquals(intArrayOf(1, 2), intArrayOf(1, 2, 3).copyOf(2)) assertArrayNotSameButEquals(intArrayOf(1, 2, 0), intArrayOf(1, 2).copyOf(3)) assertArrayNotSameButEquals(charArrayOf('A', 'B'), charArrayOf('A', 'B', 'C').copyOf(2)) assertArrayNotSameButEquals(charArrayOf('A', 'B', '\u0000'), charArrayOf('A', 'B').copyOf(3)) assertArrayNotSameButEquals(emptyArray(), arrayOf("x").copyOf(0)) assertArrayNotSameButEquals(intArrayOf(), intArrayOf(1).copyOf(0)) assertArrayNotSameButEquals(longArrayOf(), longArrayOf(1).copyOf(0)) assertArrayNotSameButEquals(charArrayOf(), charArrayOf('a').copyOf(0)) // RuntimeException is the most specific common of JVM and JS implementations assertFailsWith { arrayOf("x").copyOf(-1) } assertFailsWith { intArrayOf().copyOf(-1) } assertFailsWith { longArrayOf().copyOf(-1) } assertFailsWith { charArrayOf('c').copyOf(-1) } } @Test fun copyOfRange() { assertArrayNotSameButEquals(arrayOf("b", "c"), arrayOf("a", "b", "c").copyOfRange(1, 3)) assertArrayNotSameButEquals(booleanArrayOf(true, false, true), booleanArrayOf(true, false, true, true).copyOfRange(0, 3)) assertArrayNotSameButEquals(byteArrayOf(0, 1, 2), byteArrayOf(0, 1, 2, 3, 4, 5).copyOfRange(0, 3)) assertArrayNotSameButEquals(shortArrayOf(0, 1, 2), shortArrayOf(0, 1, 2, 3, 4, 5).copyOfRange(0, 3)) assertArrayNotSameButEquals(intArrayOf(0, 1, 2), intArrayOf(0, 1, 2, 3, 4, 5).copyOfRange(0, 3)) assertArrayNotSameButEquals(longArrayOf(0, 1, 2), longArrayOf(0, 1, 2, 3, 4, 5).copyOfRange(0, 3)) assertArrayNotSameButEquals(floatArrayOf(0F, 1F, 2F), floatArrayOf(0F, 1F, 2F, 3F, 4F, 5F).copyOfRange(0, 3)) assertArrayNotSameButEquals(doubleArrayOf(0.0, 1.0, 2.0), doubleArrayOf(0.0, 1.0, 2.0, 3.0, 4.0, 5.0).copyOfRange(0, 3)) assertArrayNotSameButEquals(charArrayOf('0', '1', '2'), charArrayOf('0', '1', '2', '3', '4', '5').copyOfRange(0, 3)) for (pos in 0..3) { assertArrayNotSameButEquals(emptyArray(), arrayOf("a", "b", "c").copyOfRange(pos, pos)) assertArrayNotSameButEquals(intArrayOf(), intArrayOf(1, 2, 3).copyOfRange(pos, pos)) assertArrayNotSameButEquals(charArrayOf(), charArrayOf('a', 'b', 'c').copyOfRange(pos, pos)) assertArrayNotSameButEquals(longArrayOf(), LongArray(3) { it.toLong() }.copyOfRange(pos, pos)) } for ((start, end) in listOf(-1 to 0, 0 to 2, 2 to 2, 1 to 0)) { val bounds = "start: $start, end: $end" val exClass = if (start > end) IllegalArgumentException::class else IndexOutOfBoundsException::class assertFailsWith(exClass, bounds) { arrayOf("x").copyOfRange(start, end) } assertFailsWith(exClass, bounds) { intArrayOf(1).copyOfRange(start, end) } assertFailsWith(exClass, bounds) { longArrayOf(1L).copyOfRange(start, end) } assertFailsWith(exClass, bounds) { charArrayOf('C').copyOfRange(start, end) } } } @Test fun copyRangeInto() { fun doTest( copyInto: T.(T, Int, Int, Int) -> T, assertTEquals: (T, T, String) -> Unit, toStringT: T.() -> String, dest: T, newValues: T, result1: T, result2: T, result3: T ) { newValues.copyInto(dest, 0, 1, 3) assertTypeEquals(result1, dest) assertTEquals(result1, dest, "Copying from newValues: ${result1.toStringT()}, ${dest.toStringT()}") dest.copyInto(dest, 0, 1, 3) assertTEquals(result2, dest, "Overlapping backward copy: ${result2.toStringT()}, ${dest.toStringT()}") dest.copyInto(dest, 1, 0, 2) assertTEquals(result3, dest, "Overlapping forward copy: ${result2.toStringT()}, ${dest.toStringT()}") for ((start, end) in listOf(-1 to 0, 0 to 4, 4 to 4, 1 to 0, 0 to -1)) { val bounds = "start: $start, end: $end" val ex = assertFails(bounds) { newValues.copyInto(dest, 0, start, end) } assertTrue(ex is IllegalArgumentException || ex is IndexOutOfBoundsException, "Unexpected exception type: $ex") } for (destIndex in listOf(-1, 2, 4)) { assertFailsWith("index: $destIndex") { newValues.copyInto(dest, destIndex, 0, 2) } } } doTest( Array::copyInto, { e, a, msg -> assertArrayNotSameButEquals(e, a, msg) }, Array<*>::contentToString, arrayOf("a", "b", "c"), arrayOf("e", "f", "g"), arrayOf("f", "g", "c"), arrayOf("g", "c", "c"), arrayOf("g", "g", "c") ) doTest( IntArray::copyInto, ::assertArrayNotSameButEquals, IntArray::contentToString, intArrayOf(1, 2, 3), intArrayOf(4, 5, 6), intArrayOf(5, 6, 3), intArrayOf(6, 3, 3), intArrayOf(6, 6, 3) ) doTest( LongArray::copyInto, ::assertArrayNotSameButEquals, LongArray::contentToString, longArrayOf(1, 2, 3), longArrayOf(4, 5, 6), longArrayOf(5, 6, 3), longArrayOf(6, 3, 3), longArrayOf(6, 6, 3) ) doTest( ByteArray::copyInto, ::assertArrayNotSameButEquals, ByteArray::contentToString, byteArrayOf(1, 2, 3), byteArrayOf(4, 5, 6), byteArrayOf(5, 6, 3), byteArrayOf(6, 3, 3), byteArrayOf(6, 6, 3) ) doTest( CharArray::copyInto, ::assertArrayNotSameButEquals, CharArray::contentToString, charArrayOf('a', 'b', 'c'), charArrayOf('e', 'f', 'g'), charArrayOf('f', 'g', 'c'), charArrayOf('g', 'c', 'c'), charArrayOf('g', 'g', 'c') ) doTest( UIntArray::copyInto, { e, a, msg -> assertTrue(e contentEquals a, msg) }, UIntArray::contentToString, uintArrayOf(1, 2, 3), uintArrayOf(4, 5, 6), uintArrayOf(5, 6, 3), uintArrayOf(6, 3, 3), uintArrayOf(6, 6, 3) ) doTest( ULongArray::copyInto, { e, a, msg -> assertTrue(e contentEquals a, msg) }, ULongArray::contentToString, ulongArrayOf(1, 2, 3), ulongArrayOf(4, 5, 6), ulongArrayOf(5, 6, 3), ulongArrayOf(6, 3, 3), ulongArrayOf(6, 6, 3) ) doTest( UByteArray::copyInto, { e, a, msg -> assertTrue(e contentEquals a, msg) }, UByteArray::contentToString, ubyteArrayOf(1, 2, 3), ubyteArrayOf(4, 5, 6), ubyteArrayOf(5, 6, 3), ubyteArrayOf(6, 3, 3), ubyteArrayOf(6, 6, 3) ) } @Test fun copyRangeIntoVarianceTest() { val sourceArr: Array = arrayOf(1, 2, 3) val targetAnyArr: Array = arrayOfNulls(3) val targetNumberArr: Array = Array(3) { 0.0 } val targetArrProjection: Array = targetNumberArr val c1 = sourceArr.copyInto(targetAnyArr) assertStaticTypeIs>(c1) val c2 = sourceArr.copyInto(targetNumberArr) assertStaticTypeIs>(c2) val c3 = sourceArr.copyInto(targetArrProjection) assertStaticTypeIs>(c3) } @Test fun reduceIndexed() { expect(-1) { intArrayOf(1, 2, 3).reduceIndexed { index, a, b -> index + a - b } } expect(-1.toLong()) { longArrayOf(1, 2, 3).reduceIndexed { index, a, b -> index + a - b } } expect(-1F) { floatArrayOf(1F, 2F, 3F).reduceIndexed { index, a, b -> index + a - b } } expect(-1.0) { doubleArrayOf(1.0, 2.0, 3.0).reduceIndexed { index, a, b -> index + a - b } } expect('2') { charArrayOf('1', '3', '2').reduceIndexed { index, a, b -> if (a > b && index == 1) a else b } } expect(true) { booleanArrayOf(true, true, false).reduceIndexed { index, a, b -> a && b || index == 2 } } expect(false) { booleanArrayOf(true, true).reduceIndexed { index, a, b -> a && b && index != 1 } } expect(1.toByte()) { byteArrayOf(3, 2, 1).reduceIndexed { index, a, b -> if (index != 2) (a - b).toByte() else a.toByte() } } expect(1.toShort()) { shortArrayOf(3, 2, 1).reduceIndexed { index, a, b -> if (index != 2) (a - b).toShort() else a.toShort() } } assertFailsWith { intArrayOf().reduceIndexed { index, a, b -> index + a + b } } } @Test fun reduceIndexedOrNull() { expect(-1) { intArrayOf(1, 2, 3).reduceIndexedOrNull { index, a, b -> index + a - b } } expect(-1.toLong()) { longArrayOf(1, 2, 3).reduceIndexedOrNull { index, a, b -> index + a - b } } expect(-1F) { floatArrayOf(1F, 2F, 3F).reduceIndexedOrNull { index, a, b -> index + a - b } } expect(-1.0) { doubleArrayOf(1.0, 2.0, 3.0).reduceIndexedOrNull { index, a, b -> index + a - b } } expect('2') { charArrayOf('1', '3', '2').reduceIndexedOrNull { index, a, b -> if (a > b && index == 1) a else b } } expect(true) { booleanArrayOf(true, true, false).reduceIndexedOrNull { index, a, b -> a && b || index == 2 } } expect(false) { booleanArrayOf(true, true).reduceIndexedOrNull { index, a, b -> a && b && index != 1 } } expect(1.toByte()) { byteArrayOf(3, 2, 1).reduceIndexedOrNull { index, a, b -> if (index != 2) (a - b).toByte() else a.toByte() } } expect(1.toShort()) { shortArrayOf(3, 2, 1).reduceIndexedOrNull { index, a, b -> if (index != 2) (a - b).toShort() else a.toShort() } } expect(null, { intArrayOf().reduceIndexedOrNull { index, a, b -> index + a + b } }) } @Test fun reduceRightIndexed() { expect(1) { intArrayOf(1, 2, 3).reduceRightIndexed { index, a, b -> index + a - b } } expect(1.toLong()) { longArrayOf(1, 2, 3).reduceRightIndexed { index, a, b -> index + a - b } } expect(1F) { floatArrayOf(1F, 2F, 3F).reduceRightIndexed { index, a, b -> index + a - b } } expect(1.0) { doubleArrayOf(1.0, 2.0, 3.0).reduceRightIndexed { index, a, b -> index + a - b } } expect('2') { charArrayOf('1', '3', '2').reduceRightIndexed { index, a, b -> if (a > b && index == 0) a else b } } expect(true) { booleanArrayOf(true, true, false).reduceRightIndexed { index, a, b -> a && b || index == 1 } } expect(false) { booleanArrayOf(true, true).reduceRightIndexed { index, a, b -> a && b && index != 0 } } expect(1.toByte()) { byteArrayOf(3, 2, 1).reduceRightIndexed { index, a, b -> if (index != 1) (a - b).toByte() else a.toByte() } } expect(1.toShort()) { shortArrayOf(3, 2, 1).reduceRightIndexed { index, a, b -> if (index != 1) (a - b).toShort() else a.toShort() } } assertFailsWith { intArrayOf().reduceRightIndexed { index, a, b -> index + a + b } } } @Test fun reduceRightIndexedOrNull() { expect(1) { intArrayOf(1, 2, 3).reduceRightIndexedOrNull { index, a, b -> index + a - b } } expect(1.toLong()) { longArrayOf(1, 2, 3).reduceRightIndexedOrNull { index, a, b -> index + a - b } } expect(1F) { floatArrayOf(1F, 2F, 3F).reduceRightIndexedOrNull { index, a, b -> index + a - b } } expect(1.0) { doubleArrayOf(1.0, 2.0, 3.0).reduceRightIndexedOrNull { index, a, b -> index + a - b } } expect('2') { charArrayOf('1', '3', '2').reduceRightIndexedOrNull { index, a, b -> if (a > b && index == 0) a else b } } expect(true) { booleanArrayOf(true, true, false).reduceRightIndexedOrNull { index, a, b -> a && b || index == 1 } } expect(false) { booleanArrayOf(true, true).reduceRightIndexedOrNull { index, a, b -> a && b && index != 0 } } expect(1.toByte()) { byteArrayOf(3, 2, 1).reduceRightIndexedOrNull { index, a, b -> if (index != 1) (a - b).toByte() else a.toByte() } } expect(1.toShort()) { shortArrayOf(3, 2, 1).reduceRightIndexedOrNull { index, a, b -> if (index != 1) (a - b).toShort() else a.toShort() } } expect(null, { intArrayOf().reduceRightIndexedOrNull { index, a, b -> index + a + b } }) } @Test fun reduce() { expect(-4) { intArrayOf(1, 2, 3).reduce { a, b -> a - b } } expect(-4.toLong()) { longArrayOf(1, 2, 3).reduce { a, b -> a - b } } expect(-4F) { floatArrayOf(1F, 2F, 3F).reduce { a, b -> a - b } } expect(-4.0) { doubleArrayOf(1.0, 2.0, 3.0).reduce { a, b -> a - b } } expect('3') { charArrayOf('1', '3', '2').reduce { a, b -> if (a > b) a else b } } expect(false) { booleanArrayOf(true, true, false).reduce { a, b -> a && b } } expect(true) { booleanArrayOf(true, true).reduce { a, b -> a && b } } expect(0.toByte()) { byteArrayOf(3, 2, 1).reduce { a, b -> (a - b).toByte() } } expect(0.toShort()) { shortArrayOf(3, 2, 1).reduce { a, b -> (a - b).toShort() } } assertFailsWith { intArrayOf().reduce { a, b -> a + b } } } @Test fun reduceOrNull() { expect(-4) { intArrayOf(1, 2, 3).reduceOrNull { a, b -> a - b } } expect(-4.toLong()) { longArrayOf(1, 2, 3).reduceOrNull { a, b -> a - b } } expect(-4F) { floatArrayOf(1F, 2F, 3F).reduceOrNull { a, b -> a - b } } expect(-4.0) { doubleArrayOf(1.0, 2.0, 3.0).reduceOrNull { a, b -> a - b } } expect('3') { charArrayOf('1', '3', '2').reduceOrNull { a, b -> if (a > b) a else b } } expect(false) { booleanArrayOf(true, true, false).reduceOrNull { a, b -> a && b } } expect(true) { booleanArrayOf(true, true).reduceOrNull { a, b -> a && b } } expect(0.toByte()) { byteArrayOf(3, 2, 1).reduceOrNull { a, b -> (a - b).toByte() } } expect(0.toShort()) { shortArrayOf(3, 2, 1).reduceOrNull { a, b -> (a - b).toShort() } } expect(null, { intArrayOf().reduceOrNull { a, b -> a + b } }) } @Test fun reduceRight() { expect(2) { intArrayOf(1, 2, 3).reduceRight { a, b -> a - b } } expect(2.toLong()) { longArrayOf(1, 2, 3).reduceRight { a, b -> a - b } } expect(2F) { floatArrayOf(1F, 2F, 3F).reduceRight { a, b -> a - b } } expect(2.0) { doubleArrayOf(1.0, 2.0, 3.0).reduceRight { a, b -> a - b } } expect('3') { charArrayOf('1', '3', '2').reduceRight { a, b -> if (a > b) a else b } } expect(false) { booleanArrayOf(true, true, false).reduceRight { a, b -> a && b } } expect(true) { booleanArrayOf(true, true).reduceRight { a, b -> a && b } } expect(2.toByte()) { byteArrayOf(1, 2, 3).reduceRight { a, b -> (a - b).toByte() } } expect(2.toShort()) { shortArrayOf(1, 2, 3).reduceRight { a, b -> (a - b).toShort() } } assertFailsWith { intArrayOf().reduceRight { a, b -> a + b } } } @Test fun reduceRightOrNull() { expect(2) { intArrayOf(1, 2, 3).reduceRightOrNull { a, b -> a - b } } expect(2.toLong()) { longArrayOf(1, 2, 3).reduceRightOrNull { a, b -> a - b } } expect(2F) { floatArrayOf(1F, 2F, 3F).reduceRightOrNull { a, b -> a - b } } expect(2.0) { doubleArrayOf(1.0, 2.0, 3.0).reduceRightOrNull { a, b -> a - b } } expect('3') { charArrayOf('1', '3', '2').reduceRightOrNull { a, b -> if (a > b) a else b } } expect(false) { booleanArrayOf(true, true, false).reduceRightOrNull { a, b -> a && b } } expect(true) { booleanArrayOf(true, true).reduceRightOrNull { a, b -> a && b } } expect(2.toByte()) { byteArrayOf(1, 2, 3).reduceRightOrNull { a, b -> (a - b).toByte() } } expect(2.toShort()) { shortArrayOf(1, 2, 3).reduceRightOrNull { a, b -> (a - b).toShort() } } expect(null, { intArrayOf().reduceRightOrNull { a, b -> a + b } }) } @Test fun scan() { for (size in 0 until 4) { val expected = listOf("", "0", "01", "012", "0123").take(size + 1) // Array assertEquals(expected, Array(size) { it }.scan("") { acc, e -> acc + e }) // Primitive Arrays assertEquals(expected, ByteArray(size) { it.toByte() }.scan("") { acc, e -> acc + e }) assertEquals(expected, CharArray(size) { '0' + it }.scan("") { acc, e -> acc + e }) assertEquals(expected, ShortArray(size) { it.toShort() }.scan("") { acc, e -> acc + e }) assertEquals(expected, IntArray(size) { it }.scan("") { acc, e -> acc + e }) assertEquals(expected, LongArray(size) { it.toLong() }.scan("") { acc, e -> acc + e }) assertEquals(expected, FloatArray(size) { it.toFloat() }.scan("") { acc, e -> acc + e.toInt() }) assertEquals(expected, DoubleArray(size) { it.toDouble() }.scan("") { acc, e -> acc + e.toInt() }) assertEquals( expected.map { it.map { c -> c.toInt() % 2 == 0 }.joinToString(separator = "") }, BooleanArray(size) { it % 2 == 0 }.scan("") { acc, e -> acc + e } ) } } @Test fun runningFold() { for (size in 0 until 4) { val expected = listOf("", "0", "01", "012", "0123").take(size + 1) // Array assertEquals(expected, Array(size) { it }.runningFold("") { acc, e -> acc + e }) // Primitive Arrays assertEquals(expected, ByteArray(size) { it.toByte() }.runningFold("") { acc, e -> acc + e }) assertEquals(expected, CharArray(size) { '0' + it }.runningFold("") { acc, e -> acc + e }) assertEquals(expected, ShortArray(size) { it.toShort() }.runningFold("") { acc, e -> acc + e }) assertEquals(expected, IntArray(size) { it }.runningFold("") { acc, e -> acc + e }) assertEquals(expected, LongArray(size) { it.toLong() }.runningFold("") { acc, e -> acc + e }) assertEquals(expected, FloatArray(size) { it.toFloat() }.runningFold("") { acc, e -> acc + e.toInt() }) assertEquals(expected, DoubleArray(size) { it.toDouble() }.runningFold("") { acc, e -> acc + e.toInt() }) assertEquals( expected.map { it.map { c -> c.toInt() % 2 == 0 }.joinToString(separator = "") }, BooleanArray(size) { it % 2 == 0 }.runningFold("") { acc, e -> acc + e } ) } } @Test fun scanIndexed() { for (size in 0 until 4) { val expected = listOf("+", "+[0: a]", "+[0: a][1: b]", "+[0: a][1: b][2: c]", "+[0: a][1: b][2: c][3: d]").take(size + 1) // Array assertEquals( expected, Array(size) { 'a' + it }.scanIndexed("+") { index, acc, e -> "$acc[$index: $e]" } ) // Primitive Arrays assertEquals( expected, ByteArray(size) { it.toByte() }.scanIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.toInt()}]" } ) assertEquals( expected, CharArray(size) { it.toChar() }.scanIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.toInt()}]" } ) assertEquals( expected, ShortArray(size) { it.toShort() }.scanIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.toInt()}]" } ) assertEquals( expected, IntArray(size) { it }.scanIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e}]" } ) assertEquals( expected, LongArray(size) { it.toLong() }.scanIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.toInt()}]" } ) assertEquals( expected, FloatArray(size) { it.toFloat() }.scanIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.toInt()}]" } ) assertEquals( expected, DoubleArray(size) { it.toDouble() }.scanIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.toInt()}]" } ) assertEquals( expected.map { it.map { c -> if (c.isAsciiLetter()) c.toInt() % 2 != 0 else c }.joinToString(separator = "") }, BooleanArray(size) { it % 2 == 0 }.scanIndexed("+") { index, acc, e -> "$acc[$index: $e]" } ) } } @Test fun runningFoldIndexed() { for (size in 0 until 4) { val expected = listOf("+", "+[0: a]", "+[0: a][1: b]", "+[0: a][1: b][2: c]", "+[0: a][1: b][2: c][3: d]").take(size + 1) // Array assertEquals( expected, Array(size) { 'a' + it }.runningFoldIndexed("+") { index, acc, e -> "$acc[$index: $e]" } ) // Primitive Arrays assertEquals( expected, ByteArray(size) { it.toByte() }.runningFoldIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.toInt()}]" } ) assertEquals( expected, CharArray(size) { it.toChar() }.runningFoldIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.toInt()}]" } ) assertEquals( expected, ShortArray(size) { it.toShort() }.runningFoldIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.toInt()}]" } ) assertEquals( expected, IntArray(size) { it }.runningFoldIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e}]" } ) assertEquals( expected, LongArray(size) { it.toLong() }.runningFoldIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.toInt()}]" } ) assertEquals( expected, FloatArray(size) { it.toFloat() }.runningFoldIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.toInt()}]" } ) assertEquals( expected, DoubleArray(size) { it.toDouble() }.runningFoldIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.toInt()}]" } ) assertEquals( expected.map { it.map { c -> if (c.isAsciiLetter()) c.toInt() % 2 != 0 else c }.joinToString(separator = "") }, BooleanArray(size) { it % 2 == 0 }.runningFoldIndexed("+") { index, acc, e -> "$acc[$index: $e]" } ) } } @Test fun runningReduce() { for (size in 0 until 4) { val expected = listOf(0, 1, 3, 6).take(size) // Array assertEquals( expected, Array(size) { it }.runningReduce { acc, e -> acc + e } ) // Primitive Arrays assertEquals( expected.map { it.toByte() }, ByteArray(size) { it.toByte() }.runningReduce { acc, e -> (acc + e).toByte() } ) assertEquals( expected.map { it.toChar() }, CharArray(size) { it.toChar() }.runningReduce { acc, e -> acc + e.toInt() } ) assertEquals( expected.map { it.toShort() }, ShortArray(size) { it.toShort() }.runningReduce { acc, e -> (acc + e).toShort() } ) assertEquals( expected, IntArray(size) { it }.runningReduce { acc, e -> acc + e } ) assertEquals( expected.map { it.toLong() }, LongArray(size) { it.toLong() }.runningReduce { acc, e -> acc + e } ) assertEquals( expected.map { it.toFloat() }, FloatArray(size) { it.toFloat() }.runningReduce { acc, e -> acc + e.toInt() } ) assertEquals( expected.map { it.toDouble() }, DoubleArray(size) { it.toDouble() }.runningReduce { acc, e -> acc + e.toInt() } ) assertEquals( expected.indices.map { it % 2 == 0 }, BooleanArray(size) { true }.runningReduce { acc, e -> acc != e } ) } } @Test fun runningReduceIndexed() { for (size in 0 until 4) { val expected = listOf(0, 1, 6, 27).take(size) // Array assertEquals( expected, Array(size) { it }.runningReduceIndexed { index, acc, e -> index * (acc + e) } ) // Primitive Arrays assertEquals( expected.map { it.toByte() }, ByteArray(size) { it.toByte() }.runningReduceIndexed { index, acc, e -> (index * (acc + e)).toByte() }) assertEquals( expected.map { it.toChar() }, CharArray(size) { it.toChar() }.runningReduceIndexed { index, acc, e -> (index * (acc.toInt() + e.toInt())).toChar() } ) assertEquals( expected.map { it.toShort() }, ShortArray(size) { it.toShort() }.runningReduceIndexed { index, acc, e -> (index * (acc + e)).toShort() } ) assertEquals( expected, IntArray(size) { it }.runningReduceIndexed { index, acc, e -> index * (acc + e) } ) assertEquals( expected.map { it.toLong() }, LongArray(size) { it.toLong() }.runningReduceIndexed { index, acc, e -> index * (acc + e) } ) assertEquals( expected.map { it.toFloat() }, FloatArray(size) { it.toFloat() }.runningReduceIndexed { index, acc, e -> index * (acc + e) } ) assertEquals( expected.map { it.toDouble() }, DoubleArray(size) { it.toDouble() }.runningReduceIndexed { index, acc, e -> index * (acc + e) } ) assertEquals( expected.indices.map { it % 2 == 0 }, BooleanArray(size) { true }.runningReduceIndexed { index, acc, e -> acc != e && index % 2 == 0 } ) } } @Test fun associateWith() { val items = arrayOf("Alice", "Bob", "Carol") val itemsWithTheirLength = items.associateWith { it.length } assertEquals(mapOf("Alice" to 5, "Bob" to 3, "Carol" to 5), itemsWithTheirLength) val updatedLength = items.copyOfRange(1, 3) .associateWithTo(itemsWithTheirLength.toMutableMap()) { name -> name.lowercase().count { it in "aeuio" } } assertEquals(mapOf("Alice" to 5, "Bob" to 1, "Carol" to 2), updatedLength) } @Test fun associateWithPrimitives() { assertEquals( mapOf(1 to "1", 2 to "2", 3 to "3"), intArrayOf(1, 2, 3).associateWith { it.toString() } ) assertEquals( mapOf(1.toByte() to "1", 2.toByte() to "2", 3.toByte() to "3"), byteArrayOf(1, 2, 3).associateWith { it.toString() } ) assertEquals( mapOf(1.toShort() to "1", 2.toShort() to "2", 3.toShort() to "3"), shortArrayOf(1, 2, 3).associateWith { it.toString() } ) assertEquals( mapOf(1L to "1", 2L to "2", 3L to "3"), longArrayOf(1, 2, 3).associateWith { it.toString() } ) assertEquals( mapOf(1f to "1", 2f to "2", 3f to "3"), floatArrayOf(1f, 2f, 3f).associateWith { if (it == 1f) "1" else if (it == 2f) "2" else "3" } ) assertEquals( mapOf(1.0 to "1", 2.0 to "2", 3.0 to "3"), doubleArrayOf(1.0, 2.0, 3.0).associateWith { if (it == 1.0) "1" else if (it == 2.0) "2" else "3" } ) assertEquals( mapOf('1' to "1", '2' to "2", '3' to "3"), charArrayOf('1', '2', '3').associateWith { it.toString() } ) assertEquals( mapOf(false to "false", true to "true"), booleanArrayOf(false, true).associateWith { it.toString() } ) } @Test fun associateWithToPrimitives() { val expected = mapOf(1 to "one", 2 to "two", 3 to "three") assertEquals( mapOf(1 to "one", 2 to "2", 3 to "3"), intArrayOf(2, 3).associateWithTo(expected.toMutableMap()) { it.toString() } ) assertEquals( mapOf(1.toByte() to "one", 2.toByte() to "2", 3.toByte() to "3"), byteArrayOf(2, 3).associateWithTo(expected.mapKeys { it.key.toByte() }.toMutableMap()) { it.toString() } ) assertEquals( mapOf(1.toShort() to "one", 2.toShort() to "2", 3.toShort() to "3"), shortArrayOf(2, 3).associateWithTo(expected.mapKeys { it.key.toShort() }.toMutableMap()) { it.toString() } ) assertEquals( mapOf(1L to "one", 2L to "2", 3L to "3"), longArrayOf(2, 3).associateWithTo(expected.mapKeys { it.key.toLong() }.toMutableMap()) { it.toString() } ) assertEquals( mapOf(1f to "one", 2f to "2", 3f to "3"), floatArrayOf(2f, 3f).associateWithTo(expected.mapKeys { it.key.toFloat() }.toMutableMap()) { if (it == 1f) "1" else if (it == 2f) "2" else "3" } ) assertEquals( mapOf(1.0 to "one", 2.0 to "2", 3.0 to "3"), doubleArrayOf(2.0, 3.0).associateWithTo(expected.mapKeys { it.key.toDouble() }.toMutableMap()) { if (it == 1.0) "1" else if (it == 2.0) "2" else "3" } ) assertEquals( mapOf('1' to "one", '2' to "2", '3' to "3"), charArrayOf('2', '3').associateWithTo(expected.mapKeys { '0' + it.key }.toMutableMap()) { it.toString() } ) assertEquals( mapOf(false to "three", true to "true"), booleanArrayOf(true, true).associateWithTo(expected.mapKeys { it.key % 2 == 0 }.toMutableMap()) { it.toString() } ) } @Test fun reverseInPlace() { fun doTest(build: Iterable.() -> TArray, reverse: TArray.() -> Unit, snapshot: TArray.() -> List) { val arrays = (0..4).map { n -> (1..n).build() } for (array in arrays) { val original = array.snapshot() array.reverse() val reversed = array.snapshot() assertEquals(original.asReversed(), reversed) } } doTest(build = { map {it}.toIntArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it.toLong()}.toLongArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it.toByte()}.toByteArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it.toShort()}.toShortArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it.toFloat()}.toFloatArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it.toDouble()}.toDoubleArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {'a' + it}.toCharArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it % 2 == 0}.toBooleanArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it.toString()}.toTypedArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it.toString()}.toTypedArray() as Array }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it.toUInt()}.toUIntArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it.toULong()}.toULongArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it.toUByte()}.toUByteArray() }, reverse = { reverse() }, snapshot = { toList() }) doTest(build = { map {it.toUShort()}.toUShortArray() }, reverse = { reverse() }, snapshot = { toList() }) } @Test fun reverseRangeInPlace() { fun doTest( build: Iterable.() -> TArray, reverse: TArray.(fromIndex: Int, toIndex: Int) -> Unit, snapshot: TArray.() -> List ) { val arrays = (0..7).map { n -> n to (0 until n).build() } for ((size, array) in arrays) { for (fromIndex in 0 until size) { for (toIndex in fromIndex..size) { val original = array.snapshot().toMutableList() array.reverse(fromIndex, toIndex) val reversed = array.snapshot() assertEquals(original.apply { subList(fromIndex, toIndex).reverse() }, reversed) } } assertFailsWith { array.reverse(-1, size) } assertFailsWith { array.reverse(0, size + 1) } assertFailsWith { array.reverse(0, -1) } } } doTest(build = { map {it.toString()}.toTypedArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toString()}.toTypedArray() as Array }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {it}.toIntArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toLong()}.toLongArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toByte()}.toByteArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toShort()}.toShortArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toFloat()}.toFloatArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toDouble()}.toDoubleArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {'a' + it}.toCharArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {it % 2 == 0}.toBooleanArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toUInt()}.toUIntArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toULong()}.toULongArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toUByte()}.toUByteArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toUShort()}.toUShortArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() }) } @Test fun reversed() { expect(listOf(3, 2, 1)) { intArrayOf(1, 2, 3).reversed() } expect(listOf(3, 2, 1)) { byteArrayOf(1, 2, 3).reversed() } expect(listOf(3, 2, 1)) { shortArrayOf(1, 2, 3).reversed() } expect(listOf(3, 2, 1)) { longArrayOf(1, 2, 3).reversed() } expect(listOf(3F, 2F, 1F)) { floatArrayOf(1F, 2F, 3F).reversed() } expect(listOf(3.0, 2.0, 1.0)) { doubleArrayOf(1.0, 2.0, 3.0).reversed() } expect(listOf('3', '2', '1')) { charArrayOf('1', '2', '3').reversed() } expect(listOf(false, false, true)) { booleanArrayOf(true, false, false).reversed() } expect(listOf("3", "2", "1")) { arrayOf("1", "2", "3").reversed() } } @Test fun reversedArray() { assertArrayNotSameButEquals(intArrayOf(3, 2, 1), intArrayOf(1, 2, 3).reversedArray()) assertArrayNotSameButEquals(byteArrayOf(3, 2, 1), byteArrayOf(1, 2, 3).reversedArray()) assertArrayNotSameButEquals(shortArrayOf(3, 2, 1), shortArrayOf(1, 2, 3).reversedArray()) assertArrayNotSameButEquals(longArrayOf(3, 2, 1), longArrayOf(1, 2, 3).reversedArray()) assertArrayNotSameButEquals(floatArrayOf(3F, 2F, 1F), floatArrayOf(1F, 2F, 3F).reversedArray()) assertArrayNotSameButEquals(doubleArrayOf(3.0, 2.0, 1.0), doubleArrayOf(1.0, 2.0, 3.0).reversedArray()) assertArrayNotSameButEquals(charArrayOf('3', '2', '1'), charArrayOf('1', '2', '3').reversedArray()) assertArrayNotSameButEquals(booleanArrayOf(false, false, true), booleanArrayOf(true, false, false).reversedArray()) assertArrayNotSameButEquals(arrayOf("3", "2", "1"), arrayOf("1", "2", "3").reversedArray()) assertArrayNotSameButEquals(arrayOf("3", "2", "1"), (arrayOf("1", "2", "3") as Array).reversedArray()) } @Test fun onEach() { var count = 0 val data = intArrayOf(1, 2, 3) val newData = data.onEach { count += it } assertEquals(6, count) assertSame(newData, data) var concat = "" val strings = arrayOf("a", "b", "c") val newStrings = strings.onEach { concat += it } assertEquals("abc", concat) assertSame(newStrings, strings) assertEquals(listOf("a", "b", "c"), mutableListOf().apply { arrayOf("a", "b", "c").onEach { add(it) } }) assertEquals(listOf(1, 2, 3), mutableListOf().apply { intArrayOf(1, 2, 3).onEach { add(it) } }) assertEquals(listOf(1, 2, 3), mutableListOf().apply { byteArrayOf(1, 2, 3).onEach { add(it) } }) assertEquals(listOf(1, 2, 3), mutableListOf().apply { shortArrayOf(1, 2, 3).onEach { add(it) } }) assertEquals(listOf(1, 2, 3), mutableListOf().apply { longArrayOf(1, 2, 3).onEach { add(it) } }) assertEquals(listOf(1f, 2f, 3f), mutableListOf().apply { floatArrayOf(1f, 2f, 3f).onEach { add(it) } }) assertEquals(listOf(1.0, 2.0, 3.0), mutableListOf().apply { doubleArrayOf(1.0, 2.0, 3.0).onEach { add(it) } }) assertEquals(listOf(true, false, false), mutableListOf().apply { booleanArrayOf(true, false, false).onEach { add(it) } }) assertEquals(listOf('1', '2', '3'), mutableListOf().apply { charArrayOf('1', '2', '3').onEach { add(it) } }) } @Test fun onEachIndexed() { assertEquals(listOf(1, 3, 5), mutableListOf().apply { intArrayOf(1, 2, 3).onEachIndexed { i, e -> add(i + e) } }) assertEquals(listOf(1, 3, 5), mutableListOf().apply { byteArrayOf(1, 2, 3).onEachIndexed { i, e -> add(i + e) } }) assertEquals(listOf(1, 3, 5), mutableListOf().apply { shortArrayOf(1, 2, 3).onEachIndexed { i, e -> add(i + e) } }) assertEquals(listOf(1, 3, 5), mutableListOf().apply { longArrayOf(1, 2, 3).onEachIndexed { i, e -> add(i + e) } }) assertEquals(listOf(1f, 3f, 5f), mutableListOf().apply { floatArrayOf(1f, 2f, 3f).onEachIndexed { i, e -> add(i + e) } }) assertEquals(listOf(1.0, 3.0, 5.0), mutableListOf().apply { doubleArrayOf(1.0, 2.0, 3.0).onEachIndexed { i, e -> add(i + e) } }) assertEquals(listOf(true, false, true), mutableListOf().apply { booleanArrayOf(true, false, false).onEachIndexed { i, e -> add(i % 2 == 0 || e) } }) assertEquals(listOf('1', '3', '5'), mutableListOf().apply { charArrayOf('1', '2', '3').onEachIndexed { i, e -> add(e + i) } }) assertEquals(listOf("a0", "b1", "c2"), mutableListOf().apply { arrayOf("a", "b", "c").onEachIndexed { i, e -> add(e + i) } }) val empty = arrayOf() assertSame(empty, empty.onEachIndexed { i, e -> fail("Should be unreachable: $i, $e") }) val nonEmpty = longArrayOf(1, 2, 3) assertSame(nonEmpty, nonEmpty.onEachIndexed { _, _ -> }) } @Test fun drop() { expect(listOf(1), { intArrayOf(1).drop(0) }) expect(listOf(), { intArrayOf().drop(1) }) expect(listOf(), { intArrayOf(1).drop(1) }) expect(listOf(3), { intArrayOf(2, 3).drop(1) }) expect(listOf(2000000000000), { longArrayOf(3000000000000, 2000000000000).drop(1) }) expect(listOf(3.toByte()), { byteArrayOf(2, 3).drop(1) }) expect(listOf(3.toShort()), { shortArrayOf(2, 3).drop(1) }) expect(listOf(3.0f), { floatArrayOf(2f, 3f).drop(1) }) expect(listOf(3.0), { doubleArrayOf(2.0, 3.0).drop(1) }) expect(listOf(false), { booleanArrayOf(true, false).drop(1) }) expect(listOf('b'), { charArrayOf('a', 'b').drop(1) }) expect(listOf("b"), { arrayOf("a", "b").drop(1) }) assertFails { listOf(2).drop(-1) } } @Test fun dropLast() { expect(listOf(), { intArrayOf().dropLast(1) }) expect(listOf(), { intArrayOf(1).dropLast(1) }) expect(listOf(1), { intArrayOf(1).dropLast(0) }) expect(listOf(2), { intArrayOf(2, 3).dropLast(1) }) expect(listOf(3000000000000), { longArrayOf(3000000000000, 2000000000000).dropLast(1) }) expect(listOf(2.toByte()), { byteArrayOf(2, 3).dropLast(1) }) expect(listOf(2.toShort()), { shortArrayOf(2, 3).dropLast(1) }) expect(listOf(2.0f), { floatArrayOf(2f, 3f).dropLast(1) }) expect(listOf(2.0), { doubleArrayOf(2.0, 3.0).dropLast(1) }) expect(listOf(true), { booleanArrayOf(true, false).dropLast(1) }) expect(listOf('a'), { charArrayOf('a', 'b').dropLast(1) }) expect(listOf("a"), { arrayOf("a", "b").dropLast(1) }) assertFails { listOf(1).dropLast(-1) } } @Test fun dropWhile() { expect(listOf(), { intArrayOf().dropWhile { it < 3 } }) expect(listOf(), { intArrayOf(1).dropWhile { it < 3 } }) expect(listOf(3, 1), { intArrayOf(2, 3, 1).dropWhile { it < 3 } }) expect(listOf(2000000000000), { longArrayOf(3000000000000, 2000000000000).dropWhile { it > 2000000000000 } }) expect(listOf(3.toByte(), 1.toByte()), { byteArrayOf(2, 3, 1).dropWhile { it < 3 } }) expect(listOf(3.toShort(), 1.toShort()), { shortArrayOf(2, 3, 1).dropWhile { it < 3 } }) expect(listOf(3f, 1f), { floatArrayOf(2f, 3f, 1f).dropWhile { it < 3 } }) expect(listOf(3.0, 1.0), { doubleArrayOf(2.0, 3.0, 1.0).dropWhile { it < 3 } }) expect(listOf(false, true), { booleanArrayOf(true, false, true).dropWhile { it } }) expect(listOf('b', 'a'), { charArrayOf('a', 'b', 'a').dropWhile { it < 'b' } }) expect(listOf("b", "a"), { arrayOf("a", "b", "a").dropWhile { it < "b" } }) } @Test fun dropLastWhile() { expect(listOf(), { intArrayOf().dropLastWhile { it < 3 } }) expect(listOf(), { intArrayOf(1).dropLastWhile { it < 3 } }) expect(listOf(2, 3), { intArrayOf(2, 3, 1).dropLastWhile { it < 3 } }) expect(listOf(3000000000000), { longArrayOf(3000000000000, 2000000000000).dropLastWhile { it < 3000000000000 } }) expect(listOf(2.toByte(), 3.toByte()), { byteArrayOf(2, 3, 1).dropLastWhile { it < 3 } }) expect(listOf(2.toShort(), 3.toShort()), { shortArrayOf(2, 3, 1).dropLastWhile { it < 3 } }) expect(listOf(2f, 3f), { floatArrayOf(2f, 3f, 1f).dropLastWhile { it < 3 } }) expect(listOf(2.0, 3.0), { doubleArrayOf(2.0, 3.0, 1.0).dropLastWhile { it < 3 } }) expect(listOf(true, false), { booleanArrayOf(true, false, true).dropLastWhile { it } }) expect(listOf('a', 'b'), { charArrayOf('a', 'b', 'a').dropLastWhile { it < 'b' } }) expect(listOf("a", "b"), { arrayOf("a", "b", "a").dropLastWhile { it < "b" } }) } @Test fun take() { expect(listOf(), { intArrayOf().take(1) }) expect(listOf(), { intArrayOf(1).take(0) }) expect(listOf(1), { intArrayOf(1).take(1) }) expect(listOf(2), { intArrayOf(2, 3).take(1) }) expect(listOf(3000000000000), { longArrayOf(3000000000000, 2000000000000).take(1) }) expect(listOf(2.toByte()), { byteArrayOf(2, 3).take(1) }) expect(listOf(2.toShort()), { shortArrayOf(2, 3).take(1) }) expect(listOf(2.0f), { floatArrayOf(2f, 3f).take(1) }) expect(listOf(2.0), { doubleArrayOf(2.0, 3.0).take(1) }) expect(listOf(true), { booleanArrayOf(true, false).take(1) }) expect(listOf('a'), { charArrayOf('a', 'b').take(1) }) expect(listOf("a"), { arrayOf("a", "b").take(1) }) assertFails { listOf(1).take(-1) } } @Test fun takeLast() { expect(listOf(), { intArrayOf().takeLast(1) }) expect(listOf(), { intArrayOf(1).takeLast(0) }) expect(listOf(1), { intArrayOf(1).takeLast(1) }) expect(listOf(3), { intArrayOf(2, 3).takeLast(1) }) expect(listOf(2000000000000), { longArrayOf(3000000000000, 2000000000000).takeLast(1) }) expect(listOf(3.toByte()), { byteArrayOf(2, 3).takeLast(1) }) expect(listOf(3.toShort()), { shortArrayOf(2, 3).takeLast(1) }) expect(listOf(3.0f), { floatArrayOf(2f, 3f).takeLast(1) }) expect(listOf(3.0), { doubleArrayOf(2.0, 3.0).takeLast(1) }) expect(listOf(false), { booleanArrayOf(true, false).takeLast(1) }) expect(listOf('b'), { charArrayOf('a', 'b').takeLast(1) }) expect(listOf("b"), { arrayOf("a", "b").takeLast(1) }) assertFails { listOf(1).takeLast(-1) } } @Test fun takeWhile() { expect(listOf(), { intArrayOf().takeWhile { it < 3 } }) expect(listOf(1), { intArrayOf(1).takeWhile { it < 3 } }) expect(listOf(2), { intArrayOf(2, 3, 1).takeWhile { it < 3 } }) expect(listOf(3000000000000), { longArrayOf(3000000000000, 2000000000000).takeWhile { it > 2000000000000 } }) expect(listOf(2.toByte()), { byteArrayOf(2, 3, 1).takeWhile { it < 3 } }) expect(listOf(2.toShort()), { shortArrayOf(2, 3, 1).takeWhile { it < 3 } }) expect(listOf(2f), { floatArrayOf(2f, 3f, 1f).takeWhile { it < 3 } }) expect(listOf(2.0), { doubleArrayOf(2.0, 3.0, 1.0).takeWhile { it < 3 } }) expect(listOf(true), { booleanArrayOf(true, false, true).takeWhile { it } }) expect(listOf('a'), { charArrayOf('a', 'c', 'b').takeWhile { it < 'c' } }) expect(listOf("a"), { arrayOf("a", "c", "b").takeWhile { it < "c" } }) } @Test fun takeLastWhile() { expect(listOf(), { intArrayOf().takeLastWhile { it < 3 } }) expect(listOf(1), { intArrayOf(1).takeLastWhile { it < 3 } }) expect(listOf(1), { intArrayOf(2, 3, 1).takeLastWhile { it < 3 } }) expect(listOf(2000000000000), { longArrayOf(3000000000000, 2000000000000).takeLastWhile { it < 3000000000000 } }) expect(listOf(1.toByte()), { byteArrayOf(2, 3, 1).takeLastWhile { it < 3 } }) expect(listOf(1.toShort()), { shortArrayOf(2, 3, 1).takeLastWhile { it < 3 } }) expect(listOf(1f), { floatArrayOf(2f, 3f, 1f).takeLastWhile { it < 3 } }) expect(listOf(1.0), { doubleArrayOf(2.0, 3.0, 1.0).takeLastWhile { it < 3 } }) expect(listOf(true), { booleanArrayOf(true, false, true).takeLastWhile { it } }) expect(listOf('b'), { charArrayOf('a', 'c', 'b').takeLastWhile { it < 'c' } }) expect(listOf("b"), { arrayOf("a", "c", "b").takeLastWhile { it < "c" } }) } @Test fun filter() { expect(listOf(), { intArrayOf().filter { it > 2 } }) expect(listOf(), { intArrayOf(1).filter { it > 2 } }) expect(listOf(3), { intArrayOf(2, 3).filter { it > 2 } }) expect(listOf(3000000000000), { longArrayOf(3000000000000, 2000000000000).filter { it > 2000000000000 } }) expect(listOf(3.toByte()), { byteArrayOf(2, 3).filter { it > 2 } }) expect(listOf(3.toShort()), { shortArrayOf(2, 3).filter { it > 2 } }) expect(listOf(3.0f), { floatArrayOf(2f, 3f).filter { it > 2 } }) expect(listOf(3.0), { doubleArrayOf(2.0, 3.0).filter { it > 2 } }) expect(listOf(true), { booleanArrayOf(true, false).filter { it } }) expect(listOf('b'), { charArrayOf('a', 'b').filter { it > 'a' } }) expect(listOf("b"), { arrayOf("a", "b").filter { it > "a" } }) } @Test fun filterIndexed() { expect(listOf(), { intArrayOf().filterIndexed { i, v -> i > v } }) expect(listOf(2, 5, 8), { intArrayOf(2, 4, 3, 5, 8).filterIndexed { index, value -> index % 2 == value % 2 } }) expect(listOf(2, 5, 8), { longArrayOf(2, 4, 3, 5, 8).filterIndexed { index, value -> index % 2 == (value % 2).toInt() } }) expect(listOf(2, 5, 8), { byteArrayOf(2, 4, 3, 5, 8).filterIndexed { index, value -> index % 2 == (value % 2).toInt() } }) expect(listOf('9', 'e', 'a'), { charArrayOf('9', 'e', 'd', 'a').filterIndexed { index, c -> c == 'a' || index < 2 }}) expect(listOf("a", "c", "d"), { arrayOf("a", "b", "c", "d").filterIndexed { index, s -> s == "a" || index >= 2 } }) } @Test fun filterNot() { expect(listOf(), { intArrayOf().filterNot { it > 2 } }) expect(listOf(1), { intArrayOf(1).filterNot { it > 2 } }) expect(listOf(2), { intArrayOf(2, 3).filterNot { it > 2 } }) expect(listOf(2000000000000), { longArrayOf(3000000000000, 2000000000000).filterNot { it > 2000000000000 } }) expect(listOf(2.toByte()), { byteArrayOf(2, 3).filterNot { it > 2 } }) expect(listOf(2.toShort()), { shortArrayOf(2, 3).filterNot { it > 2 } }) expect(listOf(2.0f), { floatArrayOf(2f, 3f).filterNot { it > 2 } }) expect(listOf(2.0), { doubleArrayOf(2.0, 3.0).filterNot { it > 2 } }) expect(listOf(false), { booleanArrayOf(true, false).filterNot { it } }) expect(listOf('a'), { charArrayOf('a', 'b').filterNot { it > 'a' } }) expect(listOf("a"), { arrayOf("a", "b").filterNot { it > "a" } }) } @Test fun filterNotNull() { expect(listOf("a"), { arrayOf("a", null).filterNotNull() }) } @Test fun map() { assertEquals(listOf(1, 2, 4), arrayOf("a", "bc", "test").map { it.length }) assertEquals(listOf('a', 'b', 'c'), intArrayOf(1, 2, 3).map { 'a' + it - 1 }) assertEquals(listOf(1, 2, 3), longArrayOf(1000, 2000, 3000).map { (it / 1000).toInt() }) assertEquals(listOf(1.0, 0.5, 0.4, 0.2, 0.1), doubleArrayOf(1.0, 2.0, 2.5, 5.0, 10.0).map { 1 / it }) } @Test fun mapIndexed() { assertEquals(listOf(1, 1, 2), arrayOf("a", "bc", "test").mapIndexed { index, s -> s.length - index }) assertEquals(listOf(0, 2, 2), intArrayOf(3, 2, 1).mapIndexed { index, i -> i * index }) assertEquals(listOf("0;20", "1;21", "2;22"), longArrayOf(20, 21, 22).mapIndexed { index, it -> "$index;$it" }) } @Test fun mapNotNull() { assertEquals(listOf(2, 3), arrayOf("", "bc", "def").mapNotNull { if (it.isEmpty()) null else it.length }) } @Test fun mapIndexedNotNull() { assertEquals(listOf(2), arrayOf("a", null, "test").mapIndexedNotNull { index, it -> it?.run { if (index != 0) length / index else null } }) } @Test fun flatMap() { val data = arrayOf(arrayOf(1, 2, 3), arrayOf(4, 5, 6)) val result1 = data.flatMap { it.asList() } val result2 = data.flatMap { it.asSequence() } val expected = (data[0] + data[1]).toList() assertEquals(expected, result1) assertEquals(expected, result2) } @Test fun flatMapIndexed() { val data = arrayOf(arrayOf(1, 2, 3), arrayOf(4, 5, 6)) val result1 = data.flatMapIndexed { index, arr -> arr.asList().subList(0, index + 1) } val result2 = data.flatMapIndexed { index, arr -> arr.asSequence().take(index + 1) } val expected = listOf(1, 4, 5) assertEquals(expected, result1) assertEquals(expected, result2) } @Test fun flattenArray() { val arr1: Array> = arrayOf(arrayOf(1, 2, 3), arrayOf(4, 5, 6)) val arr2: Array> = arr1 val arr3: Array> = arr1 @Suppress("UNCHECKED_CAST") val arr4: Array> = arr1 as Array> val expected = listOf(1, 2, 3, 4, 5, 6) assertEquals(expected, arr1.flatten()) assertEquals(expected, arr2.flatten()) assertEquals(expected, arr3.flatten()) assertEquals(expected, arr4.flatten()) } @Test fun asListPrimitives() { // Array of primitives val arr = intArrayOf(1, 2, 3, 4, 2, 5) val list = arr.asList() assertEquals(list, arr.toList()) assertTrue(2 in list) assertFalse(0 in list) assertTrue(list.containsAll(listOf(5, 4, 3))) assertFalse(list.containsAll(listOf(5, 6, 3))) expect(1) { list.indexOf(2) } expect(4) { list.lastIndexOf(2) } expect(-1) { list.indexOf(6) } assertEquals(list.subList(3, 5), listOf(4, 2)) val iter = list.listIterator(2) expect(2) { iter.nextIndex() } expect(1) { iter.previousIndex() } expect(3) { iter.next() iter.previous() iter.next() } arr[2] = 4 assertEquals(list, arr.toList()) assertEquals(IntArray(0).asList(), emptyList()) } @Test fun asListObjects() { val arr = arrayOf("a", "b", "c", "d", "b", "e") val list = arr.asList() assertEquals(list, arr.toList()) assertTrue("b" in list) assertFalse("z" in list) expect(1) { list.indexOf("b") } expect(4) { list.lastIndexOf("b") } expect(-1) { list.indexOf("x") } assertTrue(list.containsAll(listOf("e", "d", "c"))) assertFalse(list.containsAll(listOf("e", "x", "c"))) assertEquals(list.subList(3, 5), listOf("d", "b")) val iter = list.listIterator(2) expect(2) { iter.nextIndex() } expect(1) { iter.previousIndex() } expect("c") { iter.next() iter.previous() iter.next() } arr[2] = "xx" assertEquals(list, arr.toList()) assertEquals(Array(0, { "" }).asList(), emptyList()) } @Test fun sort() { val intArr = intArrayOf(5, 2, 1, 9, 80, Int.MIN_VALUE, Int.MAX_VALUE) intArr.sort() assertArrayNotSameButEquals(intArrayOf(Int.MIN_VALUE, 1, 2, 5, 9, 80, Int.MAX_VALUE), intArr) intArr.sortDescending() assertArrayNotSameButEquals(intArrayOf(Int.MAX_VALUE, 80, 9, 5, 2, 1, Int.MIN_VALUE), intArr) val longArr = longArrayOf(200, 2, 1, 4, 3, Long.MIN_VALUE, Long.MAX_VALUE) longArr.sort() assertArrayNotSameButEquals(longArrayOf(Long.MIN_VALUE, 1, 2, 3, 4, 200, Long.MAX_VALUE), longArr) longArr.sortDescending() assertArrayNotSameButEquals(longArrayOf(Long.MAX_VALUE, 200, 4, 3, 2, 1, Long.MIN_VALUE), longArr) val charArr = charArrayOf('d', 'c', 'E', 'a', '\u0000', '\uFFFF') charArr.sort() assertArrayNotSameButEquals(charArrayOf('\u0000', 'E', 'a', 'c', 'd', '\uFFFF'), charArr) charArr.sortDescending() assertArrayNotSameButEquals(charArrayOf('\uFFFF', 'd', 'c', 'a', 'E', '\u0000'), charArr) val strArr = arrayOf("9", "80", "all", "Foo") strArr.sort() assertArrayNotSameButEquals(arrayOf("80", "9", "Foo", "all"), strArr) strArr.sortDescending() assertArrayNotSameButEquals(arrayOf("all", "Foo", "9", "80"), strArr) } @Test fun sortRange() { fun > doTest( build: Iterable.() -> TArray, sort: TArray.(fromIndex: Int, toIndex: Int) -> Unit, snapshot: TArray.() -> List ) { val arrays = (0..7).map { n -> n to (-2 until n - 2).shuffled().build() } for ((size, array) in arrays) { for (fromIndex in 0 until size) { for (toIndex in fromIndex..size) { val original = array.snapshot().toMutableList() array.sort(fromIndex, toIndex) val sorted = array.snapshot() assertEquals(original.apply { subList(fromIndex, toIndex).sort() }, sorted) } } assertFailsWith { array.sort(-1, size) } assertFailsWith { array.sort(0, size + 1) } assertFailsWith { array.sort(0, -1) } } } testStableSort({ sort(1, 5) }, { sort(1, 5) }) testStableSort({ sort(0, 6) }, { sort(0, 6) }) doTest(build = { map {it.toString()}.toTypedArray() }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toString()}.toTypedArray() as Array }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) doTest(build = { map {it}.toIntArray() }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toLong()}.toLongArray() }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toByte()}.toByteArray() }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toShort()}.toShortArray() }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toFloat()}.toFloatArray() }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toDouble()}.toDoubleArray() }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) doTest(build = { map {'a' + it}.toCharArray() }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toUInt()}.toUIntArray() }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toULong()}.toULongArray() }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toUByte()}.toUByteArray() }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toUShort()}.toUShortArray() }, sort = { from, to -> sort(from, to) }, snapshot = { toList() }) } @Test fun sortDescendingRangeInPlace() { fun > doTest( build: Iterable.() -> TArray, sortDescending: TArray.(fromIndex: Int, toIndex: Int) -> Unit, snapshot: TArray.() -> List ) { val arrays = (0..7).map { n -> n to (-2 until n - 2).build() } for ((size, array) in arrays) { for (fromIndex in 0 until size) { for (toIndex in fromIndex..size) { val original = array.snapshot().toMutableList() array.sortDescending(fromIndex, toIndex) val reversed = array.snapshot() assertEquals(original.apply { subList(fromIndex, toIndex).sortDescending() }, reversed) } } assertFailsWith { array.sortDescending(-1, size) } assertFailsWith { array.sortDescending(0, size + 1) } assertFailsWith { array.sortDescending(1, 0) } } } testStableSort({ sortDescending(1, 5) }, { sortDescending(1, 5) }) testStableSort({ sortDescending(0, 6) }, { sortDescending(0, 6) }) doTest(build = { map {it.toString()}.toTypedArray() }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toString()}.toTypedArray() as Array }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) doTest(build = { map {it}.toIntArray() }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toLong()}.toLongArray() }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toByte()}.toByteArray() }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toShort()}.toShortArray() }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toFloat()}.toFloatArray() }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toDouble()}.toDoubleArray() }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) doTest(build = { map {'a' + it}.toCharArray() }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toUInt()}.toUIntArray() }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toULong()}.toULongArray() }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toUByte()}.toUByteArray() }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) doTest(build = { map {it.toUShort()}.toUShortArray() }, sortDescending = { from, to -> sortDescending(from, to) }, snapshot = { toList() }) } @Test fun sortedTests() { assertTrue(arrayOf().sorted().none()) assertEquals(listOf(1), arrayOf(1).sorted()) fun > arrayData(vararg values: T, toArray: Array.() -> A) = ArraySortedChecker(values.toArray(), naturalOrder()) with (arrayData("ac", "aD", "aba") { toList().toTypedArray() }) { checkSorted>({ sorted() }, { sortedDescending() }, { iterator() }) checkSorted>({ sortedArray() }, { sortedArrayDescending()}, { iterator() } ) } with (arrayData("ac", "aD", "aba") { toList().toTypedArray() as Array }) { checkSorted>({ sorted() }, { sortedDescending() }, { iterator() }) checkSorted>({ sortedArray() }, { sortedArrayDescending()}, { iterator() } ) } with (arrayData(3, 7, 1) { toIntArray() }) { checkSorted>( { sorted() }, { sortedDescending() }, { iterator() }) checkSorted( { sortedArray() }, { sortedArrayDescending() }, { iterator() }) } with (arrayData(1L, Long.MIN_VALUE, Long.MAX_VALUE) { toLongArray() }) { checkSorted>( { sorted() }, { sortedDescending() }, { iterator() }) checkSorted( { sortedArray() }, { sortedArrayDescending() }, { iterator() }) } with (arrayData('a', 'D', 'c') { toCharArray() }) { checkSorted>( { sorted() }, { sortedDescending() }, { iterator() }) checkSorted( { sortedArray() }, { sortedArrayDescending() }, { iterator() }) } with (arrayData(1.toByte(), Byte.MAX_VALUE, Byte.MIN_VALUE) { toByteArray() }) { checkSorted>( { sorted() }, { sortedDescending() }, { iterator() }) checkSorted( { sortedArray() }, { sortedArrayDescending() }, { iterator() }) } with(arrayData(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.MAX_VALUE, -Double.MAX_VALUE, 1.0, -1.0, Double.MIN_VALUE, -Double.MIN_VALUE, 0.0, -0.0, Double.NaN) { toDoubleArray() }) { checkSorted>( { sorted() }, { sortedDescending() }, { iterator() }) checkSorted( { sortedArray() }, { sortedArrayDescending() }, { iterator() }) } } @Test fun sortStable() { val keyRange = 'A'..'D' for (size in listOf(10, 100, 2000)) { val array = Array(size) { index -> Sortable(keyRange.random(), index) } array.sortedArray().assertStableSorted() array.sortedArrayDescending().assertStableSorted(descending = true) array.sort() array.assertStableSorted() array.sortDescending() array.assertStableSorted(descending = true) } } @Test fun sortByInPlace() { val data = arrayOf("aa" to 20, "ab" to 3, "aa" to 3) data.sortBy { it.second } assertArrayNotSameButEquals(arrayOf("ab" to 3, "aa" to 3, "aa" to 20), data) data.sortBy { it.first } assertArrayNotSameButEquals(arrayOf("aa" to 3, "aa" to 20, "ab" to 3), data) data.sortByDescending { (it.first + it.second).length } assertArrayNotSameButEquals(arrayOf("aa" to 20, "aa" to 3, "ab" to 3), data) } @Test fun sortedBy() { val values = arrayOf("ac", "aD", "aba") val indices = values.indices.toList().toIntArray() assertEquals(listOf(1, 2, 0), indices.sortedBy { values[it] }) } @Test fun sortByStable() { val keyRange = 'A'..'D' for (size in listOf(10, 100, 2000)) { val array = Array(size) { index -> Sortable(keyRange.random(), index) } array.sortedBy { it.key }.assertStableSorted() array.sortedByDescending { it.key }.assertStableSorted(descending = true) array.sortBy { it.key } array.assertStableSorted() array.sortByDescending { it.key } array.assertStableSorted(descending = true) } } @Test fun sortedNullableBy() { fun String.nullIfEmpty() = if (this.isEmpty()) null else this arrayOf(null, "").let { expect(listOf(null, "")) { it.sortedWith(nullsFirst(compareBy { it })) } expect(listOf("", null)) { it.sortedWith(nullsLast(compareByDescending { it })) } expect(listOf("", null)) { it.sortedWith(nullsLast(compareByDescending { it.nullIfEmpty() })) } } } @Test fun sortedWith() { val comparator = compareBy { it: Int -> it % 3 }.thenByDescending { it } fun arrayData(array: A, comparator: Comparator) = ArraySortedChecker(array, comparator) arrayData(intArrayOf(0, 1, 2, 3, 4, 5), comparator) .checkSorted>( { sortedWith(comparator) }, { sortedWith(comparator.reversed()) }, { iterator() }) arrayData(arrayOf(0, 1, 2, 3, 4, 5), comparator) .checkSorted>( { sortedArrayWith(comparator) }, { sortedArrayWith(comparator.reversed()) }, { iterator() }) // in-place val array = Array(6) { it } array.sortWith(comparator) array.iterator().assertSorted { a, b -> comparator.compare(a, b) <= 0 } testStableSort({ sortWith(reverseOrder()) }, { sortWith(reverseOrder()) }) testStableSort({ sortWith(naturalOrder()) }, { sortWith(naturalOrder()) }) val from = 2 val to = 5 val comp = comparator.reversed() val sorted = array.sliceArray(from until to).sortedWith(comp).toTypedArray() val expected = array.sliceArray(0 until from) + sorted + array.sliceArray(to until 6) array.sortWith(comp, from, to) assertTrue(expected contentEquals array) testStableSort({ sortWith(reverseOrder(), from, to) }, { sortWith(reverseOrder(), from, to) }) testStableSort({ sortWith(naturalOrder(), from, to) }, { sortWith(naturalOrder(), from, to) }) assertFailsWith { array.sortWith(comp, -1, 6) } assertFailsWith { array.sortWith(comp, 0, 7) } assertFailsWith { array.sortWith(comp, 0, -1) } } private data class Text(val data: String) : Comparable { override fun compareTo(other: Text): Int = data.compareTo(other.data) } private fun testStableSort(stableSort: Array.() -> Unit, intSort: Array.() -> Unit) { fun checkEqualsButNotSame(array: Array) { for (i in array.indices) { for (j in i + 1 until array.size) { assertEquals(array[i], array[j]) assertNotSame(array[i], array[j]) } } } val first = arrayOf(Text("first"), Text("first"), Text("first")) val second = arrayOf(Text("second"), Text("second")) val third = arrayOf(Text("third")) val text = arrayOf(first, second, third) text.forEach { array -> checkEqualsButNotSame(array) } val sorted = arrayOf(first[0], third[0], second[0], first[1], first[2], second[1]).apply(stableSort) val indexes = arrayOf(0, 2, 1, 0, 0, 1).apply(intSort) val counters = IntArray(3) for (i in 0 until 6) { val index = indexes[i] val expected = text[index][counters[index]++] val actual = sorted[i] assertSame(expected, actual) } } private inline fun testShuffle(array: T, shuffle: T.() -> Unit, toList: T.() -> List<*>) { val original = array.toList() array.shuffle() val shuffled = array.toList() assertNotEquals(original, shuffled) assertEquals(original.groupBy { it }, shuffled.groupBy { it }) } @Test fun shuffle() { val numbers = List(100) { it } testShuffle(numbers.map(Int::toInt).toIntArray(), { shuffle() }, { toList() }) testShuffle(numbers.map(Int::toLong).toLongArray(), { shuffle() }, { toList() }) testShuffle(numbers.map(Int::toByte).toByteArray(), { shuffle() }, { toList() }) testShuffle(numbers.map(Int::toShort).toShortArray(), { shuffle() }, { toList() }) testShuffle(numbers.map(Int::toFloat).toFloatArray(), { shuffle() }, { toList() }) testShuffle(numbers.map(Int::toDouble).toDoubleArray(), { shuffle() }, { toList() }) testShuffle(numbers.map(Int::toChar).toCharArray(), { shuffle() }, { toList() }) testShuffle(numbers.map { it % 2 == 0 }.toBooleanArray(), { shuffle() }, { toList() }) testShuffle(numbers.map(Int::toUInt).toUIntArray(), { shuffle() }, { toList() }) testShuffle(numbers.map(Int::toULong).toULongArray(), { shuffle() }, { toList() }) testShuffle(numbers.map(Int::toUByte).toUByteArray(), { shuffle() }, { toList() }) testShuffle(numbers.map(Int::toUShort).toUShortArray(), { shuffle() }, { toList() }) testShuffle(arrayOf(1, "x", null, Any(), 'a', 2u, 5.0), { shuffle() }, { toList() }) } private inline fun testShuffleR(array: T, shuffle: T.(Random) -> Unit, toList: T.() -> List<*>) { val seed = Random.nextInt() val original = array.toList() val originalShuffled = original.shuffled(Random(seed)) array.shuffle(Random(seed)) val shuffled = array.toList() assertNotEquals(original, shuffled) assertEquals(originalShuffled, shuffled) } @Test fun shufflePredictably() { val numbers = List(16) { it } testShuffleR(numbers.map(Int::toInt).toIntArray(), { r -> shuffle(r) }, { toList() }) testShuffleR(numbers.map(Int::toLong).toLongArray(), { r -> shuffle(r) }, { toList() }) testShuffleR(numbers.map(Int::toByte).toByteArray(), { r -> shuffle(r) }, { toList() }) testShuffleR(numbers.map(Int::toShort).toShortArray(), { r -> shuffle(r) }, { toList() }) testShuffleR(numbers.map(Int::toFloat).toFloatArray(), { r -> shuffle(r) }, { toList() }) testShuffleR(numbers.map(Int::toDouble).toDoubleArray(), { r -> shuffle(r) }, { toList() }) testShuffleR(numbers.map(Int::toChar).toCharArray(), { r -> shuffle(r) }, { toList() }) testShuffleR(numbers.map { it % 2 == 0 }.toBooleanArray(), { r -> shuffle(r) }, { toList() }) testShuffleR(numbers.map(Int::toUInt).toUIntArray(), { r -> shuffle(r) }, { toList() }) testShuffleR(numbers.map(Int::toULong).toULongArray(), { r -> shuffle(r) }, { toList() }) testShuffleR(numbers.map(Int::toUByte).toUByteArray(), { r -> shuffle(r) }, { toList() }) testShuffleR(numbers.map(Int::toUShort).toUShortArray(), { r -> shuffle(r) }, { toList() }) testShuffleR(arrayOf(1, "x", null, Any(), 'a', 2u, 5.0), { r -> shuffle(r) }, { toList() }) } @Test fun elementAt() { expect(0) { byteArrayOf(0, 1, 2).elementAt(0) } expect(1) { shortArrayOf(0, 1, 2).elementAt(1) } expect(2) { intArrayOf(0, 1, 2).elementAt(2) } assertFailsWith { arrayOf().elementAt(0) } assertFailsWith { longArrayOf(0, 1, 2).elementAt(-1) } } @Test fun fill() { fun testFailures(array: A, fill: A.(E, Int, Int) -> Unit, element: E, arraySize: Int) { assertFailsWith { array.fill(element, -1, arraySize) } assertFailsWith { array.fill(element, 0, arraySize + 1) } assertFailsWith { array.fill(element, 1, 0) } } testFailures(BooleanArray(5) { it % 2 == 0 }, BooleanArray::fill, true, 5) testFailures(ByteArray(5) { it.toByte() }, ByteArray::fill, 0.toByte(), 5) testFailures(CharArray(5) { it.toChar() }, CharArray::fill, 0.toChar(), 5) testFailures(FloatArray(5) { it.toFloat() }, FloatArray::fill, 0.0f, 5) testFailures(DoubleArray(5) { it.toDouble() }, DoubleArray::fill, 0.0, 5) testFailures(ShortArray(5) { it.toShort() }, ShortArray::fill, 0.toShort(), 5) testFailures(IntArray(5) { it }, IntArray::fill, 0, 5) testFailures(LongArray(5) { it.toLong() }, LongArray::fill, 0L, 5) testFailures(Array(5) { it.toString() }, Array::fill, "0", 5) fun test( array: IntArray, fill: A.(E, Int, Int) -> Unit, operations: List>, arrayTransform: IntArray.() -> A, elementTransform: Int.() -> E, contentEquals: A.(A) -> Boolean ) { for (o in operations) { val result = array.arrayTransform() result.fill(o.element.elementTransform(), o.fromIndex, o.toIndex) assertTrue(o.expectedResult.arrayTransform().contentEquals(result)) } } val array = IntArray(5) { it } val operations = listOf( OperationOnRange(5, 1, 4, intArrayOf(0, 5, 5, 5, 4)), OperationOnRange(1, 0, 5, intArrayOf(1, 1, 1, 1, 1)), OperationOnRange(2, 0, 3, intArrayOf(2, 2, 2, 3, 4)), OperationOnRange(3, 2, 5, intArrayOf(0, 1, 3, 3, 3)) ) test(array, BooleanArray::fill, operations, IntArray::toBooleanArray, { this % 2 == 0 }, BooleanArray::contentEquals) test(array, ByteArray::fill, operations, IntArray::toByteArray, Int::toByte, ByteArray::contentEquals) test(array, CharArray::fill, operations, IntArray::toCharArray, Int::toChar, CharArray::contentEquals) test(array, FloatArray::fill, operations, IntArray::toFloatArray, Int::toFloat, FloatArray::contentEquals) test(array, DoubleArray::fill, operations, IntArray::toDoubleArray, Int::toDouble, DoubleArray::contentEquals) test(array, ShortArray::fill, operations, IntArray::toShortArray, Int::toShort, ShortArray::contentEquals) test(array, IntArray::fill, operations, IntArray::copyOf, { this }, IntArray::contentEquals) test(array, LongArray::fill, operations, IntArray::toLongArray, Int::toLong, LongArray::contentEquals) test(array, Array::fill, operations, IntArray::toStringArray, Int::toString, { contentEquals(it) }) } private class OperationOnRange( val element: E, val fromIndex: Int, val toIndex: Int, val expectedResult: R ) } private fun IntArray.toBooleanArray() = BooleanArray(size) { get(it) % 2 == 0 } private fun IntArray.toByteArray() = ByteArray(size) { get(it).toByte() } private fun IntArray.toCharArray() = CharArray(size) { get(it).toChar() } private fun IntArray.toFloatArray() = FloatArray(size) { get(it).toFloat() } private fun IntArray.toDoubleArray() = DoubleArray(size) { get(it).toDouble() } private fun IntArray.toShortArray() = ShortArray(size) { get(it).toShort() } private fun IntArray.toLongArray() = LongArray(size) { get(it).toLong() } private fun IntArray.toStringArray() = Array(size) { get(it).toString() } fun > Array>.assertStableSorted(descending: Boolean = false) = iterator().assertStableSorted(descending = descending) private class ArraySortedChecker(val array: A, val comparator: Comparator) { public fun checkSorted(sorted: A.() -> R, sortedDescending: A.() -> R, iterator: R.() -> Iterator) { array.sorted().iterator().assertSorted { a, b -> comparator.compare(a, b) <= 0 } array.sortedDescending().iterator().assertSorted { a, b -> comparator.compare(a, b) >= 0 } } }