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