From bb1482ef2cf1488c624fd34b81938a3b5ae2958f Mon Sep 17 00:00:00 2001 From: Aleksandar Pokopec Date: Tue, 6 Apr 2010 14:56:14 +0000 Subject: Forgot to add scalacheck test for #2535. --- test/files/scalacheck/range.scala | 205 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 test/files/scalacheck/range.scala (limited to 'test/files/scalacheck') diff --git a/test/files/scalacheck/range.scala b/test/files/scalacheck/range.scala new file mode 100644 index 0000000000..faa1f5d479 --- /dev/null +++ b/test/files/scalacheck/range.scala @@ -0,0 +1,205 @@ +import org.scalacheck._ +import Prop._ +import Gen._ +import Arbitrary._ + +class Counter(r: Range) { + var cnt = 0L + var last: Option[Int] = None + val str = "Range["+r.start+", "+r.end+", "+r.step+(if (r.isInclusive) "]" else ")") + def apply(x: Int) = { + cnt += 1L + if (cnt % 500000000L == 0L) { + println("Working: %s %d %d" format (str, cnt, x)) + } + if (cnt > (Int.MaxValue.toLong + 1) * 2) + error("Count exceeds maximum possible for an Int Range") + if ((r.step > 0 && last.exists(_ > x)) || (r.step < 0 && last.exists(_ < x))) + error("Range wrapped: %d %s" format (x, last.toString)) + last = Some(x) + } +} + +abstract class RangeTest(kind: String) extends Properties("Range "+kind) { + def myGen: Gen[Range] + + val genRange = for { + start <- arbitrary[Int] + end <- arbitrary[Int] + step <- Gen.choose(1, (start - end).abs + 1) + } yield if (start < end) Range(start, end, step) else Range(start, end, -step) + + val genReasonableSizeRange = for { + start <- choose(-Int.MinValue, Int.MaxValue) + end <- choose(-Int.MinValue, Int.MaxValue) + step <- choose(-Int.MaxValue, Int.MaxValue) + } yield Range(start, end, if (step == 0) 100 else step) + + val genSmallRange = for { + start <- choose(-100, 100) + end <- choose(-100, 100) + step <- choose(1, 1) + } yield if (start < end) Range(start, end, step) else Range(start, end, -step) + + val genRangeByOne = for { + start <- arbitrary[Int] + end <- arbitrary[Int] + if (end.toLong - start.toLong).abs <= 10000000L + } yield if (start < end) Range(start, end) else Range(end, start) + + def str(r: Range) = "Range["+r.start+", "+r.end+", "+r.step+(if (r.isInclusive) "]" else ")") + + def expectedSize(r: Range): Long = if (r.isInclusive) { + (r.end.toLong - r.start.toLong < 0, r.step < 0) match { + case (true, true) | (false, false) => (r.end.toLong - r.start.toLong).abs / r.step.abs.toLong + 1L + case _ => if (r.start == r.end) 1L else 0L + } + } else { + (r.end.toLong - r.start.toLong < 0, r.step < 0) match { + case (true, true) | (false, false) => ( + (r.end.toLong - r.start.toLong).abs / r.step.abs.toLong + + (if ((r.end.toLong - r.start.toLong).abs % r.step.abs.toLong > 0L) 1L else 0L) + ) + case _ => 0L + } + } + + def within(r: Range, x: Int) = if (r.step > 0) + r.start <= x && (if (r.isInclusive) x <= r.end else x < r.end) + else + r.start >= x && (if (r.isInclusive) x >= r.end else x > r.end) + + def multiple(r: Range, x: Int) = (x.toLong - r.start) % r.step == 0 + + property("foreach.step") = forAll(myGen) { r => + var allValid = true + val cnt = new Counter(r) +// println("--------------------") +// println(r) + r foreach { x => cnt(x) +// println(x + ", " + (x - r.start) + ", " + (x.toLong - r.start) + ", " + ((x.toLong - r.start) % r.step)) + allValid &&= multiple(r, x) + } + allValid :| str(r) + } + + property("foreach.inside.range") = forAll(myGen) { r => + var allValid = true + var last: Option[Int] = None + val cnt = new Counter(r) + r foreach { x => cnt(x) + allValid &&= within(r, x) + } + allValid :| str(r) + } + + property("foreach.visited.size") = forAll(myGen) { r => + var visited = 0L + val cnt = new Counter(r) + r foreach { x => cnt(x) + visited += 1L + } +// println("----------") +// println(str(r)) +// println("size: " + r.size) +// println("expected: " + expectedSize(r)) +// println("visited: " + visited) + (visited == expectedSize(r)) :| str(r) + } + + property("length") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r))) { r => + (r.length == expectedSize(r)) :| str(r) + } + + property("isEmpty") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r))) { r => + (r.isEmpty == (expectedSize(r) == 0L)) :| str(r) + } + + property("contains") = forAll(myGen, arbInt.arbitrary) { (r, x) => +// println("----------------") +// println(str(r)) +// println(x) +// println("within: " + within(r, x)) +// println("multiple: " + multiple(r, x)) +// println("contains: " + r.contains(x)) + ((within(r, x) && multiple(r, x)) == r.contains(x)) :| str(r)+": "+x + } + + property("take") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r)), arbInt.arbitrary) { (r, x) => + val t = r take x + (t.size == (0 max x min r.size) && t.start == r.start && t.step == r.step) :| str(r)+" / "+str(t)+": "+x + } + + property("takeWhile") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r)), arbInt.arbitrary) { (r, x) => + val t = (if (r.step > 0) r takeWhile (_ <= x) else r takeWhile(_ >= x)) + if (r.size == 0) { + (t.size == 0) :| str(r)+" / "+str(t)+": "+x + } else { + val t2 = (if (r.step > 0) Range(r.start, x min r.last, r.step).inclusive else Range(r.start, x max r.last, r.step).inclusive) + (t.start == r.start && t.size == t2.size && t.step == r.step) :| str(r)+" / "+str(t)+" / "+str(t2)+": "+x + } + } + + property("reverse.toSet.equal") = forAll(myGen) { r => + val reversed = r.reverse + val aresame = r.toSet == reversed.toSet + if (!aresame) { + println(str(r)) + println(r) + println(reversed) + println(r.toSet) + println(reversed.toSet) + } + aresame + } +} + +object NormalRangeTest extends RangeTest("normal") { + override def myGen = genReasonableSizeRange + def genOne = for { + start <- arbitrary[Int] + end <- arbitrary[Int] + if (start.toLong - end.toLong).abs < Int.MaxValue.toLong + } yield Range(start, end, if (start < end) 1 else - 1) + property("by 1.size + 1 == inclusive.size") = forAll(genOne) { r => + (r.size + 1 == r.inclusive.size) :| str(r) + } +} + +object InclusiveRangeTest extends RangeTest("inclusive") { + override def myGen = for (r <- genReasonableSizeRange) yield r.inclusive +} + +object ByOneRangeTest extends RangeTest("byOne") { + override def myGen = genSmallRange +} + +object InclusiveByOneRangeTest extends RangeTest("inclusiveByOne") { + override def myGen = for (r <- genSmallRange) yield r.inclusive +} + +object SmallValuesRange extends RangeTest("smallValues") { + override def myGen = genSmallRange +} + +object Test extends Properties("Range") { + include(NormalRangeTest) + include(InclusiveRangeTest) + include(ByOneRangeTest) + include(InclusiveByOneRangeTest) +} + +/* Mini-benchmark +def testRange(i: Int, j: Int, k: Int) = { + var count = 0 + for { + vi <- 0 to i + vj <- 0 to j + vk <- 0 to k + } { count += 1 } +} + +testRange(10, 1000, 10000) +testRange(10000, 1000, 10) +*/ + -- cgit v1.2.3