Add manually written tests covering both min/max/By/With and their nullable variants
diff --git a/libraries/stdlib/test/collections/ArraysTest.kt b/libraries/stdlib/test/collections/ArraysTest.kt
index 42d6e13..3bcf8f0 100644
--- a/libraries/stdlib/test/collections/ArraysTest.kt
+++ b/libraries/stdlib/test/collections/ArraysTest.kt
@@ -7,10 +7,11 @@
package test.collections
+import test.assertIsNegativeZero
+import test.assertIsPositiveZero
import test.assertStaticTypeIs
import test.assertTypeEquals
import test.collections.behaviors.*
-import test.comparisons.STRING_CASE_INSENSITIVE_ORDER
import test.text.isAsciiLetter
import kotlin.test.*
import kotlin.random.Random
@@ -347,15 +348,164 @@
- @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 minMax() = with(MinMaxOperations.ArrayT) {
+ expectMinMax(1, 1, arrayOf(1))
+ expectMinMax(2, 3, arrayOf(2, 3))
+ expectMinMax(2, 3, arrayOf(3, 2))
+ expectMinMax(2000000000000, 3000000000000, arrayOf(3000000000000, 2000000000000))
+ expectMinMax('a', 'b', arrayOf('a', 'b'))
+ expectMinMax("a", "b", arrayOf("a", "b"))
+
+ MinMaxOperations.ArrayT<Int>().expectMinMaxEmpty(emptyArray())
}
+ @Test
+ fun minMaxIntArray() = with(MinMaxOperations.AInt) {
+ expectMinMaxEmpty(intArrayOf())
+ expectMinMax(1, 1, intArrayOf(1))
+ expectMinMax(1, 2, intArrayOf(1, 2))
+ }
+
+ @Test
+ fun minMaxLongArray() = with(MinMaxOperations.ALong) {
+ expectMinMaxEmpty(longArrayOf())
+ expectMinMax(1, 1, longArrayOf(1))
+ expectMinMax(1, 2, longArrayOf(1, 2))
+ }
+
+ @Test
+ fun minMaxShortArray() = with(MinMaxOperations.AShort) {
+ expectMinMaxEmpty(shortArrayOf())
+ expectMinMax(1, 1, shortArrayOf(1))
+ expectMinMax(1, 2, shortArrayOf(1, 2))
+ }
+
+ @Test
+ fun minMaxByteArray() = with(MinMaxOperations.AByte) {
+ expectMinMaxEmpty(byteArrayOf())
+ expectMinMax(1, 1, byteArrayOf(1))
+ expectMinMax(1, 2, byteArrayOf(1, 2))
+ }
+
+ @Test
+ fun minMaxFloatArray() = with(MinMaxOperations.AFloat) {
+ expectMinMaxEmpty(floatArrayOf())
+ expectMinMax(1F, 1F, floatArrayOf(1F))
+ expectMinMax(1F, 2F, floatArrayOf(1F, 2F))
+ }
+
+ @Test
+ fun minMaxDoubleArray() = with(MinMaxOperations.ADouble) {
+ expectMinMaxEmpty(doubleArrayOf())
+ expectMinMax(1.0, 1.0, doubleArrayOf(1.0))
+ expectMinMax(1.0, 2.0, doubleArrayOf(1.0, 2.0))
+ }
+
+ @Test
+ fun minMaxCharArray() = with(MinMaxOperations.AChar) {
+ expectMinMaxEmpty(charArrayOf())
+ expectMinMax('a', 'a', charArrayOf('a'))
+ expectMinMax('a', 'b', charArrayOf('a', 'b'))
+ }
+
+ @Test
+ fun minMaxFloatingPoint() {
+ val doubleZeroes = arrayOf(0.0, -0.0).also { it.shuffle() }
+ val floatZeroes = arrayOf(0.0F, -0.0F).also { it.shuffle() }
+ val doubleNaN = arrayOf(0.0, Double.NaN).also { it.shuffle() }
+ val floatNaN = arrayOf(0.0F, Float.NaN).also { it.shuffle() }
+
+ assertIsNegativeZero(doubleZeroes.min())
+ assertIsNegativeZero(doubleZeroes.minOrNull()!!)
+ assertIsNegativeZero(floatZeroes.min().toDouble())
+ assertIsNegativeZero(floatZeroes.minOrNull()!!.toDouble())
+ assertTrue(doubleNaN.min().isNaN())
+ assertTrue(doubleNaN.minOrNull()!!.isNaN())
+ assertTrue(floatNaN.min().isNaN())
+ assertTrue(floatNaN.minOrNull()!!.isNaN())
+
+ assertIsPositiveZero(doubleZeroes.max())
+ assertIsPositiveZero(doubleZeroes.maxOrNull()!!)
+ assertIsPositiveZero(floatZeroes.max().toDouble())
+ assertIsPositiveZero(floatZeroes.maxOrNull()!!.toDouble())
+ assertTrue(doubleNaN.max().isNaN())
+ assertTrue(doubleNaN.maxOrNull()!!.isNaN())
+ assertTrue(floatNaN.max().isNaN())
+ assertTrue(floatNaN.maxOrNull()!!.isNaN())
+ }
+
+ @Test
+ fun minMaxPrimitiveFloatingPoint() {
+ val doubleZeroes = doubleArrayOf(0.0, -0.0).also { it.shuffle() }
+ val floatZeroes = floatArrayOf(0.0F, -0.0F).also { it.shuffle() }
+ val doubleNaN = doubleArrayOf(0.0, Double.NaN).also { it.shuffle() }
+ val floatNaN = floatArrayOf(0.0F, Float.NaN).also { it.shuffle() }
+
+ assertIsNegativeZero(doubleZeroes.min())
+ assertIsNegativeZero(doubleZeroes.minOrNull()!!)
+ assertIsNegativeZero(floatZeroes.min().toDouble())
+ assertIsNegativeZero(floatZeroes.minOrNull()!!.toDouble())
+ assertTrue(doubleNaN.min().isNaN())
+ assertTrue(doubleNaN.minOrNull()!!.isNaN())
+ assertTrue(floatNaN.min().isNaN())
+ assertTrue(floatNaN.minOrNull()!!.isNaN())
+
+ assertIsPositiveZero(doubleZeroes.max())
+ assertIsPositiveZero(doubleZeroes.maxOrNull()!!)
+ assertIsPositiveZero(floatZeroes.max().toDouble())
+ assertIsPositiveZero(floatZeroes.maxOrNull()!!.toDouble())
+ assertTrue(doubleNaN.max().isNaN())
+ assertTrue(doubleNaN.maxOrNull()!!.isNaN())
+ assertTrue(floatNaN.max().isNaN())
+ assertTrue(floatNaN.maxOrNull()!!.isNaN())
+ }
+
+// private fun <T> expectMinMaxWith(min: T, max: T, elements: Array<T>, comparator: Comparator<T>) {
+// assertEquals(min, elements.minWithOrNull(comparator))
+// assertEquals(max, elements.maxWithOrNull(comparator))
+// assertEquals(min, elements.minWith(comparator))
+// assertEquals(max, elements.maxWith(comparator))
+// }
+
+ @Test
+ fun minMaxWith() = with(MinMaxOperationsWith.ArrayT) {
+ expectMinMaxWith(1, 1, arrayOf(1), naturalOrder())
+ expectMinMaxWith("a", "B", arrayOf("a", "B"), String.CASE_INSENSITIVE_ORDER)
+ }
+
+ @Test
+ fun minMaxWithEmpty() = with(MinMaxOperationsWith.ArrayT<Int>()) {
+ expectMinMaxWithEmpty(emptyArray(), naturalOrder())
+ }
+
+ private inline fun <T, K : Comparable<K>> expectMinMaxBy(min: T, max: T, elements: Array<T>, selector: (T) -> K) {
+ assertEquals(min, elements.minBy(selector))
+ assertEquals(min, elements.minByOrNull(selector))
+ assertEquals(max, elements.maxByOrNull(selector))
+ assertEquals(max, elements.maxByOrNull(selector))
+ }
+
+ @Test
+ fun minMaxBy() {
+ expectMinMaxBy(1, 1, arrayOf(1), { it })
+ expectMinMaxBy(3, 2, arrayOf(2, 3), { -it })
+ expectMinMaxBy('a', 'b', arrayOf('a', 'b'), { "x$it" })
+ expectMinMaxBy("b", "abc", arrayOf("abc", "b"), { it.length })
+ }
+
+ @Test
+ fun minMaxByEmpty() {
+ val empty = emptyArray<Int>()
+ val selector = Int::toString
+ assertNull(empty.minByOrNull(selector))
+ assertNull(empty.maxByOrNull(selector))
+ assertFailsWith<NoSuchElementException> { empty.minBy(selector) }
+ assertFailsWith<NoSuchElementException> { empty.maxBy(selector) }
+ }
+
+
@Test fun minOrNullInPrimitiveArrays() {
expect(null, { intArrayOf().minOrNull() })
expect(1, { intArrayOf(1).minOrNull() })
@@ -368,14 +518,6 @@
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() })
@@ -389,10 +531,6 @@
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()) })
@@ -400,25 +538,12 @@
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 } })
@@ -430,14 +555,6 @@
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 } })
diff --git a/libraries/stdlib/test/collections/CollectionTest.kt b/libraries/stdlib/test/collections/CollectionTest.kt
index 193ed2a..fd1ed1e 100644
--- a/libraries/stdlib/test/collections/CollectionTest.kt
+++ b/libraries/stdlib/test/collections/CollectionTest.kt
@@ -10,7 +10,6 @@
import test.assertStaticAndRuntimeTypeIs
import kotlin.test.*
import test.collections.behaviors.*
-import test.comparisons.STRING_CASE_INSENSITIVE_ORDER
import kotlin.math.pow
import kotlin.random.Random
@@ -833,66 +832,104 @@
assertTrue(hashSetOf(45, 14, 13).toIterable().contains(14))
}
- @Test fun minOrNull() {
- expect(null, { listOf<Int>().minOrNull() })
- expect(1, { listOf(1).minOrNull() })
- expect(2, { listOf(2, 3).minOrNull() })
- expect(2000000000000, { listOf(3000000000000, 2000000000000).minOrNull() })
- expect('a', { listOf('a', 'b').minOrNull() })
- expect("a", { listOf("a", "b").minOrNull() })
- expect(null, { listOf<Int>().asSequence().minOrNull() })
- expect(2, { listOf(2, 3).asSequence().minOrNull() })
- assertIsNegativeZero(listOf(0.0, -0.0).shuffled().minOrNull()!!)
- assertIsNegativeZero(listOf(0.0F, -0.0F).shuffled().minOrNull()!!.toDouble())
+ private fun <T : Comparable<T>> expectMinMax(min: T, max: T, elements: Iterable<T>) {
+ assertEquals(min, elements.minOrNull())
+ assertEquals(max, elements.maxOrNull())
+ assertEquals(min, elements.min())
+ assertEquals(max, elements.max())
}
- @Test fun max() {
- expect(null, { listOf<Int>().maxOrNull() })
- expect(1, { listOf(1).maxOrNull() })
- expect(3, { listOf(2, 3).maxOrNull() })
- expect(3000000000000, { listOf(3000000000000, 2000000000000).maxOrNull() })
- expect('b', { listOf('a', 'b').maxOrNull() })
- expect("b", { listOf("a", "b").maxOrNull() })
- expect(null, { listOf<Int>().asSequence().maxOrNull() })
- expect(3, { listOf(2, 3).asSequence().maxOrNull() })
-
- assertIsPositiveZero(listOf(0.0, -0.0).shuffled().maxOrNull()!!)
- assertIsPositiveZero(listOf(0.0F, -0.0F).shuffled().maxOrNull()!!.toDouble())
+ @Test
+ fun minMax() {
+ expectMinMax(1, 1, listOf(1))
+ expectMinMax(2, 3, listOf(2, 3))
+ expectMinMax(2, 3, listOf(3, 2))
+ expectMinMax(2000000000000, 3000000000000, listOf(3000000000000, 2000000000000))
+ expectMinMax('a', 'b', listOf('a', 'b'))
+ expectMinMax("a", "b", listOf("a", "b"))
}
- @Test fun minWithOrNull() {
- expect(null, { listOf<Int>().minWithOrNull(naturalOrder()) })
- expect(1, { listOf(1).minWithOrNull(naturalOrder()) })
- expect("a", { listOf("a", "B").minWithOrNull(STRING_CASE_INSENSITIVE_ORDER) })
- expect("a", { listOf("a", "B").asSequence().minWithOrNull(STRING_CASE_INSENSITIVE_ORDER) })
+ @Test
+ fun minMaxEmpty() {
+ val empty = emptyList<Int>()
+ assertNull(empty.minOrNull())
+ assertNull(empty.maxOrNull())
+ assertFailsWith<NoSuchElementException> { empty.min() }
+ assertFailsWith<NoSuchElementException> { empty.max() }
}
- @Test fun maxWithOrNull() {
- expect(null, { listOf<Int>().maxWithOrNull(naturalOrder()) })
- expect(1, { listOf(1).maxWithOrNull(naturalOrder()) })
- expect("B", { listOf("a", "B").maxWithOrNull(STRING_CASE_INSENSITIVE_ORDER) })
- expect("B", { listOf("a", "B").asSequence().maxWithOrNull(STRING_CASE_INSENSITIVE_ORDER) })
+ @Test
+ fun minMaxFloatingPoint() {
+ val doubleZeroes = listOf(0.0, -0.0)
+ val floatZeroes = listOf(0.0F, -0.0F)
+ val doubleNaN = listOf(0.0, Double.NaN)
+ val floatNaN = listOf(0.0F, Float.NaN)
+
+ assertIsNegativeZero(doubleZeroes.shuffled().min())
+ assertIsNegativeZero(doubleZeroes.shuffled().minOrNull()!!)
+ assertIsNegativeZero(floatZeroes.shuffled().min().toDouble())
+ assertIsNegativeZero(floatZeroes.shuffled().minOrNull()!!.toDouble())
+ assertTrue(doubleNaN.shuffled().min().isNaN())
+ assertTrue(doubleNaN.shuffled().minOrNull()!!.isNaN())
+ assertTrue(floatNaN.shuffled().min().isNaN())
+ assertTrue(floatNaN.shuffled().minOrNull()!!.isNaN())
+
+ assertIsPositiveZero(doubleZeroes.shuffled().max())
+ assertIsPositiveZero(doubleZeroes.shuffled().maxOrNull()!!)
+ assertIsPositiveZero(floatZeroes.shuffled().max().toDouble())
+ assertIsPositiveZero(floatZeroes.shuffled().maxOrNull()!!.toDouble())
+ assertTrue(doubleNaN.shuffled().max().isNaN())
+ assertTrue(doubleNaN.shuffled().maxOrNull()!!.isNaN())
+ assertTrue(floatNaN.shuffled().max().isNaN())
+ assertTrue(floatNaN.shuffled().maxOrNull()!!.isNaN())
}
- @Test fun minByOrNull() {
- expect(null, { listOf<Int>().minByOrNull { it } })
- expect(1, { listOf(1).minByOrNull { it } })
- expect(3, { listOf(2, 3).minByOrNull { -it } })
- expect('a', { listOf('a', 'b').minByOrNull { "x$it" } })
- expect("b", { listOf("b", "abc").minByOrNull { it.length } })
- expect(null, { listOf<Int>().asSequence().minByOrNull { it } })
- expect(3, { listOf(2, 3).asSequence().minByOrNull { -it } })
+ private fun <T> expectMinMaxWith(min: T, max: T, elements: Iterable<T>, comparator: Comparator<T>) {
+ assertEquals(min, elements.minWithOrNull(comparator))
+ assertEquals(max, elements.maxWithOrNull(comparator))
+ assertEquals(min, elements.minWith(comparator))
+ assertEquals(max, elements.maxWith(comparator))
}
- @Test fun maxByOrNull() {
- expect(null, { listOf<Int>().maxByOrNull { it } })
- expect(1, { listOf(1).maxByOrNull { it } })
- expect(2, { listOf(2, 3).maxByOrNull { -it } })
- expect('b', { listOf('a', 'b').maxByOrNull { "x$it" } })
- expect("abc", { listOf("b", "abc").maxByOrNull { it.length } })
- expect(null, { listOf<Int>().asSequence().maxByOrNull { it } })
- expect(2, { listOf(2, 3).asSequence().maxByOrNull { -it } })
+ @Test
+ fun minMaxWith() {
+ expectMinMaxWith(1, 1, listOf(1), naturalOrder())
+ expectMinMaxWith("a", "B", listOf("a", "B"), String.CASE_INSENSITIVE_ORDER)
+ }
+
+ @Test
+ fun minMaxWithEmpty() {
+ val empty = emptyList<Int>()
+ assertNull(empty.minWithOrNull(naturalOrder()))
+ assertNull(empty.maxWithOrNull(naturalOrder()))
+ assertFailsWith<NoSuchElementException> { empty.minWith(naturalOrder()) }
+ assertFailsWith<NoSuchElementException> { empty.maxWith(naturalOrder()) }
+ }
+
+ private inline fun <T, K : Comparable<K>> expectMinMaxBy(min: T, max: T, elements: Iterable<T>, selector: (T) -> K) {
+ assertEquals(min, elements.minBy(selector))
+ assertEquals(min, elements.minByOrNull(selector))
+ assertEquals(max, elements.maxByOrNull(selector))
+ assertEquals(max, elements.maxByOrNull(selector))
+ }
+
+ @Test
+ fun minMaxBy() {
+ expectMinMaxBy(1, 1, listOf(1), { it })
+ expectMinMaxBy(3, 2, listOf(2, 3), { -it })
+ expectMinMaxBy('a', 'b', listOf('a', 'b'), { "x$it" })
+ expectMinMaxBy("b", "abc", listOf("abc", "b"), { it.length })
+ }
+
+ @Test
+ fun minMaxByEmpty() {
+ val empty = emptyList<Int>()
+ val selector = Int::toString
+ assertNull(empty.minByOrNull(selector))
+ assertNull(empty.maxByOrNull(selector))
+ assertFailsWith<NoSuchElementException> { empty.minBy(selector) }
+ assertFailsWith<NoSuchElementException> { empty.maxBy(selector) }
}
@Test fun minByOrNullEvaluateOnce() {
diff --git a/libraries/stdlib/test/collections/MinMaxOperations.kt b/libraries/stdlib/test/collections/MinMaxOperations.kt
new file mode 100644
index 0000000..875df43
--- /dev/null
+++ b/libraries/stdlib/test/collections/MinMaxOperations.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2010-2022 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 kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
+import kotlin.test.assertNull
+
+sealed class MinMaxOperations<C, T>(
+ val min: C.() -> T, val max: C.() -> T, val minOrNull: C.() -> T?, val maxOrNull: C.() -> T?,
+) {
+ object AInt : MinMaxOperations<IntArray, Int>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ object ALong : MinMaxOperations<LongArray, Long>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ object AShort : MinMaxOperations<ShortArray, Short>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ object AByte : MinMaxOperations<ByteArray, Byte>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ object AUInt : MinMaxOperations<UIntArray, UInt>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ object AULong : MinMaxOperations<ULongArray, ULong>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ object AUShort : MinMaxOperations<UShortArray, UShort>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ object AUByte : MinMaxOperations<UByteArray, UByte>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ object AFloat : MinMaxOperations<FloatArray, Float>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ object ADouble : MinMaxOperations<DoubleArray, Double>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ object AChar : MinMaxOperations<CharArray, Char>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ class ArrayT<T : Comparable<T>> : MinMaxOperations<Array<T>, T>({ min() }, { max() }, { minOrNull() }, { maxOrNull() }) {
+ companion object {
+ fun <T : Comparable<T>> expectMinMax(min: T, max: T, elements: Array<T>) {
+ ArrayT<T>().expectMinMax(min, max, elements)
+ }
+ }
+ }
+ class IterableT<T : Comparable<T>> : MinMaxOperations<Iterable<T>, T>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ class SequenceT<T : Comparable<T>> : MinMaxOperations<Sequence<T>, T>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+ object CharSeq : MinMaxOperations<CharSequence, Char>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+
+
+ fun expectMinMax(min: T, max: T, elements: C) {
+ assertEquals(min, elements.minOrNull())
+ assertEquals(max, elements.maxOrNull())
+ assertEquals(min, elements.min())
+ assertEquals(max, elements.max())
+ }
+
+ fun expectMinMaxEmpty(empty: C) {
+ assertNull(empty.minOrNull())
+ assertNull(empty.maxOrNull())
+ assertFailsWith<NoSuchElementException> { empty.min() }
+ assertFailsWith<NoSuchElementException> { empty.max() }
+ }
+}
+
+
+sealed class MinMaxOperationsWith<C, T>(
+ val minWith: C.(Comparator<T>) -> T, val maxWith: C.(Comparator<T>) -> T, val minWithOrNull: C.(Comparator<T>) -> T?, val maxWithOrNull: C.(Comparator<T>) -> T?,
+) {
+ object AInt : MinMaxOperationsWith<IntArray, Int>(IntArray::minWith, IntArray::maxWith, IntArray::minWithOrNull, IntArray::maxWithOrNull)
+ object ALong : MinMaxOperationsWith<LongArray, Long>(LongArray::minWith, LongArray::maxWith, LongArray::minWithOrNull, LongArray::maxWithOrNull)
+ object AShort : MinMaxOperationsWith<ShortArray, Short>(ShortArray::minWith, ShortArray::maxWith, ShortArray::minWithOrNull, ShortArray::maxWithOrNull)
+ object AByte : MinMaxOperationsWith<ByteArray, Byte>(ByteArray::minWith, ByteArray::maxWith, ByteArray::minWithOrNull, ByteArray::maxWithOrNull)
+ object AUInt : MinMaxOperationsWith<UIntArray, UInt>(UIntArray::minWith, UIntArray::maxWith, UIntArray::minWithOrNull, UIntArray::maxWithOrNull)
+ object AULong : MinMaxOperationsWith<ULongArray, ULong>(ULongArray::minWith, ULongArray::maxWith, ULongArray::minWithOrNull, ULongArray::maxWithOrNull)
+ object AUShort : MinMaxOperationsWith<UShortArray, UShort>(UShortArray::minWith, UShortArray::maxWith, UShortArray::minWithOrNull, UShortArray::maxWithOrNull)
+ object AUByte : MinMaxOperationsWith<UByteArray, UByte>(UByteArray::minWith, UByteArray::maxWith, UByteArray::minWithOrNull, UByteArray::maxWithOrNull)
+ object AFloat : MinMaxOperationsWith<FloatArray, Float>(FloatArray::minWith, FloatArray::maxWith, FloatArray::minWithOrNull, FloatArray::maxWithOrNull)
+ object ADouble : MinMaxOperationsWith<DoubleArray, Double>(DoubleArray::minWith, DoubleArray::maxWith, DoubleArray::minWithOrNull, DoubleArray::maxWithOrNull)
+ object AChar : MinMaxOperationsWith<CharArray, Char>(CharArray::minWith, CharArray::maxWith, CharArray::minWithOrNull, CharArray::maxWithOrNull)
+ class ArrayT<T> : MinMaxOperationsWith<Array<T>, T>(Array<T>::minWith, Array<T>::maxWith, Array<T>::minWithOrNull, Array<T>::maxWithOrNull) {
+ companion object {
+ fun <T> expectMinMaxWith(min: T, max: T, elements: Array<T>, comparator: Comparator<T>) {
+ ArrayT<T>().expectMinMaxWith(min, max, elements, comparator)
+ }
+ }
+ }
+// class IterableT<T : Comparable<T>> : MinMaxOperationsWith<Iterable<T>, T>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+// class SequenceT<T : Comparable<T>> : MinMaxOperationsWith<Sequence<T>, T>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+// object CharSeq : MinMaxOperationsWith<CharSequence, Char>({ min() }, { max() }, { minOrNull() }, { maxOrNull() })
+
+
+ fun expectMinMaxWith(min: T, max: T, elements: C, comparator: Comparator<T>) {
+ assertEquals(min, elements.minWithOrNull(comparator))
+ assertEquals(max, elements.maxWithOrNull(comparator))
+ assertEquals(min, elements.minWith(comparator))
+ assertEquals(max, elements.maxWith(comparator))
+ }
+
+ fun expectMinMaxWithEmpty(empty: C, comparator: Comparator<T>) {
+ assertNull(empty.minWithOrNull(comparator))
+ assertNull(empty.maxWithOrNull(comparator))
+ assertFailsWith<NoSuchElementException> { empty.minWith(comparator) }
+ assertFailsWith<NoSuchElementException> { empty.maxWith(comparator) }
+ }
+}
+
+
diff --git a/libraries/stdlib/test/collections/SequenceTest.kt b/libraries/stdlib/test/collections/SequenceTest.kt
index 9ae24f5..4309204 100644
--- a/libraries/stdlib/test/collections/SequenceTest.kt
+++ b/libraries/stdlib/test/collections/SequenceTest.kt
@@ -5,6 +5,8 @@
package test.collections
+import test.assertIsNegativeZero
+import test.assertIsPositiveZero
import kotlin.random.Random
import kotlin.test.*
@@ -633,6 +635,106 @@
assertEquals(listOf('a', 'b', 'c'), chars)
}
+ private fun <T : Comparable<T>> expectMinMax(min: T, max: T, elements: Sequence<T>) {
+ assertEquals(min, elements.minOrNull())
+ assertEquals(max, elements.maxOrNull())
+ assertEquals(min, elements.min())
+ assertEquals(max, elements.max())
+ }
+
+ @Test
+ fun minMax() {
+ expectMinMax(1, 1, sequenceOf(1))
+ expectMinMax(2, 3, sequenceOf(2, 3))
+ expectMinMax(2, 3, sequenceOf(3, 2))
+ expectMinMax(2000000000000, 3000000000000, sequenceOf(3000000000000, 2000000000000))
+ expectMinMax('a', 'b', sequenceOf('a', 'b'))
+ expectMinMax("a", "b", sequenceOf("a", "b"))
+ }
+
+ @Test
+ fun minMaxEmpty() {
+ val empty = emptySequence<Int>()
+ assertNull(empty.minOrNull())
+ assertNull(empty.maxOrNull())
+ assertFailsWith<NoSuchElementException> { empty.min() }
+ assertFailsWith<NoSuchElementException> { empty.max() }
+ }
+
+ @Test
+ fun minMaxFloatingPoint() {
+ val doubleZeroes = sequenceOf(0.0, -0.0)
+ val floatZeroes = sequenceOf(0.0F, -0.0F)
+ val doubleNaN = sequenceOf(0.0, Double.NaN)
+ val floatNaN = sequenceOf(0.0F, Float.NaN)
+
+ assertIsNegativeZero(doubleZeroes.shuffled().min())
+ assertIsNegativeZero(doubleZeroes.shuffled().minOrNull()!!)
+ assertIsNegativeZero(floatZeroes.shuffled().min().toDouble())
+ assertIsNegativeZero(floatZeroes.shuffled().minOrNull()!!.toDouble())
+ assertTrue(doubleNaN.shuffled().min().isNaN())
+ assertTrue(doubleNaN.shuffled().minOrNull()!!.isNaN())
+ assertTrue(floatNaN.shuffled().min().isNaN())
+ assertTrue(floatNaN.shuffled().minOrNull()!!.isNaN())
+
+ assertIsPositiveZero(doubleZeroes.shuffled().max())
+ assertIsPositiveZero(doubleZeroes.shuffled().maxOrNull()!!)
+ assertIsPositiveZero(floatZeroes.shuffled().max().toDouble())
+ assertIsPositiveZero(floatZeroes.shuffled().maxOrNull()!!.toDouble())
+ assertTrue(doubleNaN.shuffled().max().isNaN())
+ assertTrue(doubleNaN.shuffled().maxOrNull()!!.isNaN())
+ assertTrue(floatNaN.shuffled().max().isNaN())
+ assertTrue(floatNaN.shuffled().maxOrNull()!!.isNaN())
+ }
+
+ private fun <T> expectMinMaxWith(min: T, max: T, elements: Sequence<T>, comparator: Comparator<T>) {
+ assertEquals(min, elements.minWithOrNull(comparator))
+ assertEquals(max, elements.maxWithOrNull(comparator))
+ assertEquals(min, elements.minWith(comparator))
+ assertEquals(max, elements.maxWith(comparator))
+ }
+
+ @Test
+ fun minMaxWith() {
+ expectMinMaxWith(1, 1, sequenceOf(1), naturalOrder())
+ expectMinMaxWith("a", "B", sequenceOf("a", "B"), String.CASE_INSENSITIVE_ORDER)
+ }
+
+ @Test
+ fun minMaxWithEmpty() {
+ val empty = emptySequence<Int>()
+ assertNull(empty.minWithOrNull(naturalOrder()))
+ assertNull(empty.maxWithOrNull(naturalOrder()))
+ assertFailsWith<NoSuchElementException> { empty.minWith(naturalOrder()) }
+ assertFailsWith<NoSuchElementException> { empty.maxWith(naturalOrder()) }
+ }
+
+ private inline fun <T, K : Comparable<K>> expectMinMaxBy(min: T, max: T, elements: Sequence<T>, selector: (T) -> K) {
+ assertEquals(min, elements.minBy(selector))
+ assertEquals(min, elements.minByOrNull(selector))
+ assertEquals(max, elements.maxByOrNull(selector))
+ assertEquals(max, elements.maxByOrNull(selector))
+ }
+
+ @Test
+ fun minMaxBy() {
+ expectMinMaxBy(1, 1, sequenceOf(1), { it })
+ expectMinMaxBy(3, 2, sequenceOf(2, 3), { -it })
+ expectMinMaxBy('a', 'b', sequenceOf('a', 'b'), { "x$it" })
+ expectMinMaxBy("b", "abc", sequenceOf("abc", "b"), { it.length })
+ }
+
+ @Test
+ fun minMaxByEmpty() {
+ val empty = emptySequence<Int>()
+ val selector = Int::toString
+ assertNull(empty.minByOrNull(selector))
+ assertNull(empty.maxByOrNull(selector))
+ assertFailsWith<NoSuchElementException> { empty.minBy(selector) }
+ assertFailsWith<NoSuchElementException> { empty.maxBy(selector) }
+ }
+
+
@Test fun sorted() {
sequenceOf(3, 7, 5).let {
it.sorted().iterator().assertSorted { a, b -> a <= b }
diff --git a/libraries/stdlib/test/collections/UnsignedArraysTest.kt b/libraries/stdlib/test/collections/UnsignedArraysTest.kt
index a8f9231..fbc6b15 100644
--- a/libraries/stdlib/test/collections/UnsignedArraysTest.kt
+++ b/libraries/stdlib/test/collections/UnsignedArraysTest.kt
@@ -421,35 +421,38 @@
}
@Test
- fun minOrNull() {
- expect(null) { arrayOf<UByte>().minOrNull() }
- expect(1u) { arrayOf<UShort>(1).minOrNull() }
- expect(2u) { arrayOf<UInt>(2, 3).minOrNull() }
- expect(2uL) { arrayOf<ULong>(3, 2).minOrNull() }
+ fun minMaxArrayOfUnsigned() = with(MinMaxOperations.ArrayT) {
+ expectMinMax(1u, 1u, arrayOf(1u))
+ expectMinMax(1u, UInt.MAX_VALUE, arrayOf(1u, UInt.MAX_VALUE))
+ expectMinMax(1uL, ULong.MAX_VALUE, arrayOf(1uL, ULong.MAX_VALUE))
}
@Test
- fun minOrNullInUnsignedArrays() {
- expect(null) { ubyteArrayOf().minOrNull() }
- expect(1u) { ushortArrayOf(1).minOrNull() }
- expect(2u) { uintArrayOf(2, 3).minOrNull() }
- expect(2uL) { ulongArrayOf(3, 2).minOrNull() }
+ fun minMaxUIntArray() = with(MinMaxOperations.AUInt) {
+ expectMinMaxEmpty(uintArrayOf())
+ expectMinMax(1, 1, uintArrayOf(1))
+ expectMinMax(1, UInt.MAX_VALUE, uintArrayOf(1, UInt.MAX_VALUE))
}
@Test
- fun maxOrNull() {
- expect(null) { arrayOf<UByte>().maxOrNull() }
- expect(1u) { arrayOf<UShort>(1).maxOrNull() }
- expect(3u) { arrayOf<UInt>(2, 3).maxOrNull() }
- expect(3uL) { arrayOf<ULong>(3, 2).maxOrNull() }
+ fun minMaxULongArray() = with(MinMaxOperations.AULong) {
+ expectMinMaxEmpty(ulongArrayOf())
+ expectMinMax(1, 1, ulongArrayOf(1))
+ expectMinMax(1, ULong.MAX_VALUE, ulongArrayOf(1, ULong.MAX_VALUE))
}
@Test
- fun maxOrNullInUnsignedArrays() {
- expect(null) { ubyteArrayOf().maxOrNull() }
- expect(1u) { ushortArrayOf(1).maxOrNull() }
- expect(3u) { uintArrayOf(2, 3).maxOrNull() }
- expect(3uL) { ulongArrayOf(3, 2).maxOrNull() }
+ fun minMaxUShortArray() = with(MinMaxOperations.AUShort) {
+ expectMinMaxEmpty(ushortArrayOf())
+ expectMinMax(1, 1, ushortArrayOf(1))
+ expectMinMax(1, 2, ushortArrayOf(1, 2))
+ }
+
+ @Test
+ fun minMaxUByteArray() = with(MinMaxOperations.AUByte) {
+ expectMinMaxEmpty(ubyteArrayOf())
+ expectMinMax(1, 1, ubyteArrayOf(1))
+ expectMinMax(1, 2, ubyteArrayOf(1, 2))
}
@Test