blob: ff5a4614262d3b669cb5b21afb5fd26cff17cbe8 [file]
/*
* Copyright 2010-2018 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.ranges
import kotlin.test.*
public class RangeTest {
@Test fun intRange() {
val range = -5..9
assertFalse(-1000 in range)
assertFalse(-6 in range)
assertTrue(-5 in range)
assertTrue(-4 in range)
assertTrue(0 in range)
assertTrue(3 in range)
assertTrue(8 in range)
assertTrue(9 in range)
assertFalse(10 in range)
assertFalse(9000 in range)
assertFalse(range.isEmpty())
assertTrue(9 in (range as ClosedRange<Int>))
assertFalse((range as ClosedRange<Int>).isEmpty())
assertTrue(1.toShort() in range)
assertTrue(1.toByte() in range)
assertTrue(1.toLong() in range)
assertFalse(Long.MAX_VALUE in range)
assertFalse(null in range)
assertTrue(1 as Int? in range)
assertFalse(10 as Int? in range)
val closedRange = 1..9
val openRange = 1 until 10
assertTrue(9 in openRange)
assertFalse(10 in openRange)
assertEquals(closedRange, openRange)
val openRange2 = 1..<10
assertEquals(closedRange, openRange2)
assertTrue((1 until Int.MIN_VALUE).isEmpty())
}
@Test fun byteRange() {
val range = (-5).toByte()..9.toByte()
assertFalse((-100).toByte() in range)
assertFalse((-6).toByte() in range)
assertTrue((-5).toByte() in range)
assertTrue((-4).toByte() in range)
assertTrue(0.toByte() in range)
assertTrue(3.toByte() in range)
assertTrue(8.toByte() in range)
assertTrue(9.toByte() in range)
assertFalse(10.toByte() in range)
assertFalse(111.toByte() in range)
assertFalse(range.isEmpty())
assertTrue(1.toShort() in range)
assertTrue(1 in range)
assertTrue(1.toLong() in range)
assertFalse(Long.MAX_VALUE in range)
// assertTrue(1.toByte() as Byte? in range) // expected not to compile
val openRange = 1.toByte() until 10.toByte()
assertTrue(9.toByte() in openRange)
assertFalse(10.toByte() in openRange)
// byte arguments now construct IntRange so no overflow here
assertTrue((0.toByte() until Byte.MIN_VALUE).isEmpty())
assertTrue((0.toByte() until Int.MIN_VALUE).isEmpty())
}
@Test fun shortRange() {
val range = (-5).toShort()..9.toShort()
assertFalse((-1000).toShort() in range)
assertFalse((-6).toShort() in range)
assertTrue((-5).toShort() in range)
assertTrue((-4).toShort() in range)
assertTrue(0.toShort() in range)
assertTrue(3.toShort() in range)
assertTrue(8.toShort() in range)
assertTrue(9.toShort() in range)
assertFalse(10.toShort() in range)
assertFalse(239.toShort() in range)
assertFalse(range.isEmpty())
assertTrue(1.toByte() in range)
assertTrue(1 in range)
assertTrue(1.toLong() in range)
assertFalse(Long.MAX_VALUE in range)
// assertTrue(1.toShort() as Short? in range) // expected not to compile
val openRange = 1.toShort() until 10.toShort()
assertTrue(9.toShort() in openRange)
assertFalse(10.toShort() in openRange)
assertTrue((0.toShort() until Short.MIN_VALUE).isEmpty())
assertTrue((0.toShort() until Int.MIN_VALUE).isEmpty())
}
@Test fun longRange() {
val range = -5L..9L
assertFalse(-10000000L in range)
assertFalse(-6L in range)
assertTrue(-5L in range)
assertTrue(-4L in range)
assertTrue(0L in range)
assertTrue(3L in range)
assertTrue(8L in range)
assertTrue(9L in range)
assertFalse(10L in range)
assertFalse(10000000L in range)
assertFalse(range.isEmpty())
assertTrue(9 in (range as ClosedRange<Long>))
assertFalse((range as ClosedRange<Long>).isEmpty())
assertTrue(1.toByte() in range)
assertTrue(1.toShort() in range)
assertTrue(1 in range)
assertFalse(null in range)
assertTrue(1L as Long? in range)
assertFalse(10L as Long? in range)
val closedRange = 1L..9L
val openRange = 1L until 10L
assertTrue(9L in openRange)
assertFalse(10L in openRange)
assertEquals(closedRange, openRange)
val openRange2 = 1L..<10L
assertEquals(closedRange, openRange2)
assertTrue((0 until Long.MIN_VALUE).isEmpty())
assertTrue((0L until Long.MIN_VALUE).isEmpty())
}
@Test fun charRange() {
val range = 'c'..'w'
assertFalse('0' in range)
assertFalse('b' in range)
assertTrue('c' in range)
assertTrue('d' in range)
assertTrue('h' in range)
assertTrue('m' in range)
assertTrue('v' in range)
assertTrue('w' in range)
assertFalse('z' in range)
assertFalse('\u1000' in range)
assertFalse(range.isEmpty())
assertTrue('v' in (range as ClosedRange<Char>))
assertFalse((range as ClosedRange<Char>).isEmpty())
assertFalse(null in range)
assertTrue('p' as Char? in range)
assertFalse('z' as Char? in range)
val closedRange = 'A'..'Y'
val openRange = 'A' until 'Z'
assertTrue('Y' in openRange)
assertFalse('Z' in openRange)
assertEquals(closedRange, openRange)
val openRange2 = 'A'..<'Z'
assertEquals(closedRange, openRange2)
assertTrue(('A' until Char.MIN_VALUE).isEmpty())
}
@Test fun doubleRange() {
val range = -1.0..3.14159265358979
assertFalse(-1e200 in range)
assertFalse(-100.0 in range)
assertFalse(-1.00000000001 in range)
assertTrue(-1.0 in range)
assertTrue(-0.99999999999 in range)
assertTrue(0.0 in range)
assertTrue(1.5 in range)
assertTrue(3.1415 in range)
assertTrue(3.14159265358979 in range)
assertFalse(3.15 in range)
assertFalse(10.0 in range)
assertFalse(1e200 in range)
assertFalse(range.isEmpty())
assertTrue(1.toFloat() in range)
val zeroRange = 0.0..-0.0
assertFalse(zeroRange.isEmpty())
assertTrue(-0.0 in zeroRange)
assertTrue(-0.0F in zeroRange)
val normalZeroRange = -0.0..0.0
assertEquals(zeroRange, normalZeroRange)
assertEquals(zeroRange.hashCode(), normalZeroRange.hashCode())
val nanRange = 0.0..Double.NaN
assertFalse(1.0 in nanRange)
assertFalse(Double.NaN in nanRange)
assertFalse(Float.NaN in nanRange)
assertTrue(nanRange.isEmpty())
val halfInfRange = 0.0..Double.POSITIVE_INFINITY
assertTrue(Double.POSITIVE_INFINITY in halfInfRange)
assertFalse(Double.NEGATIVE_INFINITY in halfInfRange)
assertFalse(Double.NaN in halfInfRange)
assertTrue(Float.POSITIVE_INFINITY in halfInfRange)
val openRange = 0.0..<Double.POSITIVE_INFINITY
assertTrue(Double.MAX_VALUE in openRange)
assertFalse(Double.POSITIVE_INFINITY in openRange)
assertFalse(Double.NEGATIVE_INFINITY in openRange)
assertFalse(Double.NaN in openRange)
assertFalse(Float.POSITIVE_INFINITY in openRange)
val openNanRange = 0.0..<Double.NaN
assertFalse(1.0 in openNanRange)
assertFalse(Double.NaN in openNanRange)
assertFalse(Float.NaN in openNanRange)
assertTrue(openNanRange.isEmpty())
}
@Test fun floatRange() {
val range = -1.0f..3.14159f
assertFalse(-1e30f in range)
assertFalse(-100.0f in range)
assertFalse(-1.00001f in range)
assertTrue(-1.0f in range)
assertTrue(-0.99999f in range)
assertTrue(0.0f in range)
assertTrue(1.5f in range)
assertTrue(3.1415f in range)
assertTrue(3.14159f in range)
assertFalse(3.15f in range)
assertFalse(10.0f in range)
assertFalse(1e30f in range)
assertFalse(range.isEmpty())
assertTrue(1.toDouble() in range)
assertFalse(Double.MAX_VALUE in range)
val zeroRange = 0.0F..-0.0F
assertFalse(zeroRange.isEmpty())
assertTrue(-0.0F in zeroRange)
val normalZeroRange = -0.0F..0.0F
assertEquals(zeroRange, normalZeroRange)
assertEquals(zeroRange.hashCode(), normalZeroRange.hashCode())
val nanRange = 0.0F..Float.NaN
assertFalse(1.0F in nanRange)
assertFalse(Float.NaN in nanRange)
assertTrue(nanRange.isEmpty())
val halfInfRange = 0.0F..Float.POSITIVE_INFINITY
assertTrue(Float.POSITIVE_INFINITY in halfInfRange)
assertFalse(Float.NEGATIVE_INFINITY in halfInfRange)
assertFalse(Float.NaN in halfInfRange)
assertTrue(Double.POSITIVE_INFINITY in halfInfRange)
assertTrue(Double.MAX_VALUE in halfInfRange)
val openRange = 0.0F..<Float.POSITIVE_INFINITY
assertTrue(Float.MAX_VALUE in openRange)
assertFalse(Float.POSITIVE_INFINITY in openRange)
assertFalse(Float.NEGATIVE_INFINITY in openRange)
assertFalse(Float.NaN in openRange)
val openNanRange = 0.0F..<Float.NaN
assertFalse(1.0F in openNanRange)
assertFalse(Float.NaN in openNanRange)
assertTrue(openNanRange.isEmpty())
}
@Test
@Suppress("DEPRECATION")
fun openRangeEndExclusive() {
assertEquals((1..5).endInclusive, (1..<4).endExclusive + 1)
assertEquals((1L..5L).endInclusive, (1L..<4L).endExclusive + 1)
assertEquals(('X'..'Z').endInclusive, ('X'..<'Y').endExclusive + 1)
assertNotEquals(Int.MIN_VALUE, (1..<Int.MIN_VALUE).endExclusive)
assertNotEquals(Long.MIN_VALUE, (1..<Long.MIN_VALUE).endExclusive)
assertNotEquals(Char.MIN_VALUE, ('A'..<Char.MIN_VALUE).endExclusive)
}
@Test
@Suppress("DEPRECATION")
fun openRangeEndExclusiveThrows() {
assertFailsWith<IllegalStateException> { (1..Int.MAX_VALUE).endExclusive }
assertFailsWith<IllegalStateException> { (1..Long.MAX_VALUE).endExclusive }
assertFailsWith<IllegalStateException> { ('A'..Char.MAX_VALUE).endExclusive }
}
@Suppress("EmptyRange")
@Test fun isEmpty() {
assertTrue((2..1).isEmpty())
assertTrue((2L..0L).isEmpty())
assertTrue((1.toShort()..(-1).toShort()).isEmpty())
assertTrue((0.toByte()..(-1).toByte()).isEmpty())
assertTrue((0f..-3.14f).isEmpty())
assertTrue((-2.72..-3.14).isEmpty())
assertTrue(('z'..'x').isEmpty())
assertTrue((1 downTo 2).isEmpty())
assertTrue((0L downTo 2L).isEmpty())
assertFalse((2 downTo 1).isEmpty())
assertFalse((2L downTo 0L).isEmpty())
assertTrue(('a' downTo 'z').isEmpty())
assertTrue(('z'..'a' step 2).isEmpty())
assertTrue(("range".."progression").isEmpty())
}
private fun <T> assertAllEqual(vararg elements: T) {
for (i in 0..<elements.size) {
assertEquals(elements[i], elements[i])
for (j in i + 1..<elements.size) {
assertEquals(elements[i], elements[j])
assertEquals(elements[j], elements[i])
assertEquals(elements[i].hashCode(), elements[j].hashCode())
}
}
}
@Suppress("EmptyRange")
@Test fun emptyEqualsHashCode() {
assertAllEqual(IntRange.EMPTY, 2..1, 3..<3, 1..<1, 5..4 step 1, 5..4 step 5, 0 downTo 3 step 2)
assertAllEqual(LongRange.EMPTY, 2L..1L, 3L..<3L, 1L..<1L, 5L..4L step 1, 5L..4L step 5, 0L downTo 3L step 2)
assertAllEqual(CharRange.EMPTY, 'b'..'a', 'c'..<'b', 'a'..<'a', 'e'..'d' step 2, 'e'..'d' step 5, 'a' downTo 'c' step 2)
assertAllEqual(0f..-3.14f, 3.14f..0f, 0.0F..Float.NaN, Float.NaN..Float.MAX_VALUE)
assertAllEqual(-2.0..-3.0, 3.0..2.0, 0.0..Double.NaN, Double.NaN..Double.MAX_VALUE)
assertAllEqual("range".."progression", "hashcode".."equals")
assertNotEquals(0..1, IntRange.EMPTY)
assertNotEquals(0L..1L, LongRange.EMPTY)
assertNotEquals('a'..'b', CharRange.EMPTY)
assertNotEquals("aa".."bb", "bb".."aa")
}
@Suppress("EmptyRange")
@Test fun emptyOpenEquals() {
assertEquals(Double.NaN..<0.0, 0.0..<0.0)
assertEquals(0.0F..<Float.NaN, 0.0F..<0.0F)
assertNotEquals<Any>(1.0..0.0, 1.0..<0.0)
assertNotEquals<Any>(1.0F..0.0F, 1.0F..<0.0F)
}
@Test
fun nonEmptyEquals() {
assertAllEqual(0..42, 0..<43, 0..42 step 1)
assertAllEqual(0L..4200000042000000L, 0L..<4200000042000001L, 0L..4200000042000000L step 1)
assertAllEqual('a'..'d', 'a'..<'e', 'a'..'d' step 1)
assertAllEqual(0.0..1.0, 0.0..1.0)
assertAllEqual(0.0F..1.0F, 0.0F..1.0F)
assertAllEqual(3 downTo 0, 3 downTo 0 step 1)
assertAllEqual(3L downTo 0L, 3L downTo 0L step 1)
assertAllEqual('d' downTo 'a', 'd' downTo 'a' step 1)
}
@Test
fun nonEmptyRangeHashCode() {
fun <N : Comparable<N>, R> checkIterableRangeHashCode(range: R) where R : ClosedRange<N>, R : Iterable<N> {
assertEquals(31 * 31 * range.start.hashCode() + 31 * range.endInclusive.hashCode() + 1, range.hashCode())
}
fun <N : Comparable<N>> checkHashCode(range: ClosedRange<N>) {
assertEquals(31 * range.start.hashCode() + range.endInclusive.hashCode(), range.hashCode())
}
checkIterableRangeHashCode(1..10)
checkIterableRangeHashCode(1L..10L)
checkIterableRangeHashCode('a'..'z')
checkHashCode(1.0..2.0)
checkHashCode(1.0f..2.0f)
checkHashCode("a".."bz")
}
@Test
fun nonEmptyProgressionHashCode() {
fun checkHashCode(progression: Any, first: Any, last: Any, step: Any) {
assertEquals(31 * 31 * first.hashCode() + 31 * last.hashCode() + step.hashCode(), progression.hashCode())
}
(1..10 step 1).let { checkHashCode(it, it.first, it.last, it.step) }
(1..10 step 2).let { checkHashCode(it, it.first, it.last, it.step) }
(10 downTo 1).let { checkHashCode(it, it.first, it.last, it.step) }
(1L..10L step 1).let { checkHashCode(it, it.first, it.last, it.step) }
(1L..10L step 2).let { checkHashCode(it, it.first, it.last, it.step) }
(10L downTo 1L).let { checkHashCode(it, it.first, it.last, it.step) }
('a'..'z' step 1).let { checkHashCode(it, it.first, it.last, it.step) }
('a'..'z' step 2).let { checkHashCode(it, it.first, it.last, it.step) }
('z' downTo 'a').let { checkHashCode(it, it.first, it.last, it.step) }
}
@Test fun comparableRange() {
val range = "island".."isle"
assertEquals("island..isle", range.toString())
assertEquals(range, range.start..range.endInclusive)
assertFalse("apple" in range)
assertFalse("icicle" in range)
assertTrue("island" in range)
assertTrue("isle" in range)
assertTrue("islandic" in range)
assertFalse("item" in range)
assertFalse("trail" in range)
assertFalse(range.isEmpty())
assertFalse(("empty".."empty").isEmpty())
}
@Test fun comparableOpenRange() {
val range = "island"..<"isle"
assertEquals("island..<isle", range.toString())
assertEquals(range, range.start..<range.endExclusive)
assertFalse("apple" in range)
assertFalse("icicle" in range)
assertTrue("island" in range)
assertFalse("isle" in range)
assertTrue("islandic" in range)
assertFalse("item" in range)
assertFalse("trail" in range)
assertFalse(range.isEmpty())
assertTrue(("empty"..<"empty").isEmpty())
}
private fun assertFailsWithIllegalArgument(f: () -> Any?): Unit { assertFailsWith<IllegalArgumentException> { f() } }
@Test
fun illegalProgressionCreation() {
// create Progression explicitly with increment = 0
assertFailsWithIllegalArgument { IntProgression.fromClosedRange(0, 5, 0) }
assertFailsWithIllegalArgument { LongProgression.fromClosedRange(0, 5, 0) }
assertFailsWithIllegalArgument { CharProgression.fromClosedRange('a', 'z', 0) }
assertFailsWithIllegalArgument { 0..5 step 0 }
assertFailsWithIllegalArgument { 0.toByte()..5.toByte() step 0 }
assertFailsWithIllegalArgument { 0.toShort()..5.toShort() step 0 }
assertFailsWithIllegalArgument { 0L..5L step 0L }
assertFailsWithIllegalArgument { 'a'..'z' step 0 }
assertFailsWithIllegalArgument { 0 downTo -5 step 0 }
assertFailsWithIllegalArgument { 0.toByte() downTo (-5).toByte() step 0 }
assertFailsWithIllegalArgument { 0.toShort() downTo (-5).toShort() step 0 }
assertFailsWithIllegalArgument { 0L downTo -5L step 0L }
assertFailsWithIllegalArgument { 'z' downTo 'a' step 0 }
assertFailsWithIllegalArgument { 0..5 step -2 }
assertFailsWithIllegalArgument { 0.toByte()..5.toByte() step -2 }
assertFailsWithIllegalArgument { 0.toShort()..5.toShort() step -2 }
assertFailsWithIllegalArgument { 0L..5L step -2L }
assertFailsWithIllegalArgument { 'a'..'z' step -2 }
assertFailsWithIllegalArgument { 0 downTo -5 step -2 }
assertFailsWithIllegalArgument { 0.toByte() downTo (-5).toByte() step -2 }
assertFailsWithIllegalArgument { 0.toShort() downTo (-5).toShort() step -2 }
assertFailsWithIllegalArgument { 0L downTo -5L step -2L }
assertFailsWithIllegalArgument { 'z' downTo 'a' step -2 }
}
@Test fun stepSizeIsTooLow() {
assertFailsWithIllegalArgument { CharProgression.fromClosedRange('a', 'b', Int.MIN_VALUE) }
assertFailsWithIllegalArgument { IntProgression.fromClosedRange(0, 1, Int.MIN_VALUE) }
assertFailsWithIllegalArgument { LongProgression.fromClosedRange(0, 1, Long.MIN_VALUE) }
}
@Test fun randomInEmptyRange() {
assertFailsWith<NoSuchElementException> { IntRange.EMPTY.random() }
assertFailsWith<NoSuchElementException> { LongRange.EMPTY.random() }
assertFailsWith<NoSuchElementException> { CharRange.EMPTY.random() }
}
@Test fun randomOrNullInEmptyRange() {
assertNull(IntRange.EMPTY.randomOrNull())
assertNull(LongRange.EMPTY.randomOrNull())
assertNull(CharRange.EMPTY.randomOrNull())
}
@Test fun firstInEmptyRange() {
assertFailsWith<NoSuchElementException> { IntRange.EMPTY.first() }
assertFailsWith<NoSuchElementException> { LongRange.EMPTY.first() }
assertFailsWith<NoSuchElementException> { CharRange.EMPTY.first() }
assertFailsWith<NoSuchElementException> { IntProgression.fromClosedRange(0, 3, -2).first() }
}
@Test fun firstOrNullInEmptyRange() {
assertNull(IntRange.EMPTY.firstOrNull())
assertNull(LongRange.EMPTY.firstOrNull())
assertNull(CharRange.EMPTY.firstOrNull())
assertNull(IntProgression.fromClosedRange(0, 3, -2).firstOrNull())
}
@Test fun lastInEmptyRange() {
assertFailsWith<NoSuchElementException> { IntRange.EMPTY.last() }
assertFailsWith<NoSuchElementException> { LongRange.EMPTY.last() }
assertFailsWith<NoSuchElementException> { CharRange.EMPTY.last() }
assertFailsWith<NoSuchElementException> { IntProgression.fromClosedRange(0, 3, -2).last() }
}
@Test fun lastOrNullInEmptyRange() {
assertNull(IntRange.EMPTY.lastOrNull())
assertNull(LongRange.EMPTY.lastOrNull())
assertNull(CharRange.EMPTY.lastOrNull())
assertNull(IntProgression.fromClosedRange(0, 3, -2).lastOrNull())
}
}