My favorites | Sign in
Project Home
Checkout   Browse   Changes  
Changes to /trunk/src/main/scala/org/scalacheck/Gen.scala
r494 vs. r506 Compare: vs.  Format:
Revision r506
Go to: 
Project members, sign in to write a code review
/trunk/src/main/scala/org/scalacheck/Gen.scala   r494 /trunk/src/main/scala/org/scalacheck/Gen.scala   r506
1 /*-------------------------------------------------------------------------*\ 1 /*-------------------------------------------------------------------------*\
2 ** ScalaCheck ** 2 ** ScalaCheck **
3 ** Copyright (c) 2007-2010 Rickard Nilsson. All rights reserved. ** 3 ** Copyright (c) 2007-2010 Rickard Nilsson. All rights reserved. **
4 ** http://www.scalacheck.org ** 4 ** http://www.scalacheck.org **
5 ** ** 5 ** **
6 ** This software is released under the terms of the Revised BSD License. ** 6 ** This software is released under the terms of the Revised BSD License. **
7 ** There is NO WARRANTY. See the file LICENSE for the full text. ** 7 ** There is NO WARRANTY. See the file LICENSE for the full text. **
8 \*-------------------------------------------------------------------------*/ 8 \*-------------------------------------------------------------------------*/
9 9
10 package org.scalacheck 10 package org.scalacheck
11 11
12 import scala.collection.mutable.ListBuffer 12 import scala.collection.mutable.ListBuffer
13 import util.Buildable 13 import util.Buildable
14 import Prop._ 14 import Prop._
15 import Arbitrary._ 15 import Arbitrary._
16 16
17 trait Choose[T] { 17 trait Choose[T] {
18 def choose(min: T, max: T): Gen[T] 18 def choose(min: T, max: T): Gen[T]
19 } 19 }
20 20
21 object Choose { 21 object Choose {
22 import Gen.{fail, parameterized, value} 22 import Gen.{fail, parameterized, value}
23 23
24 implicit val chooseLong: Choose[Long] = new Choose[Long] { 24 implicit val chooseLong: Choose[Long] = new Choose[Long] {
25 def choose(low: Long, high: Long) = 25 def choose(low: Long, high: Long) =
26 if(low > high || (high-low < 0)) fail 26 if(low > high || (high-low < 0)) fail
27 else parameterized(prms => value(prms.choose(low,high))) 27 else parameterized(prms => value(prms.choose(low,high)))
28 } 28 }
29 29
30 implicit val chooseDouble: Choose[Double] = new Choose[Double] { 30 implicit val chooseDouble: Choose[Double] = new Choose[Double] {
31 def choose(low: Double, high: Double) = 31 def choose(low: Double, high: Double) =
32 if (low > high || (high-low > Double.MaxValue)) fail 32 if (low > high || (high-low > Double.MaxValue)) fail
33 else parameterized(prms => value(prms.choose(low,high))) 33 else parameterized(prms => value(prms.choose(low,high)))
34 } 34 }
35 35
36 implicit val chooseInt: Choose[Int] = new Choose[Int] { 36 implicit val chooseInt: Choose[Int] = new Choose[Int] {
37 def choose(low: Int, high: Int) = 37 def choose(low: Int, high: Int) =
38 chooseLong.choose(low, high).map(_.toInt) 38 chooseLong.choose(low, high).map(_.toInt)
39 } 39 }
40 40
41 implicit val chooseByte: Choose[Byte] = new Choose[Byte] { 41 implicit val chooseByte: Choose[Byte] = new Choose[Byte] {
42 def choose(low: Byte, high: Byte) = 42 def choose(low: Byte, high: Byte) =
43 chooseLong.choose(low, high).map(_.toByte) 43 chooseLong.choose(low, high).map(_.toByte)
44 } 44 }
45 45
46 implicit val chooseShort: Choose[Short] = new Choose[Short] { 46 implicit val chooseShort: Choose[Short] = new Choose[Short] {
47 def choose(low: Short, high: Short) = 47 def choose(low: Short, high: Short) =
48 chooseLong.choose(low, high).map(_.toShort) 48 chooseLong.choose(low, high).map(_.toShort)
49 } 49 }
50 50
51 implicit val chooseChar: Choose[Char] = new Choose[Char] { 51 implicit val chooseChar: Choose[Char] = new Choose[Char] {
52 def choose(low: Char, high: Char) = 52 def choose(low: Char, high: Char) =
53 chooseLong.choose(low, high).map(_.toChar) 53 chooseLong.choose(low, high).map(_.toChar)
54 } 54 }
55 55
56 implicit val chooseFloat: Choose[Float] = new Choose[Float] { 56 implicit val chooseFloat: Choose[Float] = new Choose[Float] {
57 def choose(low: Float, high: Float) = 57 def choose(low: Float, high: Float) =
58 chooseDouble.choose(low, high).map(_.toFloat) 58 chooseDouble.choose(low, high).map(_.toFloat)
59 } 59 }
60 } 60 }
61 61
62 62
63 /** Class that represents a generator. */ 63 /** Class that represents a generator. */
64 sealed trait Gen[+T] { 64 sealed trait Gen[+T] {
65 65
66 import Gen.choose 66 import Gen.choose
67 67
68 var label = "" // TODO: Ugly mutable field 68 var label = "" // TODO: Ugly mutable field
69 69
70 /** Put a label on the generator to make test reports clearer */ 70 /** Put a label on the generator to make test reports clearer */
71 def label(l: String): Gen[T] = { 71 def label(l: String): Gen[T] = {
72 label = l 72 label = l
73 this 73 this
74 } 74 }
75 75
76 /** Put a label on the generator to make test reports clearer */ 76 /** Put a label on the generator to make test reports clearer */
77 def :|(l: String) = label(l) 77 def :|(l: String) = label(l)
78 78
79 /** Put a label on the generator to make test reports clearer */ 79 /** Put a label on the generator to make test reports clearer */
80 def |:(l: String) = label(l) 80 def |:(l: String) = label(l)
81 81
82 /** Put a label on the generator to make test reports clearer */ 82 /** Put a label on the generator to make test reports clearer */
83 def :|(l: Symbol) = label(l.toString.drop(1)) 83 def :|(l: Symbol) = label(l.toString.drop(1))
84 84
85 /** Put a label on the generator to make test reports clearer */ 85 /** Put a label on the generator to make test reports clearer */
86 def |:(l: Symbol) = label(l.toString.drop(1)) 86 def |:(l: Symbol) = label(l.toString.drop(1))
87 87
88 def apply(prms: Gen.Params): Option[T] 88 def apply(prms: Gen.Params): Option[T]
89 89
90 def map[U](f: T => U): Gen[U] = Gen(prms => this(prms).map(f)).label(label) 90 def map[U](f: T => U): Gen[U] = Gen(prms => this(prms).map(f)).label(label)
91 91
92 def map2[U, V](g: Gen[U])(f: (T, U) => V) = 92 def map2[U, V](g: Gen[U])(f: (T, U) => V) =
93 combine(g)((t, u) => t.flatMap(t => u.flatMap(u => Some(f(t, u))))) 93 combine(g)((t, u) => t.flatMap(t => u.flatMap(u => Some(f(t, u)))))
94 94
95 def map3[U, V, W](gu: Gen[U], gv: Gen[V])(f: (T, U, V) => W) = 95 def map3[U, V, W](gu: Gen[U], gv: Gen[V])(f: (T, U, V) => W) =
96 combine3(gu, gv)((t, u, v) => t.flatMap(t => u.flatMap(u => v.flatMap(v => Some(f(t, u, v)))))) 96 combine3(gu, gv)((t, u, v) => t.flatMap(t => u.flatMap(u => v.flatMap(v => Some(f(t, u, v))))))
97 97
98 def map4[U, V, W, X](gu: Gen[U], gv: Gen[V], gw: Gen[W])(f: (T, U, V, W) => X) = 98 def map4[U, V, W, X](gu: Gen[U], gv: Gen[V], gw: Gen[W])(f: (T, U, V, W) => X) =
99 combine4(gu, gv, gw)((t, u, v, w) => t.flatMap(t => u.flatMap(u => v.flatMap(v => w.flatMap(w => Some(f(t, u, v, w))))))) 99 combine4(gu, gv, gw)((t, u, v, w) => t.flatMap(t => u.flatMap(u => v.flatMap(v => w.flatMap(w => Some(f(t, u, v, w)))))))
100 100
101 def map5[U, V, W, X, Y](gu: Gen[U], gv: Gen[V], gw: Gen[W], gx: Gen[X])(f: (T, U, V, W, X) => Y) = 101 def map5[U, V, W, X, Y](gu: Gen[U], gv: Gen[V], gw: Gen[W], gx: Gen[X])(f: (T, U, V, W, X) => Y) =
102 combine5(gu, gv, gw, gx)((t, u, v, w, x) => t.flatMap(t => u.flatMap(u => v.flatMap(v => w.flatMap(w => x.flatMap(x => Some(f(t, u, v, w, x)))))))) 102 combine5(gu, gv, gw, gx)((t, u, v, w, x) => t.flatMap(t => u.flatMap(u => v.flatMap(v => w.flatMap(w => x.flatMap(x => Some(f(t, u, v, w, x))))))))
103 103
104 def map6[U, V, W, X, Y, Z](gu: Gen[U], gv: Gen[V], gw: Gen[W], gx: Gen[X], gy: Gen[Y])(f: (T, U, V, W, X, Y) => Z) = 104 def map6[U, V, W, X, Y, Z](gu: Gen[U], gv: Gen[V], gw: Gen[W], gx: Gen[X], gy: Gen[Y])(f: (T, U, V, W, X, Y) => Z) =
105 combine6(gu, gv, gw, gx, gy)((t, u, v, w, x, y) => t.flatMap(t => u.flatMap(u => v.flatMap(v => w.flatMap(w => x.flatMap(x => y.flatMap(y => Some(f(t, u, v, w, x, y))))))))) 105 combine6(gu, gv, gw, gx, gy)((t, u, v, w, x, y) => t.flatMap(t => u.flatMap(u => v.flatMap(v => w.flatMap(w => x.flatMap(x => y.flatMap(y => Some(f(t, u, v, w, x, y)))))))))
106 106
107 def flatMap[U](f: T => Gen[U]): Gen[U] = Gen(prms => for { 107 def flatMap[U](f: T => Gen[U]): Gen[U] = Gen(prms => for {
108 t <- this(prms) 108 t <- this(prms)
109 u <- f(t)(prms) 109 u <- f(t)(prms)
110 } yield u) 110 } yield u)
111 111
112 def filter(p: T => Boolean): Gen[T] = Gen(prms => for { 112 def filter(p: T => Boolean): Gen[T] = Gen(prms => for {
113 t <- this(prms) 113 t <- this(prms)
114 u <- if (p(t)) Some(t) else None 114 u <- if (p(t)) Some(t) else None
115 } yield u).label(label) 115 } yield u).label(label)
116
117 def withFilter(p: T => Boolean) = new GenWithFilter[T](this, p)
118
119 final class GenWithFilter[+A](self: Gen[A], p: A => Boolean) {
120 def map[B](f: A => B): Gen[B] = self filter p map f
121 def flatMap[B](f: A => Gen[B]): Gen[B] = self filter p flatMap f
122 def withFilter(q: A => Boolean): GenWithFilter[A] = new GenWithFilter[A](self, x => p(x) && q(x))
123 }
116 124
117 def suchThat(p: T => Boolean): Gen[T] = filter(p) 125 def suchThat(p: T => Boolean): Gen[T] = filter(p)
118 126
119 def combine[U,V](g: Gen[U])(f: (Option[T],Option[U]) => Option[V]): Gen[V] = 127 def combine[U,V](g: Gen[U])(f: (Option[T],Option[U]) => Option[V]): Gen[V] =
120 Gen(prms => f(this(prms), g(prms))) 128 Gen(prms => f(this(prms), g(prms)))
121 129
122 def combine3[U, V, W](gu: Gen[U], gv: Gen[V]) 130 def combine3[U, V, W](gu: Gen[U], gv: Gen[V])
123 (f: (Option[T], Option[U], Option[V]) => Option[W]) = 131 (f: (Option[T], Option[U], Option[V]) => Option[W]) =
124 Gen(prms => f(this(prms), gu(prms), gv(prms))) 132 Gen(prms => f(this(prms), gu(prms), gv(prms)))
125 133
126 def combine4[U, V, W, X](gu: Gen[U], gv: Gen[V], gw: Gen[W]) 134 def combine4[U, V, W, X](gu: Gen[U], gv: Gen[V], gw: Gen[W])
127 (f: (Option[T], Option[U], Option[V], Option[W]) => Option[X]) = 135 (f: (Option[T], Option[U], Option[V], Option[W]) => Option[X]) =
128 Gen(prms => f(this(prms), gu(prms), gv(prms), gw(prms))) 136 Gen(prms => f(this(prms), gu(prms), gv(prms), gw(prms)))
129 137
130 def combine5[U, V, W, X, Y](gu: Gen[U], gv: Gen[V], gw: Gen[W], gx: Gen[X]) 138 def combine5[U, V, W, X, Y](gu: Gen[U], gv: Gen[V], gw: Gen[W], gx: Gen[X])
131 (f: (Option[T], Option[U], Option[V], Option[W], Option[X]) => Option[Y]) = 139 (f: (Option[T], Option[U], Option[V], Option[W], Option[X]) => Option[Y]) =
132 Gen(prms => f(this(prms), gu(prms), gv(prms), gw(prms), gx(prms))) 140 Gen(prms => f(this(prms), gu(prms), gv(prms), gw(prms), gx(prms)))
133 141
134 def combine6[U, V, W, X, Y, Z](gu: Gen[U], gv: Gen[V], gw: Gen[W], gx: Gen[X], gy: Gen[Y]) 142 def combine6[U, V, W, X, Y, Z](gu: Gen[U], gv: Gen[V], gw: Gen[W], gx: Gen[X], gy: Gen[Y])
135 (f: (Option[T], Option[U], Option[V], Option[W], Option[X], Option[Y]) => Option[Z]) = 143 (f: (Option[T], Option[U], Option[V], Option[W], Option[X], Option[Y]) => Option[Z]) =
136 Gen(prms => f(this(prms), gu(prms), gv(prms), gw(prms), gx(prms), gy(prms))) 144 Gen(prms => f(this(prms), gu(prms), gv(prms), gw(prms), gx(prms), gy(prms)))
137 145
138 def ap[U](g: Gen[T => U]) = flatMap(t => g.flatMap(u => Gen(p => Some(u(t))))) 146 def ap[U](g: Gen[T => U]) = flatMap(t => g.flatMap(u => Gen(p => Some(u(t)))))
139 147
140 override def toString = 148 override def toString =
141 if(label.length == 0) "Gen()" else "Gen(\"" + label + "\")" 149 if(label.length == 0) "Gen()" else "Gen(\"" + label + "\")"
142 150
143 /** Returns a new property that holds if and only if both this 151 /** Returns a new property that holds if and only if both this
144 * and the given generator generates the same result, or both 152 * and the given generator generates the same result, or both
145 * generators generate no result. 153 * generators generate no result.
146 * @deprecated Use <code>==</code> instead */ 154 * @deprecated Use <code>==</code> instead */
147 @deprecated("Use == instead") 155 @deprecated("Use == instead")
148 def ===[U](g: Gen[U]): Prop = this == g 156 def ===[U](g: Gen[U]): Prop = this == g
149 157
150 /** Returns a new property that holds if and only if both this 158 /** Returns a new property that holds if and only if both this
151 * and the given generator generates the same result, or both 159 * and the given generator generates the same result, or both
152 * generators generate no result. */ 160 * generators generate no result. */
153 def ==[U](g: Gen[U]) = Prop(prms => 161 def ==[U](g: Gen[U]) = Prop(prms =>
154 (this(prms.genPrms), g(prms.genPrms)) match { 162 (this(prms.genPrms), g(prms.genPrms)) match {
155 case (None,None) => proved(prms) 163 case (None,None) => proved(prms)
156 case (Some(r1),Some(r2)) if r1 == r2 => proved(prms) 164 case (Some(r1),Some(r2)) if r1 == r2 => proved(prms)
157 case _ => falsified(prms) 165 case _ => falsified(prms)
158 } 166 }
159 ) 167 )
160 168
161 def !=[U](g: Gen[U]) = forAll(this)(r => forAll(g)(_ != r)) 169 def !=[U](g: Gen[U]) = forAll(this)(r => forAll(g)(_ != r))
162 170
163 def !==[U](g: Gen[U]) = Prop(prms => 171 def !==[U](g: Gen[U]) = Prop(prms =>
164 (this(prms.genPrms), g(prms.genPrms)) match { 172 (this(prms.genPrms), g(prms.genPrms)) match {
165 case (None,None) => falsified(prms) 173 case (None,None) => falsified(prms)
166 case (Some(r1),Some(r2)) if r1 == r2 => falsified(prms) 174 case (Some(r1),Some(r2)) if r1 == r2 => falsified(prms)
167 case _ => proved(prms) 175 case _ => proved(prms)
168 } 176 }
169 ) 177 )
170 178
171 private var freq = 1 179 private var freq = 1
172 def |[U >: T](g: Gen[U]): Gen[U] = { 180 def |[U >: T](g: Gen[U]): Gen[U] = {
173 val h = Gen.frequency((freq, this), (1, g)) 181 val h = Gen.frequency((freq, this), (1, g))
174 h.freq = freq+1 182 h.freq = freq+1
175 h 183 h
176 } 184 }
177 185
178 /** Generates a sample value by using default parameters */ 186 /** Generates a sample value by using default parameters */
179 def sample: Option[T] = apply(Gen.Params()) 187 def sample: Option[T] = apply(Gen.Params())
180 188
181 } 189 }
182 190
183 191
184 /** Contains combinators for building generators. */ 192 /** Contains combinators for building generators. */
185 object Gen { 193 object Gen {
186 194
187 import Arbitrary._ 195 import Arbitrary._
188 import Shrink._ 196 import Shrink._
189 197
190 /** Record that encapsulates all parameters required for data generation */ 198 /** Record that encapsulates all parameters required for data generation */
191 case class Params( 199 case class Params(
192 size: Int = 100, 200 size: Int = 100,
193 rng: java.util.Random = util.StdRand 201 rng: java.util.Random = util.StdRand
194 ) { 202 ) {
195 def resize(newSize: Int) = this.copy(size = newSize) 203 def resize(newSize: Int) = this.copy(size = newSize)
196 204
197 /** @throws IllegalArgumentException if l is greater than h, or if 205 /** @throws IllegalArgumentException if l is greater than h, or if
198 * the range between l and h doesn't fit in a Long. */ 206 * the range between l and h doesn't fit in a Long. */
199 def choose(l: Long, h: Long): Long = { 207 def choose(l: Long, h: Long): Long = {
200 val d = h-l+1 208 val d = h-l+1
201 if (d <= 0) throw new IllegalArgumentException("Invalid range") 209 if (d <= 0) throw new IllegalArgumentException("Invalid range")
202 else l + (math.abs(rng.nextLong) % d) 210 else l + (math.abs(rng.nextLong) % d)
203 } 211 }
204 212
205 /** @throws IllegalArgumentException if l is greater than h, or if 213 /** @throws IllegalArgumentException if l is greater than h, or if
206 * the range between l and h doesn't fit in a Double. */ 214 * the range between l and h doesn't fit in a Double. */
207 def choose(l: Double, h: Double) = { 215 def choose(l: Double, h: Double) = {
208 val d = h-l 216 val d = h-l
209 if (d < 0 || d > Double.MaxValue) throw new IllegalArgumentException 217 if (d < 0 || d > Double.MaxValue) throw new IllegalArgumentException
210 else rng.nextDouble * (h-l) + l 218 else rng.nextDouble * (h-l) + l
211 } 219 }
212 } 220 }
213 221
214 /* Default generator parameters 222 /* Default generator parameters
215 * @deprecated Use <code>Gen.Params()</code> instead */ 223 * @deprecated Use <code>Gen.Params()</code> instead */
216 @deprecated("Use Gen.Params() instead") 224 @deprecated("Use Gen.Params() instead")
217 val defaultParams = Params() 225 val defaultParams = Params()
218 226
219 /* Generator factory method */ 227 /* Generator factory method */
220 def apply[T](g: Gen.Params => Option[T]) = new Gen[T] { 228 def apply[T](g: Gen.Params => Option[T]) = new Gen[T] {
221 def apply(p: Gen.Params) = g(p) 229 def apply(p: Gen.Params) = g(p)
222 } 230 }
223 231
224 /* Convenience method for using the <code>frequency</code> method like this: 232 /* Convenience method for using the <code>frequency</code> method like this:
225 * <code>frequency((1, "foo"), (3, "bar"))</code> */ 233 * <code>frequency((1, "foo"), (3, "bar"))</code> */
226 implicit def freqTuple[T](t: (Int, T)): (Int, Gen[T]) = (t._1, value(t._2)) 234 implicit def freqTuple[T](t: (Int, T)): (Int, Gen[T]) = (t._1, value(t._2))
227 235
228 236
229 //// Various Generator Combinators //// 237 //// Various Generator Combinators ////
230 238
231 /** Sequences generators. If any of the given generators fails, the 239 /** Sequences generators. If any of the given generators fails, the
232 * resulting generator will also fail. */ 240 * resulting generator will also fail. */
233 def sequence[C[_],T](gs: Iterable[Gen[T]])(implicit b: Buildable[T,C]): Gen[C[T]] = Gen(prms => { 241 def sequence[C[_],T](gs: Iterable[Gen[T]])(implicit b: Buildable[T,C]): Gen[C[T]] = Gen(prms => {
234 val builder = b.builder 242 val builder = b.builder
235 var none = false 243 var none = false
236 val xs = gs.iterator 244 val xs = gs.iterator
237 while(xs.hasNext && !none) xs.next.apply(prms) match { 245 while(xs.hasNext && !none) xs.next.apply(prms) match {
238 case None => none = true 246 case None => none = true
239 case Some(x) => builder += x 247 case Some(x) => builder += x
240 } 248 }
241 if(none) None else Some(builder.result()) 249 if(none) None else Some(builder.result())
242 }) 250 })
243 251
244 /** Wraps a generator lazily. The given parameter is only evalutated once, 252 /** Wraps a generator lazily. The given parameter is only evalutated once,
245 * and not until the wrapper generator is evaluated. */ 253 * and not until the wrapper generator is evaluated. */
246 def lzy[T](g: => Gen[T]) = new Gen[T] { 254 def lzy[T](g: => Gen[T]) = new Gen[T] {
247 lazy val h = g 255 lazy val h = g
248 def apply(prms: Params) = h(prms) 256 def apply(prms: Params) = h(prms)
249 } 257 }
250 258
251 /** Wraps a generator for later evaluation. The given parameter is 259 /** Wraps a generator for later evaluation. The given parameter is
252 * evaluated each time the wrapper generator is evaluated. */ 260 * evaluated each time the wrapper generator is evaluated. */
253 def wrap[T](g: => Gen[T]) = Gen(p => g(p)) 261 def wrap[T](g: => Gen[T]) = Gen(p => g(p))
254 262
255 /** A generator that always generates the given value */ 263 /** A generator that always generates the given value */
256 implicit def value[T](x: T) = Gen(p => Some(x)) 264 implicit def value[T](x: T) = Gen(p => Some(x))
257 265
258 /** A generator that never generates a value */ 266 /** A generator that never generates a value */
259 def fail[T]: Gen[T] = Gen(p => None) 267 def fail[T]: Gen[T] = Gen(p => None)
260 268
261 /** A generator that generates a random value in the given (inclusive) 269 /** A generator that generates a random value in the given (inclusive)
262 * range. If the range is invalid, the generator will not generate any value. 270 * range. If the range is invalid, the generator will not generate any value.
263 */ 271 */
264 def choose[T](min: T, max: T)(implicit c: Choose[T]): Gen[T] = { 272 def choose[T](min: T, max: T)(implicit c: Choose[T]): Gen[T] = {
265 c.choose(min, max) 273 c.choose(min, max)
266 } 274 }
267 275
268 /** Creates a generator that can access its generation parameters */ 276 /** Creates a generator that can access its generation parameters */
269 def parameterized[T](f: Params => Gen[T]): Gen[T] = Gen(prms => f(prms)(prms)) 277 def parameterized[T](f: Params => Gen[T]): Gen[T] = Gen(prms => f(prms)(prms))
270 278
271 /** Creates a generator that can access its generation size */ 279 /** Creates a generator that can access its generation size */
272 def sized[T](f: Int => Gen[T]) = parameterized(prms => f(prms.size)) 280 def sized[T](f: Int => Gen[T]) = parameterized(prms => f(prms.size))
273 281
274 /** Creates a resized version of a generator */ 282 /** Creates a resized version of a generator */
275 def resize[T](s: Int, g: Gen[T]) = Gen(prms => g(prms.resize(s))) 283 def resize[T](s: Int, g: Gen[T]) = Gen(prms => g(prms.resize(s)))
276 284
277 /** Chooses one of the given generators with a weighted random distribution */ 285 /** Chooses one of the given generators with a weighted random distribution */
278 def frequency[T](gs: (Int,Gen[T])*): Gen[T] = { 286 def frequency[T](gs: (Int,Gen[T])*): Gen[T] = {
279 lazy val tot = (gs.map(_._1) :\ 0) (_+_) 287 lazy val tot = (gs.map(_._1) :\ 0) (_+_)
280 288
281 def pick(n: Int, l: List[(Int,Gen[T])]): Gen[T] = l match { 289 def pick(n: Int, l: List[(Int,Gen[T])]): Gen[T] = l match {
282 case Nil => fail 290 case Nil => fail
283 case (k,g)::gs => if(n <= k) g else pick(n-k, gs) 291 case (k,g)::gs => if(n <= k) g else pick(n-k, gs)
284 } 292 }
285 293
286 for { 294 for {
287 n <- choose(1,tot) 295 n <- choose(1,tot)
288 x <- pick(n,gs.toList) 296 x <- pick(n,gs.toList)
289 } yield x 297 } yield x
290 } 298 }
291 299
292 /** Picks a random value from a list */ 300 /** Picks a random value from a list */
293 def oneOf[T](xs: Seq[T]): Gen[T] = if(xs.isEmpty) fail else for { 301 def oneOf[T](xs: Seq[T]): Gen[T] = if(xs.isEmpty) fail else for {
294 i <- choose(0, xs.size-1) 302 i <- choose(0, xs.size-1)
295 } yield xs(i) 303 } yield xs(i)
296 304
297 /** Picks a random generator from a list */ 305 /** Picks a random generator from a list */
298 def oneOf[T](g1: Gen[T], g2: Gen[T], gs: Gen[T]*) = for { 306 def oneOf[T](g1: Gen[T], g2: Gen[T], gs: Gen[T]*) = for {
299 i <- choose(0, gs.length+1) 307 i <- choose(0, gs.length+1)
300 x <- if(i == 0) g1 else if(i == 1) g2 else gs(i-2) 308 x <- if(i == 0) g1 else if(i == 1) g2 else gs(i-2)
301 } yield x 309 } yield x
302 310
303 /** Chooses one of the given values, with a weighted random distribution. 311 /** Chooses one of the given values, with a weighted random distribution.
304 * @deprecated Use <code>frequency</code> with constant generators 312 * @deprecated Use <code>frequency</code> with constant generators
305 * instead. */ 313 * instead. */
306 @deprecated("Use 'frequency' with constant generators instead.") 314 @deprecated("Use 'frequency' with constant generators instead.")
307 def elementsFreq[T](vs: (Int, T)*): Gen[T] = 315 def elementsFreq[T](vs: (Int, T)*): Gen[T] =
308 frequency(vs.map { case (w,v) => (w, value(v)) } : _*) 316 frequency(vs.map { case (w,v) => (w, value(v)) } : _*)
309 317
310 /** A generator that returns a random element from a list 318 /** A generator that returns a random element from a list
311 * @deprecated Use <code>oneOf</code> with constant generators instead. */ 319 * @deprecated Use <code>oneOf</code> with constant generators instead. */
312 @deprecated("Use 'oneOf' with constant generators instead.") 320 @deprecated("Use 'oneOf' with constant generators instead.")
313 def elements[T](xs: T*): Gen[T] = if(xs.isEmpty) fail else for { 321 def elements[T](xs: T*): Gen[T] = if(xs.isEmpty) fail else for {
314 i <- choose(0,xs.length-1) 322 i <- choose(0,xs.length-1)
315 } yield xs(i) 323 } yield xs(i)
316 324
317 325
318 //// List Generators //// 326 //// List Generators ////
319 327
320 /** Generates a container of any type for which there exists an implicit 328 /** Generates a container of any type for which there exists an implicit
321 * <code>Buildable</code> instance. The elements in the container will 329 * <code>Buildable</code> instance. The elements in the container will
322 * be generated by the given generator. The size of the generated container 330 * be generated by the given generator. The size of the generated container
323 * is given by <code>n</code>. */ 331 * is given by <code>n</code>. */
324 def containerOfN[C[_],T](n: Int, g: Gen[T])(implicit b: Buildable[T,C] 332 def containerOfN[C[_],T](n: Int, g: Gen[T])(implicit b: Buildable[T,C]
325 ): Gen[C[T]] = sequence[C,T](new Iterable[Gen[T]] { 333 ): Gen[C[T]] = sequence[C,T](new Iterable[Gen[T]] {
326 def iterator = new Iterator[Gen[T]] { 334 def iterator = new Iterator[Gen[T]] {
327 var i = 0 335 var i = 0
328 def hasNext = i < n 336 def hasNext = i < n
329 def next = { i += 1; g } 337 def next = { i += 1; g }
330 } 338 }
331 }) 339 })
332 340
333 /** Generates a container of any type for which there exists an implicit 341 /** Generates a container of any type for which there exists an implicit
334 * <code>Buildable</code> instance. The elements in the container will 342 * <code>Buildable</code> instance. The elements in the container will
335 * be generated by the given generator. The size of the container is 343 * be generated by the given generator. The size of the container is
336 * bounded by the size parameter used when generating values. */ 344 * bounded by the size parameter used when generating values. */
337 def containerOf[C[_],T](g: Gen[T])(implicit b: Buildable[T,C]): Gen[C[T]] = 345 def containerOf[C[_],T](g: Gen[T])(implicit b: Buildable[T,C]): Gen[C[T]] =
338 sized(size => for(n <- choose(0,size); c <- containerOfN[C,T](n,g)) yield c) 346 sized(size => for(n <- choose(0,size); c <- containerOfN[C,T](n,g)) yield c)
339 347
340 /** Generates a non-empty container of any type for which there exists an 348 /** Generates a non-empty container of any type for which there exists an
341 * implicit <code>Buildable</code> instance. The elements in the container 349 * implicit <code>Buildable</code> instance. The elements in the container
342 * will be generated by the given generator. The size of the container is 350 * will be generated by the given generator. The size of the container is
343 * bounded by the size parameter used when generating values. */ 351 * bounded by the size parameter used when generating values. */
344 def containerOf1[C[_],T](g: Gen[T])(implicit b: Buildable[T,C]): Gen[C[T]] = 352 def containerOf1[C[_],T](g: Gen[T])(implicit b: Buildable[T,C]): Gen[C[T]] =
345 sized(size => for(n <- choose(1,size); c <- containerOfN[C,T](n,g)) yield c) 353 sized(size => for(n <- choose(1,size); c <- containerOfN[C,T](n,g)) yield c)
346 354
347 /** Generates a list of random length. The maximum length depends on the 355 /** Generates a list of random length. The maximum length depends on the
348 * size parameter. This method is equal to calling 356 * size parameter. This method is equal to calling
349 * <code>containerOf[List,T](g)</code>. */ 357 * <code>containerOf[List,T](g)</code>. */
350 def listOf[T](g: => Gen[T]) = containerOf[List,T](g) 358 def listOf[T](g: => Gen[T]) = containerOf[List,T](g)
351 359
352 /** Generates a non-empty list of random length. The maximum length depends 360 /** Generates a non-empty list of random length. The maximum length depends
353 * on the size parameter. This method is equal to calling 361 * on the size parameter. This method is equal to calling
354 * <code>containerOf1[List,T](g)</code>. */ 362 * <code>containerOf1[List,T](g)</code>. */
355 def listOf1[T](g: => Gen[T]) = containerOf1[List,T](g) 363 def listOf1[T](g: => Gen[T]) = containerOf1[List,T](g)
356 364
357 /** Generates a list of the given length. This method is equal to calling 365 /** Generates a list of the given length. This method is equal to calling
358 * <code>containerOfN[List,T](n,g)</code>. */ 366 * <code>containerOfN[List,T](n,g)</code>. */
359 def listOfN[T](n: Int, g: Gen[T]) = containerOfN[List,T](n,g) 367 def listOfN[T](n: Int, g: Gen[T]) = containerOfN[List,T](n,g)
360 368
361 /** Generates a list of the given length. This method is equal to calling 369 /** Generates a list of the given length. This method is equal to calling
362 * <code>containerOfN[List,T](n,g)</code>. 370 * <code>containerOfN[List,T](n,g)</code>.
363 * @deprecated Use the method <code>listOfN</code> instead. */ 371 * @deprecated Use the method <code>listOfN</code> instead. */
364 @deprecated("Use 'listOfN' instead.") 372 @deprecated("Use 'listOfN' instead.")
365 def vectorOf[T](n: Int, g: Gen[T]) = containerOfN[List,T](n,g) 373 def vectorOf[T](n: Int, g: Gen[T]) = containerOfN[List,T](n,g)
366 374
367 /** A generator that picks a random number of elements from a list */ 375 /** A generator that picks a random number of elements from a list */
368 def someOf[T](l: Iterable[T]) = choose(0,l.size) flatMap (pick(_,l)) 376 def someOf[T](l: Iterable[T]) = choose(0,l.size) flatMap (pick(_,l))
369 377
370 /** A generator that picks a random number of elements from a list */ 378 /** A generator that picks a random number of elements from a list */
371 def someOf[T](g1: Gen[T], g2: Gen[T], gs: Gen[T]*) = for { 379 def someOf[T](g1: Gen[T], g2: Gen[T], gs: Gen[T]*) = for {
372 n <- choose(0, gs.length+2) 380 n <- choose(0, gs.length+2)
373 x <- pick(n, g1, g2, gs: _*) 381 x <- pick(n, g1, g2, gs: _*)
374 } yield x 382 } yield x
375 383
376 /** A generator that picks a given number of elements from a list, randomly */ 384 /** A generator that picks a given number of elements from a list, randomly */
377 def pick[T](n: Int, l: Iterable[T]): Gen[Seq[T]] = 385 def pick[T](n: Int, l: Iterable[T]): Gen[Seq[T]] =
378 if(n > l.size || n < 0) fail 386 if(n > l.size || n < 0) fail
379 else Gen(prms => { 387 else Gen(prms => {
380 val buf = new ListBuffer[T] 388 val buf = new ListBuffer[T]
381 buf ++= l 389 buf ++= l
382 while(buf.length > n) { 390 while(buf.length > n) {
383 val g = choose(0, buf.length-1) 391 val g = choose(0, buf.length-1)
384 buf.remove(g(prms).get) 392 buf.remove(g(prms).get)
385 } 393 }
386 Some(buf) 394 Some(buf)
387 }) 395 })
388 396
389 /** A generator that picks a given number of elements from a list, randomly */ 397 /** A generator that picks a given number of elements from a list, randomly */
390 def pick[T](n: Int, g1: Gen[T], g2: Gen[T], gs: Gen[T]*): Gen[Seq[T]] = for { 398 def pick[T](n: Int, g1: Gen[T], g2: Gen[T], gs: Gen[T]*): Gen[Seq[T]] = for {
391 is <- pick(n, 0 until (gs.size+2)) 399 is <- pick(n, 0 until (gs.size+2))
392 allGs = gs ++ (g1::g2::Nil) 400 allGs = gs ++ (g1::g2::Nil)
393 xs <- sequence[List,T](is.toList.map(allGs(_))) 401 xs <- sequence[List,T](is.toList.map(allGs(_)))
394 } yield xs 402 } yield xs
395 403
396 404
397 //// Character Generators //// 405 //// Character Generators ////
398 406
399 /* Generates a numerical character */ 407 /* Generates a numerical character */
400 def numChar: Gen[Char] = choose(48,57) map (_.toChar) 408 def numChar: Gen[Char] = choose(48,57) map (_.toChar)
401 409
402 /* Generates an upper-case alpha character */ 410 /* Generates an upper-case alpha character */
403 def alphaUpperChar: Gen[Char] = choose(65,90) map (_.toChar) 411 def alphaUpperChar: Gen[Char] = choose(65,90) map (_.toChar)
404 412
405 /* Generates a lower-case alpha character */ 413 /* Generates a lower-case alpha character */
406 def alphaLowerChar: Gen[Char] = choose(97,122) map (_.toChar) 414 def alphaLowerChar: Gen[Char] = choose(97,122) map (_.toChar)
407 415
408 /* Generates an alpha character */ 416 /* Generates an alpha character */
409 def alphaChar = frequency((1,alphaUpperChar), (9,alphaLowerChar)) 417 def alphaChar = frequency((1,alphaUpperChar), (9,alphaLowerChar))
410 418
411 /* Generates an alphanumerical character */ 419 /* Generates an alphanumerical character */
412 def alphaNumChar = frequency((1,numChar), (9,alphaChar)) 420 def alphaNumChar = frequency((1,numChar), (9,alphaChar))
413 421
414 //// String Generators //// 422 //// String Generators ////
415 423
416 /* Generates a string that starts with a lower-case alpha character, 424 /* Generates a string that starts with a lower-case alpha character,
417 * and only contains alphanumerical characters */ 425 * and only contains alphanumerical characters */
418 def identifier: Gen[String] = for { 426 def identifier: Gen[String] = for {
419 c <- alphaLowerChar 427 c <- alphaLowerChar
420 cs <- listOf(alphaNumChar) 428 cs <- listOf(alphaNumChar)
421 } yield (c::cs).mkString 429 } yield (c::cs).mkString
422 430
423 /* Generates a string of alpha characters */ 431 /* Generates a string of alpha characters */
424 def alphaStr: Gen[String] = for(cs <- listOf(Gen.alphaChar)) yield cs.mkString 432 def alphaStr: Gen[String] = for(cs <- listOf(Gen.alphaChar)) yield cs.mkString
425 433
426 /* Generates a string of digits */ 434 /* Generates a string of digits */
427 def numStr: Gen[String] = for(cs <- listOf(Gen.numChar)) yield cs.mkString 435 def numStr: Gen[String] = for(cs <- listOf(Gen.numChar)) yield cs.mkString
428 436
429 //// Number Generators //// 437 //// Number Generators ////
430 438
431 /* Generates positive integers 439 /* Generates positive integers
432 * @deprecated Use <code>posNum[Int]code> instead */ 440 * @deprecated Use <code>posNum[Int]code> instead */
433 @deprecated("Use posNum[Int] instead") 441 @deprecated("Use posNum[Int] instead")
434 def posInt: Gen[Int] = sized(max => choose(1, max)) 442 def posInt: Gen[Int] = sized(max => choose(1, max))
435 443
436 /* Generates negative integers 444 /* Generates negative integers
437 * @deprecated Use <code>negNum[Int]code> instead */ 445 * @deprecated Use <code>negNum[Int]code> instead */
438 @deprecated("Use negNum[Int] instead") 446 @deprecated("Use negNum[Int] instead")
439 def negInt: Gen[Int] = sized(max => choose(-max, -1)) 447 def negInt: Gen[Int] = sized(max => choose(-max, -1))
440 448
441 /** Generates positive numbers of uniform distribution, with an 449 /** Generates positive numbers of uniform distribution, with an
442 * upper bound of the generation size parameter. */ 450 * upper bound of the generation size parameter. */
443 def posNum[T](implicit num: Numeric[T], c: Choose[T]): Gen[T] = { 451 def posNum[T](implicit num: Numeric[T], c: Choose[T]): Gen[T] = {
444 import num._ 452 import num._
445 sized(max => c.choose(one, fromInt(max))) 453 sized(max => c.choose(one, fromInt(max)))
446 } 454 }
447 455
448 /** Generates negative numbers of uniform distribution, with an 456 /** Generates negative numbers of uniform distribution, with an
449 * lower bound of the negated generation size parameter. */ 457 * lower bound of the negated generation size parameter. */
450 def negNum[T](implicit num: Numeric[T], c: Choose[T]): Gen[T] = { 458 def negNum[T](implicit num: Numeric[T], c: Choose[T]): Gen[T] = {
451 import num._ 459 import num._
452 sized(max => c.choose(-fromInt(max), -one)) 460 sized(max => c.choose(-fromInt(max), -one))
453 } 461 }
454 462
455 /** Generates numbers within the given inclusive range, with 463 /** Generates numbers within the given inclusive range, with
456 * extra weight on zero, +/- unity, both extremities, and any special 464 * extra weight on zero, +/- unity, both extremities, and any special
457 * numbers provided. The special numbers must lie within the given range, 465 * numbers provided. The special numbers must lie within the given range,
458 * otherwise they won't be included. */ 466 * otherwise they won't be included. */
459 def chooseNum[T](minT: T, maxT: T, specials: T*)( 467 def chooseNum[T](minT: T, maxT: T, specials: T*)(
460 implicit num: Numeric[T], c: Choose[T] 468 implicit num: Numeric[T], c: Choose[T]
461 ): Gen[T] = { 469 ): Gen[T] = {
462 import num._ 470 import num._
463 val basics = List(minT, maxT, zero, one, -one) 471 val basics = List(minT, maxT, zero, one, -one)
464 val basicsAndSpecials = for { 472 val basicsAndSpecials = for {
465 t <- specials ++ basics if t >= minT && t <= maxT 473 t <- specials ++ basics if t >= minT && t <= maxT
466 } yield (1, value(t)) 474 } yield (1, value(t))
467 val allGens = basicsAndSpecials ++ List( 475 val allGens = basicsAndSpecials ++ List(
468 (basicsAndSpecials.length, c.choose(minT, maxT)) 476 (basicsAndSpecials.length, c.choose(minT, maxT))
469 ) 477 )
470 frequency(allGens: _*) 478 frequency(allGens: _*)
471 } 479 }
472 } 480 }
Powered by Google Project Hosting