blob: 944583dddb9b2ea7ba7656a38fd7b9a682d718c6 [file] [log] [blame]
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package test.collections
import test.TestPlatform
import test.assertStaticTypeIs
import test.assertTypeEquals
import test.collections.behaviors.*
import test.comparisons.STRING_CASE_INSENSITIVE_ORDER
import test.testExceptOn
import test.text.isAsciiLetter
import kotlin.test.*
import kotlin.random.Random
fun <T> assertArrayNotSameButEquals(expected: Array<out T>, actual: Array<out T>, 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<String>? = null
val y: Array<out String>? = null
val xArray = x.orEmpty()
val yArray = y.orEmpty()
expect(0) { xArray.size }
expect(0) { yArray.size }
}
@Test fun orEmptyNotNull() {
val x: Array<String>? = 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<String>()
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<String>(5, { "$it" })
assertEquals(4, arr2.lastIndex)
assertEquals("4", arr2[arr2.lastIndex])
}
@Test fun arrayInit() {
val arr = Array(2) { it.toString() }
assertEquals(2, arr.size)
assertEquals(0.toString(), arr[0])
assertEquals(1.toString(), arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { Array(-1) { it.toString() } }
}
}
@Test fun byteArray() {
val arr = ByteArray(2)
val expected: Byte = 0
assertEquals(arr.size, 2)
assertEquals(expected, arr[0])
assertEquals(expected, arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { ByteArray(-1) }
}
}
@Test fun byteArrayInit() {
val arr = ByteArray(2) { it.toByte() }
assertEquals(2, arr.size)
assertEquals(0.toByte(), arr[0])
assertEquals(1.toByte(), arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { ByteArray(-1) { it.toByte() } }
}
}
@Test fun shortArray() {
val arr = ShortArray(2)
val expected: Short = 0
assertEquals(arr.size, 2)
assertEquals(expected, arr[0])
assertEquals(expected, arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { ShortArray(-1) }
}
}
@Test fun shortArrayInit() {
val arr = ShortArray(2) { it.toShort() }
assertEquals(2, arr.size)
assertEquals(0.toShort(), arr[0])
assertEquals(1.toShort(), arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { ShortArray(-1) { it.toShort() } }
}
}
@Test fun intArray() {
val arr = IntArray(2)
assertEquals(arr.size, 2)
assertEquals(0, arr[0])
assertEquals(0, arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { IntArray(-1) }
}
}
@Test fun intArrayInit() {
val arr = IntArray(2) { it.toInt() }
assertEquals(2, arr.size)
assertEquals(0.toInt(), arr[0])
assertEquals(1.toInt(), arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { IntArray(-1) { it.toInt() } }
}
}
@Test fun longArray() {
val arr = LongArray(2)
val expected: Long = 0
assertEquals(arr.size, 2)
assertEquals(expected, arr[0])
assertEquals(expected, arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { LongArray(-1) }
}
}
@Test fun longArrayInit() {
val arr = LongArray(2) { it.toLong() }
assertEquals(2, arr.size)
assertEquals(0.toLong(), arr[0])
assertEquals(1.toLong(), arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { LongArray(-1) { it.toLong() } }
}
}
@Test fun floatArray() {
val arr = FloatArray(2)
val expected: Float = 0.0F
assertEquals(arr.size, 2)
assertEquals(expected, arr[0])
assertEquals(expected, arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { FloatArray(-1) }
}
}
@Test fun floatArrayInit() {
val arr = FloatArray(2) { it.toFloat() }
assertEquals(2, arr.size)
assertEquals(0.toFloat(), arr[0])
assertEquals(1.toFloat(), arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { FloatArray(-1) { it.toFloat() } }
}
}
@Test fun doubleArray() {
val arr = DoubleArray(2)
assertEquals(arr.size, 2)
assertEquals(0.0, arr[0])
assertEquals(0.0, arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { DoubleArray(-1) }
}
}
@Test fun doubleArrayInit() {
val arr = DoubleArray(2) { it.toDouble() }
assertEquals(2, arr.size)
assertEquals(0.toDouble(), arr[0])
assertEquals(1.toDouble(), arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { DoubleArray(-1) { it.toDouble() } }
}
}
@Test fun charArray() {
val arr = CharArray(2)
val expected: Char = '\u0000'
assertEquals(arr.size, 2)
assertEquals(expected, arr[0])
assertEquals(expected, arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { CharArray(-1) }
}
}
@Test fun charArrayInit() {
val arr = CharArray(2) { 'a' + it }
assertEquals(2, arr.size)
assertEquals('a', arr[0])
assertEquals('b', arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { CharArray(-1) { 'a' + it } }
}
}
@Test fun booleanArray() {
val arr = BooleanArray(2)
assertEquals(arr.size, 2)
assertEquals(false, arr[0])
assertEquals(false, arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { BooleanArray(-1) }
}
}
@Test fun booleanArrayInit() {
val arr = BooleanArray(2) { it % 2 == 0 }
assertEquals(2, arr.size)
assertEquals(true, arr[0])
assertEquals(false, arr[1])
testExceptOn(TestPlatform.Js) {
assertFailsWith<RuntimeException> { BooleanArray(-1) { it % 2 == 0 } }
}
}
@Test fun contentEquals() {
fun <T> 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<String>() as Array<String>?) 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<String>?) contentDeepEquals null)
assertTrue(null contentDeepEquals (null as Array<String>?))
assertFalse(arrayOf("") contentDeepEquals null)
assertFalse(null contentDeepEquals arrayOf<Any?>(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<Int>?).contentDeepToString())
}
@Test fun contentDeepToStringNoRecursion() {
// a[b[a, b]]
val b = arrayOfNulls<Any>(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<Any>?).contentDeepHashCode())
}
@Test fun joinToString() {
val text = arrayOf("foo", "bar").joinToString("-", "<", ">")
assertEquals("<foo-bar>", 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<Int>().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<Int>().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<Int>().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<Int>().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<Int>().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<Int>().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<Int>().sum() }
expect(14) { arrayOf(2, 3, 9).sum() }
expect(3.0) { arrayOf(1.0, 2.0).sum() }
expect(200) { arrayOf<Byte>(100, 100).sum() }
expect(50000) { arrayOf<Short>(20000, 30000).sum() }
expect(3000000000000) { arrayOf<Long>(1000000000000, 2000000000000).sum() }
expect(3.0F) { arrayOf<Float>(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<Int>().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<Byte>(100, 100, 100, 100, 100, 100).average() }
expect(0) { arrayOf<Short>(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()
}
@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<String>().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<Array<out Any>> = arrayOf(arrayOf<Any>("s") as Array<out Any>)
val elementArray = arrayOf<Any>("a") as Array<out Any>
val arrayPlusElement: Array<Array<out Any>> = arrayOfArrays.plusElement(elementArray)
assertEquals("a", arrayPlusElement[1][0])
// ambiguity
// val arrayPlusArray: Array<Array<out Any>> = 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<NoSuchElementException> { emptyArray<Any>().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<Any>().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<Int> = 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<Int>(), arrayOf<Int>().slice(5..4))
assertEquals(listOf<Int>(), 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<Byte>(127, 100), byteArrayOf(50, 100, 127).slice(2 downTo 1))
assertEquals(listOf<Short>(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<Int> = listOf(3, 1, 2)
assertArrayNotSameButEquals(arrayOf("B"), arrayOf("A", "B", "C").sliceArray(1..1))
assertArrayNotSameButEquals(arrayOf("B"), (arrayOf("A", "B", "C") as Array<out String>).sliceArray(1..1))
assertArrayNotSameButEquals(arrayOf('E', 'B', 'C'), arrayOf('A', 'B', 'C', 'E').sliceArray(coll))
assertArrayNotSameButEquals(arrayOf<Int>(), arrayOf<Int>().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 <T, E> checkContract(array: T, toList: T.() -> List<E>, iterator: T.() -> Iterator<E>) =
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<Int>())
val arr4 = Array(0, { "$it" })
val iter4 = arr4.asIterable()
assertEquals(iter4.toList(), emptyList<String>())
}
@Test fun asList() {
compare(listOf(1, 2, 3), intArrayOf(1, 2, 3).asList()) { listBehavior() }
compare(listOf<Byte>(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 <T> testTotalOrder(expected: List<T>, actual: List<T>, 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<Int> = 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<Long> = 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<RuntimeException> { arrayOf("x").copyOf(-1) }
assertFailsWith<RuntimeException> { intArrayOf().copyOf(-1) }
assertFailsWith<RuntimeException> { longArrayOf().copyOf(-1) }
assertFailsWith<RuntimeException> { 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 <T> 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<IndexOutOfBoundsException>("index: $destIndex") { newValues.copyInto(dest, destIndex, 0, 2) }
}
}
doTest(
Array<String>::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(1u, 2u, 3u), uintArrayOf(4u, 5u, 6u),
uintArrayOf(5u, 6u, 3u), uintArrayOf(6u, 3u, 3u), uintArrayOf(6u, 6u, 3u)
)
doTest(
ULongArray::copyInto, { e, a, msg -> assertTrue(e contentEquals a, msg) }, ULongArray::contentToString,
ulongArrayOf(1u, 2u, 3u), ulongArrayOf(4u, 5u, 6u),
ulongArrayOf(5u, 6u, 3u), ulongArrayOf(6u, 3u, 3u), ulongArrayOf(6u, 6u, 3u)
)
doTest(
UByteArray::copyInto, { e, a, msg -> assertTrue(e contentEquals a, msg) }, UByteArray::contentToString,
ubyteArrayOf(1u, 2u, 3u), ubyteArrayOf(4u, 5u, 6u),
ubyteArrayOf(5u, 6u, 3u), ubyteArrayOf(6u, 3u, 3u), ubyteArrayOf(6u, 6u, 3u)
)
}
@Test fun copyRangeIntoVarianceTest() {
val sourceArr: Array<out Int> = arrayOf(1, 2, 3)
val targetAnyArr: Array<Any?> = arrayOfNulls<Any?>(3)
val targetNumberArr: Array<Number> = Array<Number>(3) { 0.0 }
val targetArrProjection: Array<in Number> = targetNumberArr
val c1 = sourceArr.copyInto(targetAnyArr)
assertStaticTypeIs<Array<Any?>>(c1)
val c2 = sourceArr.copyInto(targetNumberArr)
assertStaticTypeIs<Array<Number>>(c2)
val c3 = sourceArr.copyInto(targetArrProjection)
assertStaticTypeIs<Array<in Number>>(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<UnsupportedOperationException> {
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<UnsupportedOperationException> {
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<UnsupportedOperationException> {
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<UnsupportedOperationException> {
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<T>
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.code % 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<T>
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.code % 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<T>
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) { Char(it) }.scanIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.code}]" }
)
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.code % 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<T>
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) { Char(it) }.runningFoldIndexed("+") { index, acc, e -> "$acc[$index: ${'a' + e.code}]" }
)
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.code % 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<T>
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 { Char(it) },
CharArray(size) { Char(it) }.runningReduce { acc, e -> acc + e.code }
)
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<T>
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 { Char(it) },
CharArray(size) { Char(it) }.runningReduceIndexed { index, acc, e -> (index * (acc.code + e.code)).let(::Char) }
)
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 <TArray, T> doTest(build: Iterable<Int>.() -> TArray, reverse: TArray.() -> Unit, snapshot: TArray.() -> List<T>) {
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() })
@Suppress("USELESS_CAST")
doTest(build = { map {it.toString()}.toTypedArray() as Array<out String> }, 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 <TArray, T> doTest(
build: Iterable<Int>.() -> TArray,
reverse: TArray.(fromIndex: Int, toIndex: Int) -> Unit,
snapshot: TArray.() -> List<T>
) {
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<IndexOutOfBoundsException> { array.reverse(-1, size) }
assertFailsWith<IndexOutOfBoundsException> { array.reverse(0, size + 1) }
assertFailsWith<IllegalArgumentException> { array.reverse(0, -1) }
}
}
doTest(build = { map {it.toString()}.toTypedArray() }, reverse = { from, to -> reverse(from, to) }, snapshot = { toList() })
@Suppress("USELESS_CAST")
doTest(build = { map {it.toString()}.toTypedArray() as Array<out String> }, 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<Byte>(3, 2, 1)) { byteArrayOf(1, 2, 3).reversed() }
expect(listOf<Short>(3, 2, 1)) { shortArrayOf(1, 2, 3).reversed() }
expect(listOf<Long>(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<out String>).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<String>().apply { arrayOf("a", "b", "c").onEach { add(it) } })
assertEquals(listOf(1, 2, 3), mutableListOf<Int>().apply { intArrayOf(1, 2, 3).onEach { add(it) } })
assertEquals(listOf<Byte>(1, 2, 3), mutableListOf<Byte>().apply { byteArrayOf(1, 2, 3).onEach { add(it) } })
assertEquals(listOf<Short>(1, 2, 3), mutableListOf<Short>().apply { shortArrayOf(1, 2, 3).onEach { add(it) } })
assertEquals(listOf<Long>(1, 2, 3), mutableListOf<Long>().apply { longArrayOf(1, 2, 3).onEach { add(it) } })
assertEquals(listOf(1f, 2f, 3f), mutableListOf<Float>().apply { floatArrayOf(1f, 2f, 3f).onEach { add(it) } })
assertEquals(listOf(1.0, 2.0, 3.0), mutableListOf<Double>().apply { doubleArrayOf(1.0, 2.0, 3.0).onEach { add(it) } })
assertEquals(listOf(true, false, false), mutableListOf<Boolean>().apply { booleanArrayOf(true, false, false).onEach { add(it) } })
assertEquals(listOf('1', '2', '3'), mutableListOf<Char>().apply { charArrayOf('1', '2', '3').onEach { add(it) } })
}
@Test fun onEachIndexed() {
assertEquals(listOf(1, 3, 5), mutableListOf<Int>().apply { intArrayOf(1, 2, 3).onEachIndexed { i, e -> add(i + e) } })
assertEquals(listOf(1, 3, 5), mutableListOf<Int>().apply { byteArrayOf(1, 2, 3).onEachIndexed { i, e -> add(i + e) } })
assertEquals(listOf(1, 3, 5), mutableListOf<Int>().apply { shortArrayOf(1, 2, 3).onEachIndexed { i, e -> add(i + e) } })
assertEquals(listOf<Long>(1, 3, 5), mutableListOf<Long>().apply { longArrayOf(1, 2, 3).onEachIndexed { i, e -> add(i + e) } })
assertEquals(listOf(1f, 3f, 5f), mutableListOf<Float>().apply { floatArrayOf(1f, 2f, 3f).onEachIndexed { i, e -> add(i + e) } })
assertEquals(listOf(1.0, 3.0, 5.0), mutableListOf<Double>().apply { doubleArrayOf(1.0, 2.0, 3.0).onEachIndexed { i, e -> add(i + e) } })
assertEquals(listOf(true, false, true), mutableListOf<Boolean>().apply { booleanArrayOf(true, false, false).onEachIndexed { i, e -> add(i % 2 == 0 || e) } })
assertEquals(listOf('1', '3', '5'), mutableListOf<Char>().apply { charArrayOf('1', '2', '3').onEachIndexed { i, e -> add(e + i) } })
assertEquals(listOf("a0", "b1", "c2"), mutableListOf<String>().apply { arrayOf("a", "b", "c").onEachIndexed { i, e -> add(e + i) } })
val empty = arrayOf<Int>()
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<Long>(2, 5, 8), { longArrayOf(2, 4, 3, 5, 8).filterIndexed { index, value -> index % 2 == (value % 2).toInt() } })
expect(listOf<Byte>(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<Array<Int>> = arrayOf(arrayOf(1, 2, 3), arrayOf(4, 5, 6))
val arr2: Array<out Array<Int>> = arr1
val arr3: Array<out Array<out Int>> = arr1
@Suppress("UNCHECKED_CAST")
val arr4: Array<Array<out Int>> = arr1 as Array<Array<out Int>>
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<Int>())
}
@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<String>())
}
@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 <TArray, T : Comparable<T>> doTest(
build: Iterable<Int>.() -> TArray,
sort: TArray.(fromIndex: Int, toIndex: Int) -> Unit,
snapshot: TArray.() -> List<T>
) {
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<IndexOutOfBoundsException> { array.sort(-1, size) }
assertFailsWith<IndexOutOfBoundsException> { array.sort(0, size + 1) }
assertFailsWith<IllegalArgumentException> { 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() })
@Suppress("USELESS_CAST")
doTest(build = { map {it.toString()}.toTypedArray() as Array<out String> }, 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 <TArray, T : Comparable<T>> doTest(
build: Iterable<Int>.() -> TArray,
sortDescending: TArray.(fromIndex: Int, toIndex: Int) -> Unit,
snapshot: TArray.() -> List<T>
) {
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<IndexOutOfBoundsException> { array.sortDescending(-1, size) }
assertFailsWith<IndexOutOfBoundsException> { array.sortDescending(0, size + 1) }
assertFailsWith<IllegalArgumentException> { 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() })
@Suppress("USELESS_CAST")
doTest(build = { map {it.toString()}.toTypedArray() as Array<out String> }, 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<Long>().sorted().none())
assertEquals(listOf(1), arrayOf(1).sorted())
fun <A, T: Comparable<T>> arrayData(vararg values: T, toArray: Array<out T>.() -> A) = ArraySortedChecker<A, T>(values.toArray(), naturalOrder())
with (arrayData("ac", "aD", "aba") { toList().toTypedArray() }) {
checkSorted<List<String>>({ sorted() }, { sortedDescending() }, { iterator() })
checkSorted<Array<String>>({ sortedArray() }, { sortedArrayDescending()}, { iterator() } )
}
@Suppress("USELESS_CAST")
with (arrayData("ac", "aD", "aba") { toList().toTypedArray() as Array<out String> }) {
checkSorted<List<String>>({ sorted() }, { sortedDescending() }, { iterator() })
checkSorted<Array<out String>>({ sortedArray() }, { sortedArrayDescending()}, { iterator() } )
}
with (arrayData(3, 7, 1) { toIntArray() }) {
checkSorted<List<Int>>( { sorted() }, { sortedDescending() }, { iterator() })
checkSorted<IntArray>( { sortedArray() }, { sortedArrayDescending() }, { iterator() })
}
with (arrayData(1L, Long.MIN_VALUE, Long.MAX_VALUE) { toLongArray() }) {
checkSorted<List<Long>>( { sorted() }, { sortedDescending() }, { iterator() })
checkSorted<LongArray>( { sortedArray() }, { sortedArrayDescending() }, { iterator() })
}
with (arrayData('a', 'D', 'c') { toCharArray() }) {
checkSorted<List<Char>>( { sorted() }, { sortedDescending() }, { iterator() })
checkSorted<CharArray>( { sortedArray() }, { sortedArrayDescending() }, { iterator() })
}
with (arrayData(1.toByte(), Byte.MAX_VALUE, Byte.MIN_VALUE) { toByteArray() }) {
checkSorted<List<Byte>>( { sorted() }, { sortedDescending() }, { iterator() })
checkSorted<ByteArray>( { 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<List<Double>>( { sorted() }, { sortedDescending() }, { iterator() })
checkSorted<DoubleArray>( { 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 <A, T> arrayData(array: A, comparator: Comparator<T>) = ArraySortedChecker<A, T>(array, comparator)
arrayData(intArrayOf(0, 1, 2, 3, 4, 5), comparator)
.checkSorted<List<Int>>( { sortedWith(comparator) }, { sortedWith(comparator.reversed()) }, { iterator() })
arrayData(arrayOf(0, 1, 2, 3, 4, 5), comparator)
.checkSorted<Array<out Int>>( { 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<IndexOutOfBoundsException> { array.sortWith(comp, -1, 6) }
assertFailsWith<IndexOutOfBoundsException> { array.sortWith(comp, 0, 7) }
assertFailsWith<IllegalArgumentException> { array.sortWith(comp, 0, -1) }
}
private data class Text(val data: String) : Comparable<Text> {
override fun compareTo(other: Text): Int = data compareTo other.data
}
private fun testStableSort(stableSort: Array<Text>.() -> Unit, intSort: Array<Int>.() -> Unit) {
fun checkEqualsButNotSame(array: Array<Text>) {
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 <T> 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(::Char).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, 3L, true, 0), { shuffle() }, { toList() })
}
private inline fun <T> 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(32) { 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(::Char).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, 3L, true, 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<IndexOutOfBoundsException> { arrayOf<String>().elementAt(0) }
assertFailsWith<IndexOutOfBoundsException> { longArrayOf(0, 1, 2).elementAt(-1) }
}
@Test
fun fill() {
fun <A, E> testFailures(array: A, fill: A.(E, Int, Int) -> Unit, element: E, arraySize: Int) {
assertFailsWith<IndexOutOfBoundsException> {
array.fill(element, -1, arraySize)
}
assertFailsWith<IndexOutOfBoundsException> {
array.fill(element, 0, arraySize + 1)
}
assertFailsWith<IllegalArgumentException> {
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) { Char(it) }, CharArray::fill, Char(0), 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<String>::fill, "0", 5)
fun <A, E> test(
array: IntArray,
fill: A.(E, Int, Int) -> Unit,
operations: List<OperationOnRange<Int, IntArray>>,
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, ::Char, 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<String>::fill, operations, IntArray::toStringArray, Int::toString, { contentEquals(it) })
}
private class OperationOnRange<E, R>(
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) { Char(get(it)) }
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 <K : Comparable<K>> Array<out Sortable<K>>.assertStableSorted(descending: Boolean = false) =
iterator().assertStableSorted(descending = descending)
private class ArraySortedChecker<A, T>(val array: A, val comparator: Comparator<in T>) {
public fun <R> checkSorted(sorted: A.() -> R, sortedDescending: A.() -> R, iterator: R.() -> Iterator<T>) {
array.sorted().iterator().assertSorted { a, b -> comparator.compare(a, b) <= 0 }
array.sortedDescending().iterator().assertSorted { a, b -> comparator.compare(a, b) >= 0 }
}
}