Skip to content

Commit bf26437

Browse files
dcsobralpaulp
authored andcommitted
Improve quality of scalacheck range tests input and output.
Remove some dead code, activate ByOne generator again, add generators for inclusive ranges, add generators that concentrate on the boundaries, and add some print statements next to exceptions that might get eaten by out of memory errors.
1 parent 6912ff8 commit bf26437

File tree

1 file changed

+55
-26
lines changed

1 file changed

+55
-26
lines changed

test/files/scalacheck/range.scala

Lines changed: 55 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,40 +12,57 @@ class Counter(r: Range) {
1212
if (cnt % 500000000L == 0L) {
1313
println("Working: %s %d %d" format (str, cnt, x))
1414
}
15-
if (cnt > (Int.MaxValue.toLong + 1) * 2)
16-
error("Count exceeds maximum possible for an Int Range")
17-
if ((r.step > 0 && last.exists(_ > x)) || (r.step < 0 && last.exists(_ < x)))
18-
error("Range wrapped: %d %s" format (x, last.toString))
15+
if (cnt > (Int.MaxValue.toLong + 1) * 2) {
16+
val msg = "Count exceeds maximum possible for an Int Range: %s" format str
17+
println(msg) // exception is likely to be eaten by an out of memory error
18+
sys error msg
19+
}
20+
if ((r.step > 0 && last.exists(_ > x)) || (r.step < 0 && last.exists(_ < x))) {
21+
val msg = "Range %s wrapped: %d %s" format (str, x, last.toString)
22+
println(msg) // exception is likely to be eaten by an out of memory error
23+
sys error msg
24+
}
1925
last = Some(x)
2026
}
2127
}
2228

2329
abstract class RangeTest(kind: String) extends Properties("Range "+kind) {
2430
def myGen: Gen[Range]
2531

26-
val genRange = for {
27-
start <- arbitrary[Int]
28-
end <- arbitrary[Int]
29-
step <- Gen.choose(1, (start - end).abs + 1)
30-
} yield if (start < end) Range(start, end, step) else Range(start, end, -step)
31-
32-
val genReasonableSizeRange = for {
33-
start <- choose(-Int.MinValue, Int.MaxValue)
34-
end <- choose(-Int.MinValue, Int.MaxValue)
32+
def genReasonableSizeRange = oneOf(genArbitraryRange, genBoundaryRange)
33+
34+
def genArbitraryRange = for {
35+
start <- choose(Int.MinValue, Int.MaxValue)
36+
end <- choose(Int.MinValue, Int.MaxValue)
3537
step <- choose(-Int.MaxValue, Int.MaxValue)
3638
} yield Range(start, end, if (step == 0) 100 else step)
3739

38-
val genSmallRange = for {
40+
def genBoundaryRange = for {
41+
boundary <- oneOf(Int.MinValue, -1, 0, 1, Int.MaxValue)
42+
isStart <- arbitrary[Boolean]
43+
size <- choose(1, 100)
44+
step <- choose(1, 101)
45+
} yield {
46+
val signum = if (boundary == 0) 1 else boundary.signum
47+
if (isStart) Range(boundary, boundary - size * boundary.signum, - step * signum)
48+
else Range(boundary - size * boundary.signum, boundary, step * signum)
49+
}
50+
51+
52+
def genSmallRange = for {
3953
start <- choose(-100, 100)
4054
end <- choose(-100, 100)
4155
step <- choose(1, 1)
4256
} yield if (start < end) Range(start, end, step) else Range(start, end, -step)
4357

44-
val genRangeByOne = for {
45-
start <- arbitrary[Int]
46-
end <- arbitrary[Int]
47-
if (end.toLong - start.toLong).abs <= 10000000L
48-
} yield if (start < end) Range(start, end) else Range(end, start)
58+
def genRangeByOne = oneOf(genRangeOpenByOne, genRangeClosedByOne)
59+
60+
def genRangeOpenByOne = for {
61+
r <- oneOf(genSmallRange, genBoundaryRange)
62+
if (r.end.toLong - r.start.toLong).abs <= 10000000L
63+
} yield if (r.start < r.end) Range(r.start, r.end) else Range(r.end, r.start)
64+
65+
def genRangeClosedByOne = for (r <- genRangeOpenByOne) yield r.start to r.end
4966

5067
def str(r: Range) = "Range["+r.start+", "+r.end+", "+r.step+(if (r.isInclusive) "]" else ")")
5168

@@ -71,7 +88,8 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) {
7188

7289
def multiple(r: Range, x: Int) = (x.toLong - r.start) % r.step == 0
7390

74-
property("foreach.step") = forAll(myGen) { r =>
91+
property("foreach.step") = forAllNoShrink(myGen) { r =>
92+
// println("foreach.step "+str(r))
7593
var allValid = true
7694
val cnt = new Counter(r)
7795
// println("--------------------")
@@ -84,6 +102,7 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) {
84102
}
85103

86104
property("foreach.inside.range") = forAll(myGen) { r =>
105+
// println("foreach.inside.range "+str(r))
87106
var allValid = true
88107
var last: Option[Int] = None
89108
val cnt = new Counter(r)
@@ -94,6 +113,7 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) {
94113
}
95114

96115
property("foreach.visited.size") = forAll(myGen) { r =>
116+
// println("foreach.visited.size "+str(r))
97117
var visited = 0L
98118
val cnt = new Counter(r)
99119
r foreach { x => cnt(x)
@@ -108,14 +128,17 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) {
108128
}
109129

110130
property("length") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r))) { r =>
131+
// println("length "+str(r))
111132
(r.length == expectedSize(r)) :| str(r)
112133
}
113134

114135
property("isEmpty") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r))) { r =>
136+
// println("isEmpty "+str(r))
115137
(r.isEmpty == (expectedSize(r) == 0L)) :| str(r)
116138
}
117139

