| /* | |
| * 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()) | |
| } | |
| } |