Skip to content

Commit

Permalink
Replace Range Intersect tests with Property Tests (#3824)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexCue987 committed Jan 25, 2024
1 parent ebcbd0e commit 175473b
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 185 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1869,6 +1869,7 @@ public final class io/kotest/matchers/ranges/Range {
public final fun getStart ()Lio/kotest/matchers/ranges/RangeEdge;
public final fun greaterThan (Lio/kotest/matchers/ranges/Range;)Z
public fun hashCode ()I
public final fun intersect (Lio/kotest/matchers/ranges/Range;)Z
public final fun isEmpty ()Z
public final fun lessThan (Lio/kotest/matchers/ranges/Range;)Z
public fun toString ()Ljava/lang/String;
Expand All @@ -1877,8 +1878,8 @@ public final class io/kotest/matchers/ranges/Range {
public final class io/kotest/matchers/ranges/Range$Companion {
public final fun closedClosed (Ljava/lang/Comparable;Ljava/lang/Comparable;)Lio/kotest/matchers/ranges/Range;
public final fun closedOpen (Ljava/lang/Comparable;Ljava/lang/Comparable;)Lio/kotest/matchers/ranges/Range;
public final fun of (Lkotlin/ranges/ClosedRange;)Lio/kotest/matchers/ranges/Range;
public final fun of (Lkotlin/ranges/OpenEndRange;)Lio/kotest/matchers/ranges/Range;
public final fun ofClosedRange (Lkotlin/ranges/ClosedRange;)Lio/kotest/matchers/ranges/Range;
public final fun ofOpenEndRange (Lkotlin/ranges/OpenEndRange;)Lio/kotest/matchers/ranges/Range;
public final fun openClosed (Ljava/lang/Comparable;Ljava/lang/Comparable;)Lio/kotest/matchers/ranges/Range;
public final fun openOpen (Ljava/lang/Comparable;Ljava/lang/Comparable;)Lio/kotest/matchers/ranges/Range;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ data class Range<T: Comparable<T>>(
end.edgeType == RangeEdgeType.EXCLUSIVE
)

fun intersect(other: Range<T>): Boolean = !this.lessThan(other) && !other.lessThan(this)

fun lessThan(other: Range<T>): Boolean {
val endOfThis: T = this.end.value
val startOfOther: T = other.start.value
Expand All @@ -31,13 +33,13 @@ data class Range<T: Comparable<T>>(
fun greaterThan(other: Range<T>) = other.lessThan(this)

companion object {
fun<T: Comparable<T>> of(range: ClosedRange<T>) = Range(
fun<T: Comparable<T>> ofClosedRange(range: ClosedRange<T>) = Range(
start = RangeEdge(range.start, RangeEdgeType.INCLUSIVE),
end = RangeEdge(range.endInclusive, RangeEdgeType.INCLUSIVE)
)

@OptIn(ExperimentalStdlibApi::class)
fun<T: Comparable<T>> of(range: OpenEndRange<T>) = Range(
fun<T: Comparable<T>> ofOpenEndRange(range: OpenEndRange<T>) = Range(
start = RangeEdge(range.start, RangeEdgeType.INCLUSIVE),
end = RangeEdge(range.endExclusive, RangeEdgeType.EXCLUSIVE)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import io.kotest.matchers.shouldNot
* @see [intersect]
*/
infix fun <T: Comparable<T>> ClosedRange<T>.shouldIntersect(range: ClosedRange<T>): ClosedRange<T> {
Range.of(this) should intersect(Range.of(range))
Range.ofClosedRange(this) should intersect(Range.ofClosedRange(range))
return this
}

Expand All @@ -33,7 +33,7 @@ infix fun <T: Comparable<T>> ClosedRange<T>.shouldIntersect(range: ClosedRange<T
*/
@OptIn(ExperimentalStdlibApi::class)
infix fun <T: Comparable<T>> OpenEndRange<T>.shouldIntersect(range: ClosedRange<T>): OpenEndRange<T> {
Range.of(this) should intersect(Range.of(range))
Range.ofOpenEndRange(this) should intersect(Range.ofClosedRange(range))
return this
}

Expand All @@ -47,7 +47,7 @@ infix fun <T: Comparable<T>> OpenEndRange<T>.shouldIntersect(range: ClosedRange<
*/
@OptIn(ExperimentalStdlibApi::class)
infix fun <T: Comparable<T>> ClosedRange<T>.shouldIntersect(range: OpenEndRange<T>): ClosedRange<T> {
Range.of(this) should intersect(Range.of(range))
Range.ofClosedRange(this) should intersect(Range.ofOpenEndRange(range))
return this
}

Expand All @@ -61,7 +61,7 @@ infix fun <T: Comparable<T>> ClosedRange<T>.shouldIntersect(range: OpenEndRange<
*/
@OptIn(ExperimentalStdlibApi::class)
infix fun <T: Comparable<T>> OpenEndRange<T>.shouldIntersect(range: OpenEndRange<T>): OpenEndRange<T> {
Range.of(this) should intersect(Range.of(range))
Range.ofOpenEndRange(this) should intersect(Range.ofOpenEndRange(range))
return this
}

Expand All @@ -76,7 +76,7 @@ infix fun <T: Comparable<T>> OpenEndRange<T>.shouldIntersect(range: OpenEndRange
* @see [intersect]
*/
infix fun <T: Comparable<T>> ClosedRange<T>.shouldNotIntersect(range: ClosedRange<T>): ClosedRange<T> {
Range.of(this) shouldNot intersect(Range.of(range))
Range.ofClosedRange(this) shouldNot intersect(Range.ofClosedRange(range))
return this
}

Expand All @@ -90,7 +90,7 @@ infix fun <T: Comparable<T>> ClosedRange<T>.shouldNotIntersect(range: ClosedRang
*/
@OptIn(ExperimentalStdlibApi::class)
infix fun <T: Comparable<T>> ClosedRange<T>.shouldNotIntersect(range: OpenEndRange<T>): ClosedRange<T> {
Range.of(this) shouldNot intersect(Range.of(range))
Range.ofClosedRange(this) shouldNot intersect(Range.ofOpenEndRange(range))
return this
}

Expand All @@ -106,7 +106,7 @@ infix fun <T: Comparable<T>> ClosedRange<T>.shouldNotIntersect(range: OpenEndRan
*/
@OptIn(ExperimentalStdlibApi::class)
infix fun <T: Comparable<T>> OpenEndRange<T>.shouldNotIntersect(range: ClosedRange<T>): OpenEndRange<T> {
Range.of(this) shouldNot intersect(Range.of(range))
Range.ofOpenEndRange(this) shouldNot intersect(Range.ofClosedRange(range))
return this
}

Expand All @@ -120,7 +120,7 @@ infix fun <T: Comparable<T>> OpenEndRange<T>.shouldNotIntersect(range: ClosedRan
*/
@OptIn(ExperimentalStdlibApi::class)
infix fun <T: Comparable<T>> OpenEndRange<T>.shouldNotIntersect(range: OpenEndRange<T>): OpenEndRange<T> {
Range.of(this) shouldNot intersect(Range.of(range))
Range.ofOpenEndRange(this) shouldNot intersect(Range.ofOpenEndRange(range))
return this
}

Expand All @@ -136,7 +136,7 @@ fun <T: Comparable<T>> intersect(range: Range<T>) = object : Matcher<Range<T>> {
override fun test(value: Range<T>): MatcherResult {
if (range.isEmpty()) throw AssertionError("Asserting content on empty range. Use Iterable.shouldBeEmpty() instead.")

val match = !range.lessThan(value) && !value.lessThan(range)
val match = range.intersect(value)

return MatcherResult(
match,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,90 +6,40 @@ import io.kotest.core.spec.style.WordSpec
import io.kotest.matchers.ranges.shouldIntersect
import io.kotest.matchers.ranges.shouldNotIntersect
import io.kotest.matchers.shouldBe
import io.kotest.property.Arb
import io.kotest.property.arbitrary.int
import io.kotest.property.forAll

class ClosedIntersectClosedTest: WordSpec() {
private val oneThree: ClosedRange<Int> = (1..3)
private val twoFour: ClosedRange<Int> = (2..4)
private val threeFour: ClosedRange<Int> = (3..4)
private val threeFive: ClosedRange<Int> = (3..5)
private val fourSix: ClosedRange<Int> = (4..6)
init {
"should" should {
"fail if left below right" {
"fail" {
shouldThrowAny {
oneThree shouldIntersect fourSix
}.message shouldBe "Range [1, 3] should intersect [4, 6], but doesn't"
}

"fail if right below left" {
shouldThrowAny {
fourSix shouldIntersect oneThree
}.message shouldBe "Range [4, 6] should intersect [1, 3], but doesn't"
}

"pass if have common edge" {
"pass" {
shouldNotThrowAny {
oneThree shouldIntersect threeFive
threeFive shouldIntersect oneThree
}
}

"pass if intersect but not completely inside one another" {
shouldNotThrowAny {
oneThree shouldIntersect twoFour
twoFour shouldIntersect oneThree
}
}

"pass if one completely inside another" {
shouldNotThrowAny {
twoFour shouldIntersect threeFour
threeFour shouldIntersect twoFour
}
}
}

"shouldNot" should {
"pass if left below right" {
"pass" {
shouldNotThrowAny {
oneThree shouldNotIntersect fourSix
}
}

"pass if right below left" {
shouldNotThrowAny {
fourSix shouldNotIntersect oneThree
}
}

"fail if have common edge" {
"fail" {
shouldThrowAny {
oneThree shouldNotIntersect threeFive
}.message shouldBe "Range [1, 3] should not intersect [3, 5], but does"

shouldThrowAny {
threeFive shouldNotIntersect oneThree
}.message shouldBe "Range [3, 5] should not intersect [1, 3], but does"
}

"fail if intersect but not completely inside one another" {
shouldThrowAny {
oneThree shouldNotIntersect twoFour
}.message shouldBe "Range [1, 3] should not intersect [2, 4], but does"

shouldThrowAny {
twoFour shouldNotIntersect oneThree
}.message shouldBe "Range [2, 4] should not intersect [1, 3], but does"
}

"fail if one completely inside another" {
shouldThrowAny {
twoFour shouldNotIntersect threeFour
}.message shouldBe "Range [2, 4] should not intersect [3, 4], but does"

shouldThrowAny {
threeFour shouldNotIntersect twoFour
}.message shouldBe "Range [3, 4] should not intersect [2, 4], but does"
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,89 +11,35 @@ import io.kotest.matchers.shouldBe
class ClosedIntersectOpenEndTest: WordSpec() {
private val oneThree: ClosedRange<Double> = (1.0..3.0)
private val twoFour: ClosedRange<Double> = (2.0 .. 4.0)
private val threeFour: ClosedRange<Double> = (3.0..4.0)
private val threeFive: ClosedRange<Double> = (3.0..5.0)
private val fourSix: ClosedRange<Double> = (4.0..6.0)
init {
"should" should {
"fail if left below right" {
"fail" {
shouldThrowAny {
val openEndRange = oneThree.toOpenEndRange()
println(openEndRange)
openEndRange shouldIntersect fourSix
}.message shouldBe "Range [1.0, 3.0) should intersect [4.0, 6.0], but doesn't"
}

"fail if right below left" {
shouldThrowAny {
fourSix shouldIntersect (oneThree.toOpenEndRange())
}.message shouldBe "Range [4.0, 6.0] should intersect [1.0, 3.0), but doesn't"
}

"fail if have common edge, but only one inclusive" {
val openEndRange = oneThree.toOpenEndRange()
shouldThrowAny {
openEndRange shouldIntersect threeFive
}.message shouldBe "Range [1.0, 3.0) should intersect [3.0, 5.0], but doesn't"
shouldThrowAny {
threeFive shouldIntersect openEndRange
}.message shouldBe "Range [3.0, 5.0] should intersect [1.0, 3.0), but doesn't"
}

"pass if intersect but not completely inside one another" {
"pass" {
shouldNotThrowAny {
oneThree.toOpenEndRange() shouldIntersect twoFour
twoFour shouldIntersect oneThree.toOpenEndRange()
}
}

"pass if one completely inside another" {
shouldNotThrowAny {
twoFour shouldIntersect threeFour.toOpenEndRange()
threeFour.toOpenEndRange() shouldIntersect twoFour
}
}
}

"shouldNot" should {
"pass if left below right" {
"pass" {
shouldNotThrowAny {
oneThree.toOpenEndRange() shouldNotIntersect fourSix
oneThree.toOpenEndRange() shouldNotIntersect threeFour
}
}

"pass if right below left" {
shouldNotThrowAny {
fourSix shouldNotIntersect oneThree.toOpenEndRange()
}
}

"pass if have common edge" {
shouldNotThrowAny {
oneThree.toOpenEndRange() shouldNotIntersect threeFive
threeFive shouldNotIntersect oneThree.toOpenEndRange()
}
}

"fail if intersect but not completely inside one another" {
"fail" {
shouldThrowAny {
oneThree.toOpenEndRange() shouldNotIntersect twoFour
}.message shouldBe "Range [1.0, 3.0) should not intersect [2.0, 4.0], but does"

shouldThrowAny {
twoFour shouldNotIntersect oneThree.toOpenEndRange()
}.message shouldBe "Range [2.0, 4.0] should not intersect [1.0, 3.0), but does"
}

"fail if one completely inside another" {
shouldThrowAny {
twoFour shouldNotIntersect threeFour.toOpenEndRange()
}.message shouldBe "Range [2.0, 4.0] should not intersect [3.0, 4.0), but does"

shouldThrowAny {
threeFour.toOpenEndRange() shouldNotIntersect twoFour
}.message shouldBe "Range [3.0, 4.0) should not intersect [2.0, 4.0], but does"
}
}
}
Expand Down

0 comments on commit 175473b

Please sign in to comment.