118140
property("contains") = forAll(myGen, arbInt.arbitrary) { (r, x) =>
141+
// println("contains "+str(r))
119142
// println("----------------")
120143
// println(str(r))
121144
// println(x)
@@ -126,18 +149,21 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) {
126149
}
127150

128151
property("take") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r)), arbInt.arbitrary) { (r, x) =>
152+
// println("take "+str(r))
129153
val t = r take x
130154
(t.size == (0 max x min r.size) && t.start == r.start && t.step == r.step) :| str(r)+" / "+str(t)+": "+x
131155
}
132156

133157
property("init") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r))) { r =>
158+
// println("init "+str(r))
134159
(r.size == 0) || {
135160
val t = r.init
136161
(t.size + 1 == r.size) && (t.isEmpty || t.head == r.head)
137162
}
138163
}
139164

140165
property("takeWhile") = forAll(myGen suchThat (r => expectedSize(r).toInt == expectedSize(r)), arbInt.arbitrary) { (r, x) =>
166+
// println("takeWhile "+str(r))
141167
val t = (if (r.step > 0) r takeWhile (_ <= x) else r takeWhile(_ >= x))
142168
if (r.size == 0) {
143169
(t.size == 0) :| str(r)+" / "+str(t)+": "+x
@@ -148,6 +174,7 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) {
148174
}
149175

150176
property("reverse.toSet.equal") = forAll(myGen) { r =>
177+
// println("reverse.toSet.equal "+str(r))
151178
val reversed = r.reverse
152179
val aresame = r.toSet == reversed.toSet
153180
if (!aresame) {
@@ -157,7 +184,7 @@ abstract class RangeTest(kind: String) extends Properties("Range "+kind) {
157184
println(r.toSet)
158185
println(reversed.toSet)
159186
}
160-
aresame
187+
aresame :| str(r)
161188
}
162189
}
163190

@@ -178,11 +205,11 @@ object InclusiveRangeTest extends RangeTest("inclusive") {
178205
}
179206

180207
object ByOneRangeTest extends RangeTest("byOne") {
181-
override def myGen = genSmallRange
208+
override def myGen = genRangeByOne
182209
}
183210

184211
object InclusiveByOneRangeTest extends RangeTest("inclusiveByOne") {
185-
override def myGen = for (r <- genSmallRange) yield r.inclusive
212+
override def myGen = for (r <- genRangeByOne) yield r.inclusive
186213
}
187214

188215
object SmallValuesRange extends RangeTest("smallValues") {
@@ -207,9 +234,11 @@ object TooLargeRange extends Properties("Too Large Range") {
207234
object Test extends Properties("Range") {
208235
import org.scalacheck.{ Test => STest }
209236

210-
List(NormalRangeTest, InclusiveRangeTest, ByOneRangeTest, InclusiveByOneRangeTest, TooLargeRange) foreach { ps =>
211-
STest.checkProperties(STest.Params(testCallback = ConsoleReporter(0)), ps)
212-
}
237+
include(NormalRangeTest)
238+
include(InclusiveRangeTest)
239+
include(ByOneRangeTest)
240+
include(InclusiveByOneRangeTest)
241+
include(TooLargeRange)
213242
}
214243

215244
/* Mini-benchmark

0 commit comments

Comments
 (0)