summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.sbt5
-rw-r--r--build.xml21
-rw-r--r--doc/LICENSE.md1
-rw-r--r--doc/licenses/bsd_scalacheck.txt32
-rw-r--r--src/partest-extras/scala/org/scalacheck/Arbitrary.scala433
-rw-r--r--src/partest-extras/scala/org/scalacheck/Commands.scala146
-rw-r--r--src/partest-extras/scala/org/scalacheck/Commands2.scala150
-rw-r--r--src/partest-extras/scala/org/scalacheck/Gen.scala813
-rw-r--r--src/partest-extras/scala/org/scalacheck/Prop.scala953
-rw-r--r--src/partest-extras/scala/org/scalacheck/Properties.scala82
-rw-r--r--src/partest-extras/scala/org/scalacheck/ScalaCheckFramework.scala93
-rw-r--r--src/partest-extras/scala/org/scalacheck/Shrink.scala215
-rw-r--r--src/partest-extras/scala/org/scalacheck/Test.scala372
-rw-r--r--src/partest-extras/scala/org/scalacheck/util/Buildable.scala77
-rw-r--r--src/partest-extras/scala/org/scalacheck/util/CmdLineParser.scala41
-rw-r--r--src/partest-extras/scala/org/scalacheck/util/ConsoleReporter.scala44
-rw-r--r--src/partest-extras/scala/org/scalacheck/util/FreqMap.scala65
-rw-r--r--src/partest-extras/scala/org/scalacheck/util/Pretty.scala129
-rw-r--r--versions.properties4
19 files changed, 3653 insertions, 23 deletions
diff --git a/build.sbt b/build.sbt
index 20ae42b3e6..1d4e208da2 100644
--- a/build.sbt
+++ b/build.sbt
@@ -60,7 +60,6 @@ val scalaParserCombinatorsDep = scalaDep("org.scala-lang.modules", "scala-par
val scalaSwingDep = scalaDep("org.scala-lang.modules", "scala-swing")
val scalaXmlDep = scalaDep("org.scala-lang.modules", "scala-xml")
val partestDep = scalaDep("org.scala-lang.modules", "scala-partest", versionProp = "partest")
-val scalacheckDep = scalaDep("org.scalacheck", "scalacheck", scope = "it")
// Non-Scala dependencies:
val junitDep = "junit" % "junit" % "4.11"
@@ -562,6 +561,7 @@ lazy val junit = project.in(file("test") / "junit")
fork in Test := true,
libraryDependencies ++= Seq(junitDep, junitInterfaceDep, jolDep),
testOptions += Tests.Argument(TestFrameworks.JUnit, "-a", "-v"),
+ testFrameworks -= new TestFramework("org.scalacheck.ScalaCheckFramework"),
unmanagedSourceDirectories in Test := List(baseDirectory.value)
)
@@ -642,7 +642,7 @@ lazy val test = project
.settings(disablePublishing: _*)
.settings(Defaults.itSettings: _*)
.settings(
- libraryDependencies ++= Seq(asmDep, partestDep, scalaXmlDep, scalacheckDep),
+ libraryDependencies ++= Seq(asmDep, partestDep, scalaXmlDep),
libraryDependencies ++= {
// Resolve the JARs for all test/files/lib/*.jar.desired.sha1 files through Ivy
val baseDir = (baseDirectory in ThisBuild).value
@@ -659,6 +659,7 @@ lazy val test = project
fork in IntegrationTest := true,
javaOptions in IntegrationTest += "-Xmx2G",
testFrameworks += new TestFramework("scala.tools.partest.sbt.Framework"),
+ testFrameworks -= new TestFramework("org.scalacheck.ScalaCheckFramework"),
testOptions in IntegrationTest += Tests.Argument("-Dpartest.java_opts=-Xmx1024M -Xms64M -XX:MaxPermSize=128M"),
testOptions in IntegrationTest += Tests.Argument("-Dpartest.scalac_opts=" + (scalacOptions in Compile).value.mkString(" ")),
testOptions in IntegrationTest += Tests.Setup { () =>
diff --git a/build.xml b/build.xml
index 519d3597cc..6b2c9ade0d 100644
--- a/build.xml
+++ b/build.xml
@@ -319,7 +319,6 @@ TODO:
<prepareCross name="scala-parser-combinators" />
<prepareCross name="scala-swing"/>
<prepareCross name="partest"/>
- <prepareCross name="scalacheck"/>
<artifact:dependencies pathId="asm.classpath" filesetId="asm.fileset">
<dependency groupId="org.scala-lang.modules" artifactId="scala-asm" version="${scala-asm.version}"/>
@@ -339,11 +338,6 @@ TODO:
</artifact:dependencies>
<copy-deps project="partest"/>
- <artifact:dependencies pathId="scalacheck.classpath" filesetId="scalacheck.fileset" versionsId="scalacheck.versions">
- <artifact:remoteRepository refid="extra-repo"/>
- <dependency groupId="org.scalacheck" artifactId="scalacheck${scalacheck.cross}" version="${scalacheck.version.number}" />
- </artifact:dependencies>
-
<artifact:dependencies pathId="repl.deps.classpath" filesetId="repl.fileset" versionsId="repl.deps.versions">
<dependency groupId="jline" artifactId="jline" version="${jline.version}"/>
</artifact:dependencies>
@@ -567,7 +561,6 @@ TODO:
<echo message="scala-swing.version.number = ${scala-swing.version.number}"/>
<echo message="jline.version = ${jline.version}"/>
<echo message="partest.version.number = ${partest.version.number}"/>
- <echo message="scalacheck.version.number = ${scalacheck.version.number}"/>
<propertyfile file="versions.properties">
<entry key="starr.version" value="${starr.version}"/>
@@ -577,7 +570,6 @@ TODO:
<entry key="scala-swing.version.number" value="${scala-swing.version.number}"/>
<entry key="jline.version" value="${jline.version}"/>
<entry key="partest.version.number" value="${partest.version.number}"/>
- <entry key="scalacheck.version.number" value="${scalacheck.version.number}"/>
</propertyfile>
</then></if>
@@ -922,7 +914,7 @@ TODO:
(but not scala-library, so we filter that one out...)
so we provide them: scala-[library/reflect/compiler], scalap built here,
scala-xml, scala-parser-combinators via external-modules-nocore,
- scalacheck as part of `partest.classpath` -->
+ as part of `partest.classpath` -->
<restrict>
<path refid="partest.classpath"/>
<rsel:not><rsel:or>
@@ -933,17 +925,6 @@ TODO:
<pathelement location="${scala-parser-combinators}"/>
<!-- <pathelement location="${scala-swing}"/> -->
- <restrict>
- <path refid="scalacheck.classpath"/>
- <rsel:not><rsel:or>
- <rsel:name name="scala-library*.jar"/>
- <rsel:name name="scala-compiler*.jar"/>
- <rsel:name name="scala-reflect*.jar"/>
- <rsel:name name="scala-parser-combinators*.jar"/>
- <rsel:name name="scala-xml*.jar"/>
- </rsel:or></rsel:not>
- </restrict>
-
<!-- partest classes specific to the core compiler build -->
<pathelement location="${partest-extras.jar}"/>
<pathelement location="${partest-javaagent.jar}"/>
diff --git a/doc/LICENSE.md b/doc/LICENSE.md
index a07ba32e0b..0718c43e05 100644
--- a/doc/LICENSE.md
+++ b/doc/LICENSE.md
@@ -46,6 +46,7 @@ This license is used by the following third-party libraries:
This license is used by the following third-party libraries:
* jline
+ * scalacheck
### [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause)
This license is used by the following third-party libraries:
diff --git a/doc/licenses/bsd_scalacheck.txt b/doc/licenses/bsd_scalacheck.txt
new file mode 100644
index 0000000000..f1920752e0
--- /dev/null
+++ b/doc/licenses/bsd_scalacheck.txt
@@ -0,0 +1,32 @@
+ScalaCheck LICENSE
+
+Copyright (c) 2007-2013, Rickard Nilsson
+All rights reserved.
+
+Permission to use, copy, modify, and distribute this software in source
+or binary form for any purpose with or without fee is hereby granted,
+provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the author nor the names of its contributors
+ may be used to endorse or promote products derived from this
+ software without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
diff --git a/src/partest-extras/scala/org/scalacheck/Arbitrary.scala b/src/partest-extras/scala/org/scalacheck/Arbitrary.scala
new file mode 100644
index 0000000000..1cbd668f0c
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/Arbitrary.scala
@@ -0,0 +1,433 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck
+
+import util.{FreqMap, Buildable, Buildable2}
+
+
+sealed abstract class Arbitrary[T] {
+ val arbitrary: Gen[T]
+}
+
+/** Defines implicit [[org.scalacheck.Arbitrary]] instances for common types.
+ * <p>
+ * ScalaCheck
+ * uses implicit [[org.scalacheck.Arbitrary]] instances when creating properties
+ * out of functions with the `Prop.property` method, and when
+ * the `Arbitrary.arbitrary` method is used. For example, the
+ * following code requires that there exists an implicit
+ * `Arbitrary[MyClass]` instance:
+ * </p>
+ *
+ * {{{
+ * val myProp = Prop.forAll { myClass: MyClass =>
+ * ...
+ * }
+ *
+ * val myGen = Arbitrary.arbitrary[MyClass]
+ * }}}
+ *
+ * <p>
+ * The required implicit definition could look like this:
+ * </p>
+ *
+ * {{{
+ * implicit val arbMyClass: Arbitrary[MyClass] = Arbitrary(...)
+ * }}}
+ *
+ * <p>
+ * The factory method `Arbitrary(...)` takes a generator of type
+ * `Gen[T]` and returns an instance of `Arbitrary[T]`.
+ * </p>
+ *
+ * <p>
+ * The `Arbitrary` module defines implicit [[org.scalacheck.Arbitrary]]
+ * instances for common types, for convenient use in your properties and
+ * generators.
+ * </p>
+ */
+object Arbitrary {
+
+ import Gen.{const, choose, sized, frequency, oneOf, containerOf, resize}
+ import collection.{immutable, mutable}
+ import java.util.Date
+
+ /** Creates an Arbitrary instance */
+ def apply[T](g: => Gen[T]): Arbitrary[T] = new Arbitrary[T] {
+ lazy val arbitrary = g
+ }
+
+ /** Returns an arbitrary generator for the type T. */
+ def arbitrary[T](implicit a: Arbitrary[T]): Gen[T] = a.arbitrary
+
+ /**** Arbitrary instances for each AnyVal ****/
+
+ /** Arbitrary AnyVal */
+ implicit lazy val arbAnyVal: Arbitrary[AnyVal] = Arbitrary(oneOf(
+ arbitrary[Unit], arbitrary[Boolean], arbitrary[Char], arbitrary[Byte],
+ arbitrary[Short], arbitrary[Int], arbitrary[Long], arbitrary[Float],
+ arbitrary[Double]
+ ))
+
+ /** Arbitrary instance of Boolean */
+ implicit lazy val arbBool: Arbitrary[Boolean] =
+ Arbitrary(oneOf(true, false))
+
+ /** Arbitrary instance of Int */
+ implicit lazy val arbInt: Arbitrary[Int] = Arbitrary(
+ Gen.chooseNum(Int.MinValue, Int.MaxValue)
+ )
+
+ /** Arbitrary instance of Long */
+ implicit lazy val arbLong: Arbitrary[Long] = Arbitrary(
+ Gen.chooseNum(Long.MinValue, Long.MaxValue)
+ )
+
+ /** Arbitrary instance of Float */
+ implicit lazy val arbFloat: Arbitrary[Float] = Arbitrary(
+ Gen.chooseNum(
+ Float.MinValue, Float.MaxValue
+ // I find that including these by default is a little TOO testy.
+ // Float.Epsilon, Float.NaN, Float.PositiveInfinity, Float.NegativeInfinity
+ )
+ )
+
+ /** Arbitrary instance of Double */
+ implicit lazy val arbDouble: Arbitrary[Double] = Arbitrary(
+ Gen.chooseNum(
+ Double.MinValue / 2, Double.MaxValue / 2
+ // As above. Perhaps behind some option?
+ // Double.Epsilon, Double.NaN, Double.PositiveInfinity, Double.NegativeInfinity
+ )
+ )
+
+ /** Arbitrary instance of Char */
+ implicit lazy val arbChar: Arbitrary[Char] = Arbitrary(
+ Gen.frequency(
+ (0xD800-Char.MinValue, Gen.choose[Char](Char.MinValue,0xD800-1)),
+ (Char.MaxValue-0xDFFF, Gen.choose[Char](0xDFFF+1,Char.MaxValue))
+ )
+ )
+
+ /** Arbitrary instance of Byte */
+ implicit lazy val arbByte: Arbitrary[Byte] = Arbitrary(
+ Gen.chooseNum(Byte.MinValue, Byte.MaxValue)
+ )
+
+ /** Arbitrary instance of Short */
+ implicit lazy val arbShort: Arbitrary[Short] = Arbitrary(
+ Gen.chooseNum(Short.MinValue, Short.MaxValue)
+ )
+
+ /** Absolutely, totally, 100% arbitrarily chosen Unit. */
+ implicit lazy val arbUnit: Arbitrary[Unit] = Arbitrary(const(()))
+
+ /**** Arbitrary instances of other common types ****/
+
+ /** Arbitrary instance of String */
+ implicit lazy val arbString: Arbitrary[String] =
+ Arbitrary(arbitrary[List[Char]] map (_.mkString))
+
+ /** Arbitrary instance of Date */
+ implicit lazy val arbDate: Arbitrary[Date] = Arbitrary(for {
+ l <- arbitrary[Long]
+ d = new Date
+ } yield new Date(d.getTime + l))
+
+ /** Arbitrary instance of Throwable */
+ implicit lazy val arbThrowable: Arbitrary[Throwable] =
+ Arbitrary(oneOf(const(new Exception), const(new Error)))
+
+ /** Arbitrary instance of Exception */
+ implicit lazy val arbException: Arbitrary[Exception] =
+ Arbitrary(const(new Exception))
+
+ /** Arbitrary instance of Error */
+ implicit lazy val arbError: Arbitrary[Error] =
+ Arbitrary(const(new Error))
+
+ /** Arbitrary BigInt */
+ implicit lazy val arbBigInt: Arbitrary[BigInt] = {
+ def chooseBigInt: Gen[BigInt] =
+ sized((s: Int) => choose(-s, s)) map (x => BigInt(x))
+
+ def chooseReallyBigInt: Gen[BigInt] = for {
+ bi <- chooseBigInt
+ n <- choose(32,128)
+ } yield bi << n
+
+ Arbitrary(
+ frequency(
+ (5, chooseBigInt),
+ (10, chooseReallyBigInt),
+ (1, BigInt(0)),
+ (1, BigInt(1)),
+ (1, BigInt(-1)),
+ (1, BigInt(Int.MaxValue) + 1),
+ (1, BigInt(Int.MinValue) - 1),
+ (1, BigInt(Long.MaxValue)),
+ (1, BigInt(Long.MinValue)),
+ (1, BigInt(Long.MaxValue) + 1),
+ (1, BigInt(Long.MinValue) - 1)
+ )
+ )
+ }
+
+ /** Arbitrary BigDecimal */
+ implicit lazy val arbBigDecimal: Arbitrary[BigDecimal] = {
+ import java.math.MathContext._
+ val mcGen = oneOf(UNLIMITED, DECIMAL32, DECIMAL64, DECIMAL128)
+ val bdGen = for {
+ x <- arbBigInt.arbitrary
+ mc <- mcGen
+ limit <- const(if(mc == UNLIMITED) 0 else math.max(x.abs.toString.length - mc.getPrecision, 0))
+ scale <- Gen.chooseNum(Int.MinValue + limit , Int.MaxValue)
+ } yield {
+ try {
+ BigDecimal(x, scale, mc)
+ } catch {
+ case ae: java.lang.ArithmeticException => BigDecimal(x, scale, UNLIMITED) // Handle the case where scale/precision conflict
+ }
+ }
+ Arbitrary(bdGen)
+ }
+
+ /** Arbitrary java.lang.Number */
+ implicit lazy val arbNumber: Arbitrary[Number] = {
+ val gen = Gen.oneOf(
+ arbitrary[Byte], arbitrary[Short], arbitrary[Int], arbitrary[Long],
+ arbitrary[Float], arbitrary[Double]
+ )
+ Arbitrary(gen map (_.asInstanceOf[Number]))
+ // XXX TODO - restore BigInt and BigDecimal
+ // Arbitrary(oneOf(arbBigInt.arbitrary :: (arbs map (_.arbitrary) map toNumber) : _*))
+ }
+
+ /** Generates an arbitrary property */
+ implicit lazy val arbProp: Arbitrary[Prop] = {
+ import Prop._
+ val undecidedOrPassed = forAll { b: Boolean =>
+ b ==> true
+ }
+ Arbitrary(frequency(
+ (4, falsified),
+ (4, passed),
+ (3, proved),
+ (3, undecidedOrPassed),
+ (2, undecided),
+ (1, exception(null))
+ ))
+ }
+
+ /** Arbitrary instance of test parameters */
+ implicit lazy val arbTestParameters: Arbitrary[Test.Parameters] =
+ Arbitrary(for {
+ _minSuccTests <- choose(10,200)
+ _maxDiscardRatio <- choose(0.2f,10f)
+ _minSize <- choose(0,500)
+ sizeDiff <- choose(0,500)
+ _maxSize <- choose(_minSize, _minSize + sizeDiff)
+ _workers <- choose(1,4)
+ } yield new Test.Parameters.Default {
+ override val minSuccessfulTests = _minSuccTests
+ override val maxDiscardRatio = _maxDiscardRatio
+ override val minSize = _minSize
+ override val maxSize = _maxSize
+ override val workers = _workers
+ })
+
+ /** Arbitrary instance of gen params */
+ implicit lazy val arbGenParams: Arbitrary[Gen.Parameters] =
+ Arbitrary(for {
+ sz <- arbitrary[Int] suchThat (_ >= 0)
+ } yield (new Gen.Parameters.Default {
+ override val size = sz
+ }))
+
+
+ // Higher-order types //
+
+ /** Arbitrary instance of [[org.scalacheck.Gen]] */
+ implicit def arbGen[T](implicit a: Arbitrary[T]): Arbitrary[Gen[T]] =
+ Arbitrary(frequency(
+ (5, arbitrary[T] map (const(_))),
+ (1, Gen.fail)
+ ))
+
+ /** Arbitrary instance of the Option type */
+ implicit def arbOption[T](implicit a: Arbitrary[T]): Arbitrary[Option[T]] =
+ Arbitrary(sized(n =>
+ // When n is larger, make it less likely that we generate None,
+ // but still do it some of the time. When n is zero, we always
+ // generate None, since it's the smallest value.
+ frequency(
+ (n, resize(n / 2, arbitrary[T]).map(Some(_))),
+ (1, const(None)))))
+
+ /** Arbitrary instance of the Either type */
+ implicit def arbEither[T, U](implicit at: Arbitrary[T], au: Arbitrary[U]): Arbitrary[Either[T, U]] =
+ Arbitrary(oneOf(arbitrary[T].map(Left(_)), arbitrary[U].map(Right(_))))
+
+ /** Arbitrary instance of any [[org.scalacheck.util.Buildable]] container
+ * (such as lists, arrays, streams, etc). The maximum size of the container
+ * depends on the size generation parameter. */
+ implicit def arbContainer[C[_],T](implicit
+ a: Arbitrary[T], b: Buildable[T,C], t: C[T] => Traversable[T]
+ ): Arbitrary[C[T]] = Arbitrary(containerOf[C,T](arbitrary[T]))
+
+ /** Arbitrary instance of any [[org.scalacheck.util.Buildable2]] container
+ * (such as maps, etc). The maximum size of the container depends on the size
+ * generation parameter. */
+ implicit def arbContainer2[C[_,_],T,U](implicit
+ a: Arbitrary[(T,U)], b: Buildable2[T,U,C], t: C[T,U] => Traversable[(T,U)]
+ ): Arbitrary[C[T,U]] = Arbitrary(containerOf[C,T,U](arbitrary[(T,U)]))
+
+ // Functions //
+
+ /** Arbitrary instance of Function1 */
+ implicit def arbFunction1[T1,R](implicit a: Arbitrary[R]
+ ): Arbitrary[T1 => R] = Arbitrary(
+ for(r <- arbitrary[R]) yield (t1: T1) => r
+ )
+
+ /** Arbitrary instance of Function2 */
+ implicit def arbFunction2[T1,T2,R](implicit a: Arbitrary[R]
+ ): Arbitrary[(T1,T2) => R] = Arbitrary(
+ for(r <- arbitrary[R]) yield (t1: T1, t2: T2) => r
+ )
+
+ /** Arbitrary instance of Function3 */
+ implicit def arbFunction3[T1,T2,T3,R](implicit a: Arbitrary[R]
+ ): Arbitrary[(T1,T2,T3) => R] = Arbitrary(
+ for(r <- arbitrary[R]) yield (t1: T1, t2: T2, t3: T3) => r
+ )
+
+ /** Arbitrary instance of Function4 */
+ implicit def arbFunction4[T1,T2,T3,T4,R](implicit a: Arbitrary[R]
+ ): Arbitrary[(T1,T2,T3,T4) => R] = Arbitrary(
+ for(r <- arbitrary[R]) yield (t1: T1, t2: T2, t3: T3, t4: T4) => r
+ )
+
+ /** Arbitrary instance of Function5 */
+ implicit def arbFunction5[T1,T2,T3,T4,T5,R](implicit a: Arbitrary[R]
+ ): Arbitrary[(T1,T2,T3,T4,T5) => R] = Arbitrary(
+ for(r <- arbitrary[R]) yield (t1: T1, t2: T2, t3: T3, t4: T4, t5: T5) => r
+ )
+
+
+ // Tuples //
+
+ /** Arbitrary instance of 2-tuple */
+ implicit def arbTuple2[T1,T2](implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2]
+ ): Arbitrary[(T1,T2)] =
+ Arbitrary(for {
+ t1 <- arbitrary[T1]
+ t2 <- arbitrary[T2]
+ } yield (t1,t2))
+
+ /** Arbitrary instance of 3-tuple */
+ implicit def arbTuple3[T1,T2,T3](implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3]
+ ): Arbitrary[(T1,T2,T3)] =
+ Arbitrary(for {
+ t1 <- arbitrary[T1]
+ t2 <- arbitrary[T2]
+ t3 <- arbitrary[T3]
+ } yield (t1,t2,t3))
+
+ /** Arbitrary instance of 4-tuple */
+ implicit def arbTuple4[T1,T2,T3,T4](implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4]
+ ): Arbitrary[(T1,T2,T3,T4)] =
+ Arbitrary(for {
+ t1 <- arbitrary[T1]
+ t2 <- arbitrary[T2]
+ t3 <- arbitrary[T3]
+ t4 <- arbitrary[T4]
+ } yield (t1,t2,t3,t4))
+
+ /** Arbitrary instance of 5-tuple */
+ implicit def arbTuple5[T1,T2,T3,T4,T5](implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4],
+ a5: Arbitrary[T5]
+ ): Arbitrary[(T1,T2,T3,T4,T5)] =
+ Arbitrary(for {
+ t1 <- arbitrary[T1]
+ t2 <- arbitrary[T2]
+ t3 <- arbitrary[T3]
+ t4 <- arbitrary[T4]
+ t5 <- arbitrary[T5]
+ } yield (t1,t2,t3,t4,t5))
+
+ /** Arbitrary instance of 6-tuple */
+ implicit def arbTuple6[T1,T2,T3,T4,T5,T6](implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4],
+ a5: Arbitrary[T5], a6: Arbitrary[T6]
+ ): Arbitrary[(T1,T2,T3,T4,T5,T6)] =
+ Arbitrary(for {
+ t1 <- arbitrary[T1]
+ t2 <- arbitrary[T2]
+ t3 <- arbitrary[T3]
+ t4 <- arbitrary[T4]
+ t5 <- arbitrary[T5]
+ t6 <- arbitrary[T6]
+ } yield (t1,t2,t3,t4,t5,t6))
+
+ /** Arbitrary instance of 7-tuple */
+ implicit def arbTuple7[T1,T2,T3,T4,T5,T6,T7](implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4],
+ a5: Arbitrary[T5], a6: Arbitrary[T6], a7: Arbitrary[T7]
+ ): Arbitrary[(T1,T2,T3,T4,T5,T6,T7)] =
+ Arbitrary(for {
+ t1 <- arbitrary[T1]
+ t2 <- arbitrary[T2]
+ t3 <- arbitrary[T3]
+ t4 <- arbitrary[T4]
+ t5 <- arbitrary[T5]
+ t6 <- arbitrary[T6]
+ t7 <- arbitrary[T7]
+ } yield (t1,t2,t3,t4,t5,t6,t7))
+
+ /** Arbitrary instance of 8-tuple */
+ implicit def arbTuple8[T1,T2,T3,T4,T5,T6,T7,T8](implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4],
+ a5: Arbitrary[T5], a6: Arbitrary[T6], a7: Arbitrary[T7], a8: Arbitrary[T8]
+ ): Arbitrary[(T1,T2,T3,T4,T5,T6,T7,T8)] =
+ Arbitrary(for {
+ t1 <- arbitrary[T1]
+ t2 <- arbitrary[T2]
+ t3 <- arbitrary[T3]
+ t4 <- arbitrary[T4]
+ t5 <- arbitrary[T5]
+ t6 <- arbitrary[T6]
+ t7 <- arbitrary[T7]
+ t8 <- arbitrary[T8]
+ } yield (t1,t2,t3,t4,t5,t6,t7,t8))
+
+ /** Arbitrary instance of 9-tuple */
+ implicit def arbTuple9[T1,T2,T3,T4,T5,T6,T7,T8,T9](implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4],
+ a5: Arbitrary[T5], a6: Arbitrary[T6], a7: Arbitrary[T7], a8: Arbitrary[T8],
+ a9: Arbitrary[T9]
+ ): Arbitrary[(T1,T2,T3,T4,T5,T6,T7,T8,T9)] =
+ Arbitrary(for {
+ t1 <- arbitrary[T1]
+ t2 <- arbitrary[T2]
+ t3 <- arbitrary[T3]
+ t4 <- arbitrary[T4]
+ t5 <- arbitrary[T5]
+ t6 <- arbitrary[T6]
+ t7 <- arbitrary[T7]
+ t8 <- arbitrary[T8]
+ t9 <- arbitrary[T9]
+ } yield (t1,t2,t3,t4,t5,t6,t7,t8,t9))
+
+}
diff --git a/src/partest-extras/scala/org/scalacheck/Commands.scala b/src/partest-extras/scala/org/scalacheck/Commands.scala
new file mode 100644
index 0000000000..5ff3a397e5
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/Commands.scala
@@ -0,0 +1,146 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck
+
+/** See User Guide for usage examples */
+@deprecated("Will be replaced with a new implementation in 1.12.0", "1.11.4")
+trait Commands extends Prop {
+
+ /** The abstract state data type. This type must be immutable.
+ * The state type that encodes the abstract state. The abstract state
+ * should model all the features we need from the real state, the system
+ * under test. We should leave out all details that aren't needed for
+ * specifying our pre- and postconditions. The state type must be called
+ * State and be immutable. */
+ type State <: AnyRef
+
+ class Binding(private val key: State) {
+ def get: Any = bindings.find(_._1 eq key) match {
+ case None => sys.error("No value bound")
+ case Some(x) => x._2
+ }
+ }
+
+ /** Abstract commands are defined as subtypes of the traits Command or SetCommand.
+ * Each command must have a run method and a method that returns the new abstract
+ * state, as it should look after the command has been run.
+ * A command can also define a precondition that states how the current
+ * abstract state must look if the command should be allowed to run.
+ * Finally, we can also define a postcondition which verifies that the
+ * system under test is in a correct state after the command exectution. */
+ trait Command {
+
+ /** Used internally. */
+ protected[Commands] def run_(s: State) = run(s)
+
+ def run(s: State): Any
+ def nextState(s: State): State
+
+ /** Returns all preconditions merged into a single function */
+ def preCondition: (State => Boolean) =
+ s => preConditions.toList.forall(_.apply(s))
+
+ /** A precondition is a function that
+ * takes the current abstract state as parameter and returns a boolean
+ * that says if the precondition is fulfilled or not. You can add several
+ * conditions to the precondition list */
+ val preConditions = new collection.mutable.ListBuffer[State => Boolean]
+
+ /** Returns all postconditions merged into a single function */
+ def postCondition: (State,State,Any) => Prop =
+ (s0,s1,r) => Prop.all(postConditions.map(_.apply(s0,s1,r)): _*)
+
+ /** A postcondition is a function that
+ * takes three parameters, s0, s1 and r. s0 is the abstract state before
+ * the command was run, s1 is the abstract state after the command was
+ * run, and r is the result from the command's run
+ * method. The postcondition function should return a Boolean (or
+ * a Prop instance) that says if the condition holds or not. You can add several
+ * conditions to the postConditions list. */
+ val postConditions = new collection.mutable.ListBuffer[(State,State,Any) => Prop]
+ }
+
+ /** A command that binds its result for later use */
+ trait SetCommand extends Command {
+ /** Used internally. */
+ protected[Commands] final override def run_(s: State) = {
+ val r = run(s)
+ bindings += ((s,r))
+ r
+ }
+
+ final def nextState(s: State) = nextState(s, new Binding(s))
+ def nextState(s: State, b: Binding): State
+ }
+
+ private case class Cmds(cs: List[Command], ss: List[State]) {
+ override def toString = cs.map(_.toString).mkString(", ")
+ }
+
+ private val bindings = new scala.collection.mutable.ListBuffer[(State,Any)]
+
+ private def initState() = {
+ bindings.clear()
+ initialState()
+ }
+
+ private def genCmds: Gen[Cmds] = {
+ def sizedCmds(s: State, sz: Int): Gen[Cmds] = {
+ if(sz <= 0) Gen.const(Cmds(Nil, Nil)) else for {
+ c <- genCommand(s) suchThat (_.preCondition(s))
+ Cmds(cs,ss) <- sizedCmds(c.nextState(s), sz-1)
+ } yield Cmds(c::cs, s::ss)
+ }
+
+ Gen.sized(sz => sizedCmds(initialState(), sz))
+ }
+
+ private def validCmds(s: State, cs: List[Command]): Option[Cmds] =
+ cs match {
+ case Nil => Some(Cmds(Nil, s::Nil))
+ case c::_ if !c.preCondition(s) => None
+ case c::cmds => for {
+ Cmds(_, ss) <- validCmds(c.nextState(s), cmds)
+ } yield Cmds(cs, s::ss)
+ }
+
+ private def runCommands(cmds: Cmds): Prop = Prop.all {
+ cmds.cs.indices.map { i =>
+ val (c,s) = (cmds.cs(i), cmds.ss(i))
+ c.postCondition(s,c.nextState(s),c.run_(s))
+ } : _*
+ }
+
+ private def commandsProp: Prop = {
+ def shrinkCmds(cmds: Cmds) =
+ Shrink.shrink(cmds.cs)(Shrink.shrinkContainer).flatMap { cs =>
+ validCmds(initialState(), cs).toList
+ }
+
+ Prop.forAllShrink(genCmds label "COMMANDS", shrinkCmds)(runCommands _)
+ }
+
+ def apply(p: Gen.Parameters) = commandsProp(p)
+
+ /** initialState should reset the system under test to a well defined
+ * initial state, and return the abstract version of that state. */
+ def initialState(): State
+
+ /** The command generator. Given an abstract state, the generator
+ * should return a command that is allowed to run in that state. Note that
+ * it is still neccessary to define preconditions on the commands if there
+ * are any. The generator is just giving a hint of which commands that are
+ * suitable for a given state, the preconditions will still be checked before
+ * a command runs. Sometimes you maybe want to adjust the distribution of
+ * your command generator according to the state, or do other calculations
+ * based on the state. */
+ def genCommand(s: State): Gen[Command]
+
+}
diff --git a/src/partest-extras/scala/org/scalacheck/Commands2.scala b/src/partest-extras/scala/org/scalacheck/Commands2.scala
new file mode 100644
index 0000000000..67393a7a70
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/Commands2.scala
@@ -0,0 +1,150 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck
+
+private[scalacheck] trait Commands2 {
+
+ /** The abstract state type. Must be immutable.
+ * The [[Commands2.State]] type should model the state of the system under test (SUT).
+ * It should leave out all details that aren't needed for specifying our
+ * pre- and postconditions. */
+ type State
+
+ /** A type representing one instance of the system under test (SUT).
+ * The [[Commands2.System]] type should be a proxy to the actual system under test.
+ * It is used in the postconditions to verify that the real system
+ * behaves according to specification. It should be possible to have
+ * up to [[Commands2.maxSystemInstanceCount]] co-existing instances of the System
+ * type, and each System instance should be a proxy to a distinct
+ * SUT instance. There should be no dependencies between the System
+ * instances, as they might be used in parallel by ScalaCheck.
+ * System instances are created by [[Commands2.newSystemInstance]] and destroyed by
+ * [[Commands2.destroySystemInstance]]. [[Commands2.newSystemInstance]] and
+ * [[Commands2.destroySystemInstance]] might be called at any time by ScalaCheck,
+ * as long as [[Commands2.maxSystemInstanceCount]] isn't violated. */
+ type System
+
+ /** The maximum number of concurrent [[Commands2.System]] instances allowed to exist. */
+ def maxSystemInstanceCount: Int
+
+ /** Should create a new [[Commands2.System]] instance with an internal state that
+ * corresponds to the provided abstract state instance. The provided state
+ * is guaranteed to fulfill [[Commands2.initialPreCondition]], and
+ * [[Commands2.newSystemInstance]] will never be called if there already
+ * is [[Commands2.maxSystemInstanceCount]] instances of [[Commands2.System]] */
+ def newSystemInstance(state: State): System
+
+ /** Should destroy the given SUT, so that a new [[Commands2.System]] instance can be
+ * created with [[Commands2.newSystemInstance]]. */
+ def destroySystemInstance(system: System): Unit
+
+ /** The precondition for the initial state, when no commands yet have
+ * run. This is used by ScalaCheck when command sequences are shrinked
+ * and the first state might differ from what is returned from
+ * [[Commands2.initialState]]. */
+ def initialPreCondition(state: State): Boolean
+
+ /** A generator that should produce an initial [[Commands2.State]] instance that is
+ * usable by [[Commands2.newSystemInstance]] to create a new system under test.
+ * The state returned by this generator is always checked with the
+ * [[Commands2.initialPreCondition]] method before it is used. */
+ def genInitialState: Gen[State]
+
+ /** A generator that, given the current abstract state, should produce
+ * a suitable Command instance. */
+ def genCommand(state: State): Gen[Command]
+
+ /** Abstract commands are defined as subtypes of the trait [[Commands2.Command]].
+ * Each command must have a run method and a method
+ * that returns the new abstract state, as it is supposed to look after
+ * the command has been run. A command can also define a precondition
+ * that defines how the current abstract state must look if the command
+ * should be allowed to run. Finally, you can also define a postcondition
+ * that verifies that the system under test is in a correct state after
+ * the command execution. */
+ trait Command {
+ /** Runs this command in the system under test,
+ * represented by the provided [[Commands2.System]] instance. This method
+ * can return any value as result. The returned value will be
+ * used by the postcondition to decide if the system behaves as
+ * expected. */
+ def run(state: State, system: System): Any
+
+ /** Returns a new abstract [[Commands2.State]] instance that represents the
+ * state of the system after this command has run. */
+ def nextState(state: State): State
+
+ /** The precondition that decides if this command is allowed to run
+ * when the system under test is in the specified (abstract) state. */
+ def preCondition(state: State): Boolean
+
+ /** The postcondition that decides if the system under test behaved
+ * correctly when the command ran.
+ * @param s0 The abstract state as it looked before this command ran.
+ * @param s1 The abstract state as it looked after this command ran.
+ * @param system The proxy for the system under test. The postcondition
+ * can query the system for its current state, but care must be taken
+ * not to mutate the system under test in any way.
+ * @param result The result returned from the [[Command.run]] method.
+ */
+ def postCondition(s0: State, s1: State, system: System, result: Any): Prop
+ }
+
+/* WIP
+ private case class Cmds(cs: List[Command], ss: List[State]) {
+ override def toString = cs.map(_.toString).mkString(", ")
+ }
+
+ private val bindings = new scala.collection.mutable.ListBuffer[(State,Any)]
+
+ private def initState() = {
+ bindings.clear()
+ initialState()
+ }
+
+ private def genCmds: Gen[Cmds] = {
+ def sizedCmds(s: State, sz: Int): Gen[Cmds] = {
+ if(sz <= 0) Gen.const(Cmds(Nil, Nil)) else for {
+ c <- genCommand(s) suchThat (_.preCondition(s))
+ Cmds(cs,ss) <- sizedCmds(c.nextState(s), sz-1)
+ } yield Cmds(c::cs, s::ss)
+ }
+
+ Gen.sized(sz => sizedCmds(initialState(), sz))
+ }
+
+ private def validCmds(s: State, cs: List[Command]): Option[Cmds] =
+ cs match {
+ case Nil => Some(Cmds(Nil, s::Nil))
+ case c::_ if !c.preCondition(s) => None
+ case c::cmds => for {
+ Cmds(_, ss) <- validCmds(c.nextState(s), cmds)
+ } yield Cmds(cs, s::ss)
+ }
+
+ private def runCommands(cmds: Cmds): Prop = Prop.all {
+ cmds.cs.indices.map { i =>
+ val (c,s) = (cmds.cs(i), cmds.ss(i))
+ c.postCondition(s,c.nextState(s),c.run_(s))
+ } : _*
+ }
+
+ private def commandsProp: Prop = {
+ def shrinkCmds(cmds: Cmds) =
+ Shrink.shrink(cmds.cs)(Shrink.shrinkContainer).flatMap { cs =>
+ validCmds(initialState(), cs).toList
+ }
+
+ Prop.forAllShrink(genCmds label "COMMANDS", shrinkCmds)(runCommands _)
+ }
+
+ def apply(p: Prop.Params) = commandsProp(p)
+*/
+}
diff --git a/src/partest-extras/scala/org/scalacheck/Gen.scala b/src/partest-extras/scala/org/scalacheck/Gen.scala
new file mode 100644
index 0000000000..ba82c9ea95
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/Gen.scala
@@ -0,0 +1,813 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck
+
+import util.{Buildable, Buildable2}
+import scala.collection.immutable.TreeMap
+
+sealed trait Gen[+T] {
+
+ //// Private interface ////
+
+ import Gen.{R, r, gen}
+
+ /** Just an alias */
+ private type P = Gen.Parameters
+
+ /** Should be a copy of R.sieve. Used internally in Gen when some generators
+ * with suchThat-claues are created (when R is not available). This method
+ * actually breaks covariance, but since this method will only ever be
+ * called with a value of exactly type T, it is OK. */
+ protected def sieveCopy(x: Any): Boolean = true
+
+ private[scalacheck] def doApply(p: P): R[T]
+
+
+ //// Public interface ////
+
+ /** A class supporting filtered operations. */
+ final class WithFilter(p: T => Boolean) {
+ def map[U](f: T => U): Gen[U] = Gen.this.suchThat(p).map(f)
+ def flatMap[U](f: T => Gen[U]): Gen[U] = Gen.this.suchThat(p).flatMap(f)
+ def withFilter(q: T => Boolean): WithFilter = Gen.this.withFilter(x => p(x) && q(x))
+ }
+
+ /** Evaluate this generator with the given parameters */
+ def apply(p: Gen.Parameters): Option[T] = doApply(p).retrieve
+
+ /** Create a new generator by mapping the result of this generator */
+ def map[U](f: T => U): Gen[U] = gen { p => doApply(p).map(f) }
+
+ /** Create a new generator by flat-mapping the result of this generator */
+ def flatMap[U](f: T => Gen[U]): Gen[U] = gen { p =>
+ doApply(p).flatMap(t => f(t).doApply(p))
+ }
+
+ /** Create a new generator that uses this generator to produce a value
+ * that fulfills the given condition. If the condition is not fulfilled,
+ * the generator fails (returns None). */
+ def filter(p: T => Boolean): Gen[T] = suchThat(p)
+
+ /** Creates a non-strict filtered version of this generator. */
+ def withFilter(p: T => Boolean): WithFilter = new WithFilter(p)
+
+ /** Create a new generator that uses this generator to produce a value
+ * that fulfills the given condition. If the condition is not fulfilled,
+ * the generator fails (returns None). This method is identical to
+ * [Gen.filter]. */
+ def suchThat(f: T => Boolean): Gen[T] = new Gen[T] {
+ def doApply(p: P) = {
+ val res = Gen.this.doApply(p)
+ res.copy(s = { x:T => res.sieve(x) && f(x) })
+ }
+ override def sieveCopy(x: Any) =
+ try Gen.this.sieveCopy(x) && f(x.asInstanceOf[T])
+ catch { case _: java.lang.ClassCastException => false }
+ }
+
+ /** Create a generator that calls this generator repeatedly until
+ * the given condition is fulfilled. The generated value is then
+ * returned. Use this combinator with care, since it may result
+ * in infinite loops. */
+ def retryUntil(p: T => Boolean): Gen[T] = flatMap { t =>
+ if (p(t)) Gen.const(t).suchThat(p) else retryUntil(p)
+ }
+
+ def sample: Option[T] = doApply(Gen.Parameters.default).retrieve
+
+ /** Returns a new property that holds if and only if both this
+ * and the given generator generates the same result, or both
+ * generators generate no result. */
+ def ==[U](g: Gen[U]) = Prop { prms =>
+ (doApply(prms).retrieve, g.doApply(prms).retrieve) match {
+ case (None,None) => Prop.proved(prms)
+ case (Some(r1),Some(r2)) if r1 == r2 => Prop.proved(prms)
+ case _ => Prop.falsified(prms)
+ }
+ }
+
+ def !=[U](g: Gen[U]) = Prop.forAll(this)(r => Prop.forAll(g)(_ != r))
+
+ def !==[U](g: Gen[U]) = Prop { prms =>
+ (doApply(prms).retrieve, g.doApply(prms).retrieve) match {
+ case (None,None) => Prop.falsified(prms)
+ case (Some(r1),Some(r2)) if r1 == r2 => Prop.falsified(prms)
+ case _ => Prop.proved(prms)
+ }
+ }
+
+ /** Put a label on the generator to make test reports clearer */
+ def label(l: String) = new Gen[T] {
+ def doApply(p: P) = {
+ val r = Gen.this.doApply(p)
+ r.copy(l = r.labels + l)
+ }
+ override def sieveCopy(x: Any) = Gen.this.sieveCopy(x)
+ }
+
+ /** Put a label on the generator to make test reports clearer */
+ def :|(l: String) = label(l)
+
+ /** Put a label on the generator to make test reports clearer */
+ def |:(l: String) = label(l)
+
+ /** Put a label on the generator to make test reports clearer */
+ def :|(l: Symbol) = label(l.toString.drop(1))
+
+ /** Put a label on the generator to make test reports clearer */
+ def |:(l: Symbol) = label(l.toString.drop(1))
+
+}
+
+object Gen {
+
+ //// Private interface ////
+
+ import Arbitrary.arbitrary
+
+ /** Just an alias */
+ private type P = Parameters
+
+ private[scalacheck] trait R[+T] {
+ def labels: Set[String] = Set()
+ def sieve[U >: T]: U => Boolean = _ => true
+ protected def result: Option[T]
+
+ def retrieve = result.filter(sieve)
+
+ def copy[U >: T](
+ l: Set[String] = this.labels,
+ s: U => Boolean = this.sieve,
+ r: Option[U] = this.result
+ ): R[U] = new R[U] {
+ override val labels = l
+ override def sieve[V >: U] = { x:Any =>
+ try s(x.asInstanceOf[U])
+ catch { case _: java.lang.ClassCastException => false }
+ }
+ val result = r
+ }
+
+ def map[U](f: T => U): R[U] = r(retrieve.map(f)).copy(l = labels)
+
+ def flatMap[U](f: T => R[U]): R[U] = retrieve match {
+ case None => r(None).copy(l = labels)
+ case Some(t) =>
+ val r = f(t)
+ r.copy(l = labels ++ r.labels)
+ }
+ }
+
+ private[scalacheck] def r[T](r: Option[T]): R[T] = new R[T] {
+ val result = r
+ }
+
+ /** Generator factory method */
+ private[scalacheck] def gen[T](f: P => R[T]): Gen[T] = new Gen[T] {
+ def doApply(p: P) = f(p)
+ }
+
+ //// Public interface ////
+
+ /** Generator parameters, used by [[org.scalacheck.Gen.apply]] */
+ trait Parameters {
+
+ /** The size of the generated value. Generator implementations are allowed
+ * to freely interpret (or ignore) this value. During test execution, the
+ * value of this parameter is controlled by [[Test.Parameters.minSize]] and
+ * [[Test.Parameters.maxSize]]. */
+ val size: Int
+
+ /** Create a copy of this [[Gen.Parameters]] instance with
+ * [[Gen.Parameters.size]] set to the specified value. */
+ def withSize(size: Int): Parameters = cp(size = size)
+
+ /** The random number generator used. */
+ val rng: scala.util.Random
+
+ /** Create a copy of this [[Gen.Parameters]] instance with
+ * [[Gen.Parameters.rng]] set to the specified value. */
+ def withRng(rng: scala.util.Random): Parameters = cp(rng = rng)
+
+ /** Change the size parameter.
+ * @deprecated Use [[Gen.Parameters.withSize]] instead. */
+ @deprecated("Use withSize instead.", "1.11.2")
+ def resize(newSize: Int): Parameters = withSize(newSize)
+
+ // private since we can't guarantee binary compatibility for this one
+ private case class cp(
+ size: Int = size,
+ rng: scala.util.Random = rng
+ ) extends Parameters
+ }
+
+ /** Provides methods for creating [[org.scalacheck.Gen.Parameters]] values */
+ object Parameters {
+ /** Default generator parameters trait. This can be overriden if you
+ * need to tweak the parameters. */
+ trait Default extends Parameters {
+ val size: Int = 100
+ val rng: scala.util.Random = scala.util.Random
+ }
+
+ /** Default generator parameters instance. */
+ val default: Parameters = new Default {}
+ }
+
+ /** A wrapper type for range types */
+ trait Choose[T] {
+ /** Creates a generator that returns a value in the given inclusive range */
+ def choose(min: T, max: T): Gen[T]
+ }
+
+ /** Provides implicit [[org.scalacheck.Gen.Choose]] instances */
+ object Choose {
+
+ private def chLng(l: Long, h: Long)(p: P): R[Long] = {
+ if (h < l) r(None) else {
+ val d = h - l + 1
+ if (d <= 0) {
+ var n = p.rng.nextLong
+ while (n < l || n > h) {
+ n = p.rng.nextLong
+ }
+ r(Some(n))
+ } else {
+ r(Some(l + math.abs(p.rng.nextLong % d)))
+ }
+ }
+ }
+
+ private def chDbl(l: Double, h: Double)(p: P): R[Double] = {
+ val d = h-l
+ if (d < 0 || d > Double.MaxValue) r(None)
+ else if (d == 0) r(Some(l))
+ else r(Some(p.rng.nextDouble * (h-l) + l))
+ }
+
+ implicit val chooseLong: Choose[Long] = new Choose[Long] {
+ def choose(low: Long, high: Long) =
+ gen(chLng(low,high)).suchThat(x => x >= low && x <= high)
+ }
+ implicit val chooseInt: Choose[Int] = new Choose[Int] {
+ def choose(low: Int, high: Int) =
+ gen(chLng(low,high)).map(_.toInt).suchThat(x => x >= low && x <= high)
+ }
+ implicit val chooseByte: Choose[Byte] = new Choose[Byte] {
+ def choose(low: Byte, high: Byte) =
+ gen(chLng(low,high)).map(_.toByte).suchThat(x => x >= low && x <= high)
+ }
+ implicit val chooseShort: Choose[Short] = new Choose[Short] {
+ def choose(low: Short, high: Short) =
+ gen(chLng(low,high)).map(_.toShort).suchThat(x => x >= low && x <= high)
+ }
+ implicit val chooseChar: Choose[Char] = new Choose[Char] {
+ def choose(low: Char, high: Char) =
+ gen(chLng(low,high)).map(_.toChar).suchThat(x => x >= low && x <= high)
+ }
+ implicit val chooseDouble: Choose[Double] = new Choose[Double] {
+ def choose(low: Double, high: Double) =
+ gen(chDbl(low,high)).suchThat(x => x >= low && x <= high)
+ }
+ implicit val chooseFloat: Choose[Float] = new Choose[Float] {
+ def choose(low: Float, high: Float) =
+ gen(chDbl(low,high)).map(_.toFloat).suchThat(x => x >= low && x <= high)
+ }
+
+ /** Transform a Choose[T] to a Choose[U] where T and U are two isomorphic types
+ * whose relationship is described by the provided transformation functions.
+ * (exponential functor map) */
+ def xmap[T, U](from: T => U, to: U => T)(implicit c: Choose[T]): Choose[U] = new Choose[U] {
+ def choose(low: U, high: U) =
+ c.choose(to(low), to(high)).map(from)
+ }
+ }
+
+
+ //// Various Generator Combinators ////
+
+ /** A generator that always generates the given value */
+ @deprecated("Use Gen.const instead", "1.11.0")
+ def value[T](x: T): Gen[T] = const(x)
+
+ /** A generator that always generates the given value */
+ implicit def const[T](x: T): Gen[T] = gen(_ => r(Some(x))).suchThat(_ == x)
+
+ /** A generator that never generates a value */
+ def fail[T]: Gen[T] = gen(_ => r(None)).suchThat(_ => false)
+
+ /** A generator that generates a random value in the given (inclusive)
+ * range. If the range is invalid, the generator will not generate
+ * any value. */
+ def choose[T](min: T, max: T)(implicit c: Choose[T]): Gen[T] =
+ c.choose(min, max)
+
+ /** Sequences generators. If any of the given generators fails, the
+ * resulting generator will also fail. */
+ def sequence[C[_],T](gs: Traversable[Gen[T]])(implicit b: Buildable[T,C]): Gen[C[T]] = {
+ val g = gen { p =>
+ gs.foldLeft(r(Some(collection.immutable.Vector.empty[T]))) {
+ case (rs,g) => g.doApply(p).flatMap(r => rs.map(_ :+ r))
+ }
+ }
+ g.map(b.fromIterable)
+ }
+
+ /** Sequences generators. If any of the given generators fails, the
+ * resulting generator will also fail. */
+ def sequence[C[_,_],T,U](gs: Traversable[Gen[(T,U)]])(implicit b: Buildable2[T,U,C]): Gen[C[T,U]] = {
+ val g = gen { p =>
+ gs.foldLeft(r(Some(collection.immutable.Vector.empty[(T,U)]))) {
+ case (rs,g) => g.doApply(p).flatMap(r => rs.map(_ :+ r))
+ }
+ }
+ g.map(b.fromIterable)
+ }
+
+ /** Wraps a generator lazily. The given parameter is only evaluated once,
+ * and not until the wrapper generator is evaluated. */
+ def lzy[T](g: => Gen[T]): Gen[T] = {
+ lazy val h = g
+ gen { p => h.doApply(p) }
+ }
+
+ /** Wraps a generator for later evaluation. The given parameter is
+ * evaluated each time the wrapper generator is evaluated. */
+ def wrap[T](g: => Gen[T]) = gen { p => g.doApply(p) }
+
+ /** Creates a generator that can access its generation parameters */
+ def parameterized[T](f: Parameters => Gen[T]) = gen { p => f(p).doApply(p) }
+
+ /** Creates a generator that can access its generation size */
+ def sized[T](f: Int => Gen[T]) = gen { p => f(p.size).doApply(p) }
+
+ /** A generator that returns the current generation size */
+ lazy val size: Gen[Int] = sized { sz => sz }
+
+ /** Creates a resized version of a generator */
+ def resize[T](s: Int, g: Gen[T]) = gen(p => g.doApply(p.withSize(s)))
+
+ /** Picks a random value from a list */
+ def oneOf[T](xs: Seq[T]): Gen[T] =
+ choose(0, xs.size-1).map(xs(_)).suchThat(xs.contains)
+
+ /** Picks a random value from a list */
+ def oneOf[T](t0: T, t1: T, tn: T*): Gen[T] = oneOf(t0 +: t1 +: tn)
+
+ /** Picks a random generator from a list */
+ def oneOf[T](g0: Gen[T], g1: Gen[T], gn: Gen[T]*): Gen[T] = {
+ val gs = g0 +: g1 +: gn
+ choose(0,gs.size-1).flatMap(gs(_)).suchThat(x => gs.exists(_.sieveCopy(x)))
+ }
+
+ /** Makes a generator result optional. Either `Some(T)` or `None` will be provided. */
+ def option[T](g: Gen[T]): Gen[Option[T]] =
+ oneOf[Option[T]](g.map(Some.apply), None)
+
+ /** Chooses one of the given generators with a weighted random distribution */
+ def frequency[T](gs: (Int,Gen[T])*): Gen[T] = {
+ gs.filter(_._1 > 0) match {
+ case Nil => fail
+ case filtered =>
+ var tot = 0l
+ val tree: TreeMap[Long, Gen[T]] = {
+ val builder = TreeMap.newBuilder[Long, Gen[T]]
+ filtered.foreach {
+ case (f, v) =>
+ tot += f
+ builder.+=((tot, v))
+ }
+ builder.result()
+ }
+ choose(1L, tot).flatMap(r => tree.from(r).head._2).suchThat { x =>
+ gs.exists(_._2.sieveCopy(x))
+ }
+ }
+ }
+
+ /** Implicit convenience method for using the `frequency` method
+ * like this:
+ * {{{
+ * frequency((1, "foo"), (3, "bar"))
+ * }}}
+ */
+ implicit def freqTuple[T](t: (Int,T)): (Int,Gen[T]) = (t._1, const(t._2))
+
+
+ //// List Generators ////
+
+ /** Generates a container of any Traversable type for which there exists an
+ * implicit [[org.scalacheck.util.Buildable]] instance. The elements in the
+ * container will be generated by the given generator. The size of the
+ * generated container is limited by `n`. Depending on what kind of container
+ * that is generated, the resulting container may contain fewer elements than
+ * `n`, but not more. If the given generator fails generating a value, the
+ * complete container generator will also fail. */
+ def containerOfN[C[_],T](n: Int, g: Gen[T])(implicit
+ evb: Buildable[T,C], evt: C[T] => Traversable[T]
+ ): Gen[C[T]] =
+ sequence[C,T](Traversable.fill(n)(g)) suchThat { c =>
+ // TODO: Can we guarantee c.size == n (See issue #89)?
+ c.forall(g.sieveCopy)
+ }
+
+ /** Generates a container of any Traversable type for which there exists an
+ * implicit [[org.scalacheck.util.Buildable]] instance. The elements in the
+ * container will be generated by the given generator. The size of the
+ * container is bounded by the size parameter used when generating values. */
+ def containerOf[C[_],T](g: Gen[T])(implicit
+ evb: Buildable[T,C], evt: C[T] => Traversable[T]
+ ): Gen[C[T]] =
+ sized(s => choose(0,s).flatMap(containerOfN[C,T](_,g))) suchThat { c =>
+ c.forall(g.sieveCopy)
+ }
+
+ /** Generates a non-empty container of any Traversable type for which there
+ * exists an implicit [[org.scalacheck.util.Buildable]] instance. The
+ * elements in the container will be generated by the given generator. The
+ * size of the container is bounded by the size parameter used when
+ * generating values. */
+ def nonEmptyContainerOf[C[_],T](g: Gen[T])(implicit
+ evb: Buildable[T,C], evt: C[T] => Traversable[T]
+ ): Gen[C[T]] =
+ sized(s => choose(1,s).flatMap(containerOfN[C,T](_,g))) suchThat { c =>
+ c.size > 0 && c.forall(g.sieveCopy)
+ }
+
+ /** Generates a non-empty container of any Traversable type for which there
+ * exists an implicit [[org.scalacheck.util.Buildable]] instance. The
+ * elements in the container will be generated by the given generator. The
+ * size of the container is bounded by the size parameter used when
+ * generating values. */
+ @deprecated("Use Gen.nonEmptyContainerOf instead", "1.11.0")
+ def containerOf1[C[_],T](g: Gen[T])(implicit
+ evb: Buildable[T,C], evt: C[T] => Traversable[T]
+ ): Gen[C[T]] = nonEmptyContainerOf[C,T](g)
+
+ /** Generates a container of any Traversable type for which there exists an
+ * implicit [[org.scalacheck.util.Buildable2]] instance. The elements in
+ * container will be generated by the given generator. The size of the
+ * generated container is limited by `n`. Depending on what kind of container
+ * that is generated, the resulting container may contain fewer elements than
+ * `n`, but not more. If the given generator fails generating a value, the
+ * complete container generator will also fail. */
+ def containerOfN[C[_,_],T,U](n: Int, g: Gen[(T,U)])(implicit
+ evb: Buildable2[T,U,C], evt: C[T,U] => Traversable[(T,U)]
+ ): Gen[C[T,U]] =
+ sequence[C,T,U](Traversable.fill(n)(g)).suchThat { c =>
+ // TODO: Can we guarantee c.size == n (See issue #89)?
+ c.forall(g.sieveCopy)
+ }
+
+ /** Generates a container of any Traversable type for which there exists
+ * an implicit <code>Buildable2</code> instance. The elements in the
+ * container will be generated by the given generator. The size of the
+ * container is bounded by the size parameter used when generating values. */
+ def containerOf[C[_,_],T,U](g: Gen[(T,U)])(implicit
+ evb: Buildable2[T,U,C], evt: C[T,U] => Traversable[(T,U)]
+ ): Gen[C[T,U]] =
+ sized(s => choose(0,s).flatMap(containerOfN[C,T,U](_,g))) suchThat { c =>
+ c.forall(g.sieveCopy)
+ }
+
+ /** Generates a non-empty container of any type for which there exists an
+ * implicit <code>Buildable2</code> instance. The elements in the container
+ * will be generated by the given generator. The size of the container is
+ * bounded by the size parameter used when generating values. */
+ def nonEmptyContainerOf[C[_,_],T,U](g: Gen[(T,U)])(implicit
+ evb: Buildable2[T,U,C], evt: C[T,U] => Traversable[(T,U)]
+ ): Gen[C[T,U]] =
+ sized(s => choose(1,s).flatMap(containerOfN[C,T,U](_,g))) suchThat { c =>
+ c.size > 0 && c.forall(g.sieveCopy)
+ }
+
+ /** Generates a list of random length. The maximum length depends on the
+ * size parameter. This method is equal to calling
+ * `containerOf[List,T](g)`. */
+ def listOf[T](g: => Gen[T]) = containerOf[List,T](g)
+
+ /** Generates a non-empty list of random length. The maximum length depends
+ * on the size parameter. This method is equal to calling
+ * `nonEmptyContainerOf[List,T](g)`. */
+ def nonEmptyListOf[T](g: => Gen[T]) = nonEmptyContainerOf[List,T](g)
+
+ /** Generates a non-empty list of random length. The maximum length depends
+ * on the size parameter. This method is equal to calling
+ * `nonEmptyContainerOf[List,T](g)`. */
+ @deprecated("Use Gen.nonEmptyListOf instead", "1.11.0")
+ def listOf1[T](g: => Gen[T]) = nonEmptyListOf[T](g)
+
+ /** Generates a list of the given length. This method is equal to calling
+ * `containerOfN[List,T](n,g)`. */
+ def listOfN[T](n: Int, g: Gen[T]) = containerOfN[List,T](n,g)
+
+ /** Generates a map of random length. The maximum length depends on the
+ * size parameter. This method is equal to calling
+ * <code>containerOf[Map,T,U](g)</code>. */
+ def mapOf[T,U](g: => Gen[(T,U)]) = containerOf[Map,T,U](g)
+
+ /** Generates a non-empty map of random length. The maximum length depends
+ * on the size parameter. This method is equal to calling
+ * <code>nonEmptyContainerOf[Map,T,U](g)</code>. */
+ def nonEmptyMap[T,U](g: => Gen[(T,U)]) = nonEmptyContainerOf[Map,T,U](g)
+
+ /** Generates a map of with at least the given number of elements. This method
+ * is equal to calling <code>containerOfN[Map,T,U](n,g)</code>. */
+ def mapOfN[T,U](n: Int, g: Gen[(T,U)]) = containerOfN[Map,T,U](n,g)
+
+ /** A generator that picks a random number of elements from a list */
+ def someOf[T](l: Iterable[T]) = choose(0,l.size).flatMap(pick(_,l))
+
+ /** A generator that picks a random number of elements from a list */
+ def someOf[T](g1: Gen[T], g2: Gen[T], gs: Gen[T]*) =
+ choose(0, gs.length+2).flatMap(pick(_, g1, g2, gs: _*))
+
+ /** A generator that picks a given number of elements from a list, randomly */
+ def pick[T](n: Int, l: Iterable[T]): Gen[Seq[T]] =
+ if(n > l.size || n < 0) fail
+ else (gen { p =>
+ val b = new collection.mutable.ListBuffer[T]
+ b ++= l
+ while(b.length > n) b.remove(choose(0, b.length-1).doApply(p).retrieve.get)
+ r(Some(b))
+ }).suchThat(_.forall(x => l.exists(x == _)))
+
+ /** A generator that picks a given number of elements from a list, randomly */
+ def pick[T](n: Int, g1: Gen[T], g2: Gen[T], gn: Gen[T]*): Gen[Seq[T]] = {
+ val gs = g1 +: g2 +: gn
+ pick(n, 0 until gs.size).flatMap(idxs =>
+ sequence[List,T](idxs.toList.map(gs(_)))
+ ).suchThat(_.forall(x => gs.exists(_.sieveCopy(x))))
+ }
+
+
+ //// Character Generators ////
+
+ /** Generates a numerical character */
+ def numChar: Gen[Char] = choose(48.toChar, 57.toChar)
+
+ /** Generates an upper-case alpha character */
+ def alphaUpperChar: Gen[Char] = choose(65.toChar, 90.toChar)
+
+ /** Generates a lower-case alpha character */
+ def alphaLowerChar: Gen[Char] = choose(97.toChar, 122.toChar)
+
+ /** Generates an alpha character */
+ def alphaChar = frequency((1,alphaUpperChar), (9,alphaLowerChar))
+
+ /** Generates an alphanumerical character */
+ def alphaNumChar = frequency((1,numChar), (9,alphaChar))
+
+
+ //// String Generators ////
+
+ /** Generates a string that starts with a lower-case alpha character,
+ * and only contains alphanumerical characters */
+ def identifier: Gen[String] = (for {
+ c <- alphaLowerChar
+ cs <- listOf(alphaNumChar)
+ } yield (c::cs).mkString).suchThat(_.forall(c => c.isLetter || c.isDigit))
+
+ /** Generates a string of alpha characters */
+ def alphaStr: Gen[String] =
+ listOf(alphaChar).map(_.mkString).suchThat(_.forall(_.isLetter))
+
+ /** Generates a string of digits */
+ def numStr: Gen[String] =
+ listOf(numChar).map(_.mkString).suchThat(_.forall(_.isDigit))
+
+
+ //// Number Generators ////
+
+ /** Generates positive numbers of uniform distribution, with an
+ * upper bound of the generation size parameter. */
+ def posNum[T](implicit num: Numeric[T], c: Choose[T]): Gen[T] = {
+ import num._
+ sized(max => c.choose(one, fromInt(max)))
+ }
+
+ /** Generates negative numbers of uniform distribution, with an
+ * lower bound of the negated generation size parameter. */
+ def negNum[T](implicit num: Numeric[T], c: Choose[T]): Gen[T] = {
+ import num._
+ sized(max => c.choose(-fromInt(max), -one))
+ }
+
+ /** Generates numbers within the given inclusive range, with
+ * extra weight on zero, +/- unity, both extremities, and any special
+ * numbers provided. The special numbers must lie within the given range,
+ * otherwise they won't be included. */
+ def chooseNum[T](minT: T, maxT: T, specials: T*)(
+ implicit num: Numeric[T], c: Choose[T]
+ ): Gen[T] = {
+ import num._
+ val basics = List(minT, maxT, zero, one, -one)
+ val basicsAndSpecials = for {
+ t <- specials ++ basics if t >= minT && t <= maxT
+ } yield (1, const(t))
+ val allGens = basicsAndSpecials ++ List(
+ (basicsAndSpecials.length, c.choose(minT, maxT))
+ )
+ frequency(allGens: _*)
+ }
+
+ /** Generates a version 4 (random) UUID. */
+ lazy val uuid: Gen[java.util.UUID] = for {
+ l1 <- Gen.choose(Long.MinValue, Long.MaxValue)
+ l2 <- Gen.choose(Long.MinValue, Long.MaxValue)
+ y <- Gen.oneOf('8', '9', 'a', 'b')
+ } yield java.util.UUID.fromString(
+ new java.util.UUID(l1,l2).toString.updated(14, '4').updated(19, y)
+ )
+
+ /** Combines the given generators into one generator that produces a
+ * tuple of their generated values. */
+ def zip[T1,T2](g1: Gen[T1], g2: Gen[T2]): Gen[(T1,T2)] = {
+ val g = for {
+ t1 <- g1; t2 <- g2
+ } yield (t1,t2)
+ g.suchThat { case (t1,t2) => g1.sieveCopy(t1) && g2.sieveCopy(t2) }
+ }
+
+ /** Combines the given generators into one generator that produces a
+ * tuple of their generated values. */
+ def zip[T1,T2,T3](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3]): Gen[(T1,T2,T3)] = {
+ val g0 = zip(g1,g2)
+ val g = for {
+ (t1,t2) <- g0; t3 <- g3
+ } yield (t1,t2,t3)
+ g.suchThat { case (t1,t2,t3) => g0.sieveCopy(t1,t2) && g3.sieveCopy(t3) }
+ }
+
+ /** Combines the given generators into one generator that produces a
+ * tuple of their generated values. */
+ def zip[T1,T2,T3,T4](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4]
+ ): Gen[(T1,T2,T3,T4)] = {
+ val g0 = zip(g1,g2,g3)
+ val g = for {
+ (t1,t2,t3) <- g0; t4 <- g4
+ } yield (t1,t2,t3,t4)
+ g.suchThat { case (t1,t2,t3,t4) => g0.sieveCopy(t1,t2,t3) && g4.sieveCopy(t4) }
+ }
+
+ /** Combines the given generators into one generator that produces a
+ * tuple of their generated values. */
+ def zip[T1,T2,T3,T4,T5](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4],
+ g5: Gen[T5]
+ ): Gen[(T1,T2,T3,T4,T5)] = {
+ val g0 = zip(g1,g2,g3,g4)
+ val g = for {
+ (t1,t2,t3,t4) <- g0; t5 <- g5
+ } yield (t1,t2,t3,t4,t5)
+ g.suchThat { case (t1,t2,t3,t4,t5) =>
+ g0.sieveCopy(t1,t2,t3,t4) && g5.sieveCopy(t5)
+ }
+ }
+
+ /** Combines the given generators into one generator that produces a
+ * tuple of their generated values. */
+ def zip[T1,T2,T3,T4,T5,T6](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4],
+ g5: Gen[T5], g6: Gen[T6]
+ ): Gen[(T1,T2,T3,T4,T5,T6)] = {
+ val g0 = zip(g1,g2,g3,g4,g5)
+ val g = for {
+ (t1,t2,t3,t4,t5) <- g0; t6 <- g6
+ } yield (t1,t2,t3,t4,t5,t6)
+ g.suchThat { case (t1,t2,t3,t4,t5,t6) =>
+ g0.sieveCopy(t1,t2,t3,t4,t5) && g6.sieveCopy(t6)
+ }
+ }
+
+ /** Combines the given generators into one generator that produces a
+ * tuple of their generated values. */
+ def zip[T1,T2,T3,T4,T5,T6,T7](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3],
+ g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7]
+ ): Gen[(T1,T2,T3,T4,T5,T6,T7)] = {
+ val g0 = zip(g1,g2,g3,g4,g5,g6)
+ val g = for {
+ (t1,t2,t3,t4,t5,t6) <- g0; t7 <- g7
+ } yield (t1,t2,t3,t4,t5,t6,t7)
+ g.suchThat { case (t1,t2,t3,t4,t5,t6,t7) =>
+ g0.sieveCopy(t1,t2,t3,t4,t5,t6) && g7.sieveCopy(t7)
+ }
+ }
+
+ /** Combines the given generators into one generator that produces a
+ * tuple of their generated values. */
+ def zip[T1,T2,T3,T4,T5,T6,T7,T8](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3],
+ g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7], g8: Gen[T8]
+ ): Gen[(T1,T2,T3,T4,T5,T6,T7,T8)] = {
+ val g0 = zip(g1,g2,g3,g4,g5,g6,g7)
+ val g = for {
+ (t1,t2,t3,t4,t5,t6,t7) <- g0; t8 <- g8
+ } yield (t1,t2,t3,t4,t5,t6,t7,t8)
+ g.suchThat { case (t1,t2,t3,t4,t5,t6,t7,t8) =>
+ g0.sieveCopy(t1,t2,t3,t4,t5,t6,t7) && g8.sieveCopy(t8)
+ }
+ }
+
+ /** Combines the given generators into one generator that produces a
+ * tuple of their generated values. */
+ def zip[T1,T2,T3,T4,T5,T6,T7,T8,T9](g1: Gen[T1], g2: Gen[T2], g3: Gen[T3],
+ g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7], g8: Gen[T8], g9: Gen[T9]
+ ): Gen[(T1,T2,T3,T4,T5,T6,T7,T8,T9)] = {
+ val g0 = zip(g1,g2,g3,g4,g5,g6,g7,g8)
+ val g = for {
+ (t1,t2,t3,t4,t5,t6,t7,t8) <- g0; t9 <- g9
+ } yield (t1,t2,t3,t4,t5,t6,t7,t8,t9)
+ g.suchThat { case (t1,t2,t3,t4,t5,t6,t7,t8,t9) =>
+ g0.sieveCopy(t1,t2,t3,t4,t5,t6,t7,t8) && g9.sieveCopy(t9)
+ }
+ }
+
+ /** Takes a function and returns a generator that generates arbitrary
+ * results of that function by feeding it with arbitrarily generated input
+ * parameters. */
+ def resultOf[T,R](f: T => R)(implicit a: Arbitrary[T]): Gen[R] =
+ arbitrary[T] map f
+
+ /** Takes a function and returns a generator that generates arbitrary
+ * results of that function by feeding it with arbitrarily generated input
+ * parameters. */
+ def resultOf[T1,T2,R](f: (T1,T2) => R)(implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2]
+ ): Gen[R] = arbitrary[T1] flatMap { t => resultOf(f(t, _:T2)) }
+
+ /** Takes a function and returns a generator that generates arbitrary
+ * results of that function by feeding it with arbitrarily generated input
+ * parameters. */
+ def resultOf[T1,T2,T3,R](f: (T1,T2,T3) => R)(implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3]
+ ): Gen[R] = arbitrary[T1] flatMap { t => resultOf(f(t, _:T2, _:T3)) }
+
+ /** Takes a function and returns a generator that generates arbitrary
+ * results of that function by feeding it with arbitrarily generated input
+ * parameters. */
+ def resultOf[T1,T2,T3,T4,R](f: (T1,T2,T3,T4) => R)(implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4]
+ ): Gen[R] = arbitrary[T1] flatMap {
+ t => resultOf(f(t, _:T2, _:T3, _:T4))
+ }
+
+ /** Takes a function and returns a generator that generates arbitrary
+ * results of that function by feeding it with arbitrarily generated input
+ * parameters. */
+ def resultOf[T1,T2,T3,T4,T5,R](f: (T1,T2,T3,T4,T5) => R)(implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4],
+ a5: Arbitrary[T5]
+ ): Gen[R] = arbitrary[T1] flatMap {
+ t => resultOf(f(t, _:T2, _:T3, _:T4, _:T5))
+ }
+
+ /** Takes a function and returns a generator that generates arbitrary
+ * results of that function by feeding it with arbitrarily generated input
+ * parameters. */
+ def resultOf[T1,T2,T3,T4,T5,T6,R](
+ f: (T1,T2,T3,T4,T5,T6) => R)(implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3],
+ a4: Arbitrary[T4], a5: Arbitrary[T5], a6: Arbitrary[T6]
+ ): Gen[R] = arbitrary[T1] flatMap {
+ t => resultOf(f(t, _:T2, _:T3, _:T4, _:T5, _:T6))
+ }
+
+ /** Takes a function and returns a generator that generates arbitrary
+ * results of that function by feeding it with arbitrarily generated input
+ * parameters. */
+ def resultOf[T1,T2,T3,T4,T5,T6,T7,R](
+ f: (T1,T2,T3,T4,T5,T6,T7) => R)(implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3],
+ a4: Arbitrary[T4], a5: Arbitrary[T5], a6: Arbitrary[T6], a7: Arbitrary[T7]
+ ): Gen[R] = arbitrary[T1] flatMap {
+ t => resultOf(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7))
+ }
+
+ /** Takes a function and returns a generator that generates arbitrary
+ * results of that function by feeding it with arbitrarily generated input
+ * parameters. */
+ def resultOf[T1,T2,T3,T4,T5,T6,T7,T8,R](
+ f: (T1,T2,T3,T4,T5,T6,T7,T8) => R)(implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4],
+ a5: Arbitrary[T5], a6: Arbitrary[T6], a7: Arbitrary[T7], a8: Arbitrary[T8]
+ ): Gen[R] = arbitrary[T1] flatMap {
+ t => resultOf(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7, _:T8))
+ }
+
+ /** Takes a function and returns a generator that generates arbitrary
+ * results of that function by feeding it with arbitrarily generated input
+ * parameters. */
+ def resultOf[T1,T2,T3,T4,T5,T6,T7,T8,T9,R](
+ f: (T1,T2,T3,T4,T5,T6,T7,T8,T9) => R)(implicit
+ a1: Arbitrary[T1], a2: Arbitrary[T2], a3: Arbitrary[T3], a4: Arbitrary[T4],
+ a5: Arbitrary[T5], a6: Arbitrary[T6], a7: Arbitrary[T7], a8: Arbitrary[T8],
+ a9: Arbitrary[T9]
+ ): Gen[R] = arbitrary[T1] flatMap {
+ t => resultOf(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7, _:T8, _:T9))
+ }
+}
diff --git a/src/partest-extras/scala/org/scalacheck/Prop.scala b/src/partest-extras/scala/org/scalacheck/Prop.scala
new file mode 100644
index 0000000000..6b607002fd
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/Prop.scala
@@ -0,0 +1,953 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck
+
+import util.{Pretty, FreqMap, Buildable, ConsoleReporter}
+import scala.annotation.tailrec
+
+trait Prop {
+
+ import Prop.{Result, Proof, True, False, Exception, Undecided,
+ provedToTrue, secure, mergeRes}
+ import Gen.Parameters
+
+ def apply(prms: Parameters): Result
+
+ def map(f: Result => Result): Prop = Prop(prms => f(this(prms)))
+
+ def flatMap(f: Result => Prop): Prop = Prop(prms => f(this(prms))(prms))
+
+ // TODO In 1.12.0, make p call-by-name, and remove the calls to secure()
+ // in the methods that use combine()
+ def combine(p: Prop)(f: (Result, Result) => Result) =
+ for(r1 <- this; r2 <- p) yield f(r1,r2)
+
+ /** Convenience method that checks this property with the given parameters
+ * and reports the result on the console. */
+ def check(prms: Test.Parameters): Unit = Test.check(
+ if(prms.testCallback.isInstanceOf[ConsoleReporter]) prms
+ else prms.withTestCallback(prms.testCallback.chain(ConsoleReporter(1))),
+ this
+ )
+
+ /** Convenience method that checks this property and reports the
+ * result on the console. The default test parameters
+ * ([[Test.Parameters.default]]) are used for the check. */
+ def check: Unit = check(Test.Parameters.default)
+
+ /** Convenience method that checks this property and reports the result
+ * on the console. The provided argument should be a function that takes
+ * the default test parameters ([[Test.Parameters.default]])
+ * as input and outputs a modified [[Test.Parameters]] instance that
+ * Example use:
+ *
+ * {{{
+ * p.check(_.withMinSuccessfulTests(500))
+
+ * p.check { _.
+ * withMinSuccessfulTests(80000).
+ * withWorkers(4)
+ * }
+ * }}}
+ */
+ def check(paramFun: Test.Parameters => Test.Parameters): Unit = check(
+ paramFun(Test.Parameters.default)
+ )
+
+ /** Convenience method that checks this property with specified minimal
+ * number of successful test and the given testing parameters, and
+ * reports the result on the console. If you need to get the results
+ * from the test use the `check` methods in [[org.scalacheck.Test]]
+ * instead. */
+ @deprecated("Use check(prms.withMinSuccessfulTests(n)) instead", "1.11.2")
+ def check(minSuccessfulTests: Int, prms: Test.Parameters): Unit = check(
+ prms.withMinSuccessfulTests(minSuccessfulTests)
+ )
+
+ /** Convenience method that checks this property with specified minimal
+ * number of successful test and reports the result on the console.
+ * If you need to get the results from the test use
+ * the `check` methods in [[org.scalacheck.Test]] instead. */
+ @deprecated("Use check(_.withMinSuccessfulTests(n)) instead", "1.11.2")
+ def check(minSuccessfulTests: Int): Unit = check(
+ _.withMinSuccessfulTests(minSuccessfulTests)
+ )
+
+ /** The logic for main, separated out to make it easier to
+ * avoid System.exit calls. Returns exit code.
+ */
+ def mainRunner(args: Array[String]): Int = {
+ Test.parseParams(args) match {
+ case Some(params) =>
+ if (Test.check(params, this).passed) 0
+ else 1
+ case None =>
+ println("Incorrect options")
+ -1
+ }
+ }
+
+ /** Whether main should call System.exit with an exit code.
+ * Defaults to true; override to change. */
+ def mainCallsExit = true
+
+ /** Convenience method that makes it possible to use this property
+ * as an application that checks itself on execution */
+ def main(args: Array[String]): Unit = {
+ val code = mainRunner(args)
+ if (mainCallsExit && code != 0)
+ System exit code
+ }
+
+ /** Returns a new property that holds if and only if both this
+ * and the given property hold. If one of the properties doesn't
+ * generate a result, the new property will generate false. */
+ def &&(p: => Prop) = combine(secure(p))(_ && _)
+
+ /** Returns a new property that holds if either this
+ * or the given property (or both) hold. */
+ def ||(p: => Prop) = combine(secure(p))(_ || _)
+
+ /** Returns a new property that holds if and only if both this
+ * and the given property hold. If one of the properties doesn't
+ * generate a result, the new property will generate the same result
+ * as the other property. */
+ def ++(p: => Prop): Prop = combine(secure(p))(_ ++ _)
+
+ /** Combines two properties through implication */
+ def ==>(p: => Prop): Prop = flatMap { r1 =>
+ if(r1.proved) p map { r2 => mergeRes(r1,r2,r2.status) }
+ else if(!r1.success) Prop(r1.copy(status = Undecided))
+ else p map { r2 => provedToTrue(mergeRes(r1,r2,r2.status)) }
+ }
+
+ /** Returns a new property that holds if and only if both this
+ * and the given property generates a result with the exact
+ * same status. Note that this means that if one of the properties is
+ * proved, and the other one passed, then the resulting property
+ * will fail. */
+ def ==(p: => Prop) = this.flatMap { r1 =>
+ p.map { r2 =>
+ mergeRes(r1, r2, if(r1.status == r2.status) True else False)
+ }
+ }
+
+ override def toString = "Prop"
+
+ /** Put a label on the property to make test reports clearer */
+ def label(l: String) = map(_.label(l))
+
+ /** Put a label on the property to make test reports clearer */
+ def :|(l: String) = label(l)
+
+ /** Put a label on the property to make test reports clearer */
+ def |:(l: String) = label(l)
+
+ /** Put a label on the property to make test reports clearer */
+ def :|(l: Symbol) = label(l.toString.drop(1))
+
+ /** Put a label on the property to make test reports clearer */
+ def |:(l: Symbol) = label(l.toString.drop(1))
+
+}
+
+object Prop {
+
+ import Gen.{value, fail, frequency, oneOf, Parameters}
+ import Arbitrary.{arbitrary}
+ import Shrink.{shrink}
+
+ // Types
+
+ /** A property argument */
+ case class Arg[+T](
+ label: String,
+ arg: T,
+ shrinks: Int,
+ origArg: T,
+ prettyArg: Pretty,
+ prettyOrigArg: Pretty
+ )
+
+ object Result {
+ @deprecated("Will be removed in 1.12.0", "1.11.2")
+ def apply(st: Status): Result = Result(status = st)
+ @deprecated("Will be removed in 1.12.0", "1.11.2")
+ def merge(x: Result, y: Result, status: Status) = mergeRes(x,y,status)
+ }
+
+ private[scalacheck] def mergeRes(x: Result, y: Result, st: Status) = Result(
+ status = st,
+ args = x.args ++ y.args,
+ collected = x.collected ++ y.collected,
+ labels = x.labels ++ y.labels
+ )
+
+ /** The result of evaluating a property */
+ case class Result(
+ status: Status,
+ args: List[Arg[Any]] = Nil,
+ collected: Set[Any] = Set.empty,
+ labels: Set[String] = Set.empty
+ ) {
+ def success = status match {
+ case True => true
+ case Proof => true
+ case _ => false
+ }
+
+ def failure = status match {
+ case False => true
+ case Exception(_) => true
+ case _ => false
+ }
+
+ def proved = status == Proof
+
+ def addArg(a: Arg[Any]) = copy(args = a::args)
+
+ def collect(x: Any) = copy(collected = collected+x)
+
+ def label(l: String) = copy(labels = labels+l)
+
+ def &&(r: Result) = (this.status, r.status) match {
+ case (Exception(_),_) => this
+ case (_,Exception(_)) => r
+
+ case (False,_) => this
+ case (_,False) => r
+
+ case (Undecided,_) => this
+ case (_,Undecided) => r
+
+ case (_,Proof) => mergeRes(this, r, this.status)
+ case (Proof,_) => mergeRes(this, r, r.status)
+
+ case (True,True) => mergeRes(this, r, True)
+ }
+
+ def ||(r: Result) = (this.status, r.status) match {
+ case (Exception(_),_) => this
+ case (_,Exception(_)) => r
+
+ case (False,False) => mergeRes(this, r, False)
+ case (False,_) => r
+ case (_,False) => this
+
+ case (Proof,_) => this
+ case (_,Proof) => r
+
+ case (True,_) => this
+ case (_,True) => r
+
+ case (Undecided,Undecided) => mergeRes(this, r, Undecided)
+ }
+
+ def ++(r: Result) = (this.status, r.status) match {
+ case (Exception(_),_) => this
+ case (_,Exception(_)) => r
+
+ case (_, Undecided) => this
+ case (Undecided, _) => r
+
+ case (_, Proof) => this
+ case (Proof, _) => r
+
+ case (_, True) => this
+ case (True, _) => r
+
+ case (False, _) => this
+ case (_, False) => r
+ }
+
+ def ==>(r: Result) = (this.status, r.status) match {
+ case (Exception(_),_) => this
+ case (_,Exception(_)) => r
+
+ case (False,_) => mergeRes(this, r, Undecided)
+
+ case (Undecided,_) => this
+
+ case (Proof,_) => mergeRes(this, r, r.status)
+ case (True,_) => mergeRes(this, r, r.status)
+ }
+ }
+
+ sealed trait Status
+
+ /** The property was proved */
+ case object Proof extends Status
+
+ /** The property was true */
+ case object True extends Status
+
+ /** The property was false */
+ case object False extends Status
+
+ /** The property could not be falsified or proved */
+ case object Undecided extends Status
+
+ /** Evaluating the property raised an exception */
+ sealed case class Exception(e: Throwable) extends Status {
+ override def equals(o: Any) = o match {
+ case Exception(_) => true
+ case _ => false
+ }
+ }
+
+ /** Create a new property from the given function. */
+ def apply(f: Parameters => Result): Prop = new Prop {
+ def apply(prms: Parameters) = try f(prms) catch {
+ case e: Throwable => Result(status = Exception(e))
+ }
+ }
+
+ /** Create a property that returns the given result */
+ def apply(r: Result): Prop = Prop.apply(prms => r)
+
+ /** Create a property from a boolean value */
+ def apply(b: Boolean): Prop = if(b) proved else falsified
+
+
+ // Implicits
+
+ /** A collection of property operators on `Any` values.
+ * Import [[Prop.AnyOperators]] to make the operators available. */
+ class ExtendedAny[T <% Pretty](x: => T) {
+ /** See [[Prop.imply]] */
+ def imply(f: PartialFunction[T,Prop]) = Prop.imply(x,f)
+ /** See [[Prop.iff]] */
+ def iff(f: PartialFunction[T,Prop]) = Prop.iff(x,f)
+ /** See [[Prop.?=]] */
+ def ?=(y: T) = Prop.?=(x, y)
+ /** See [[Prop.=?]] */
+ def =?(y: T) = Prop.=?(x, y)
+ }
+
+ /** A collection of property operators on `Boolean` values.
+ * Import [[Prop.BooleanOperators]] to make the operators available. */
+ class ExtendedBoolean(b: => Boolean) {
+ /** See the documentation for [[org.scalacheck.Prop]] */
+ def ==>(p: => Prop) = Prop(b) ==> p
+ /** See the documentation for [[org.scalacheck.Prop]] */
+ def :|(l: String) = Prop(b) :| l
+ /** See the documentation for [[org.scalacheck.Prop]] */
+ def |:(l: String) = l |: Prop(b)
+ /** See the documentation for [[org.scalacheck.Prop]] */
+ def :|(l: Symbol) = Prop(b) :| l
+ /** See the documentation for [[org.scalacheck.Prop]] */
+ def |:(l: Symbol) = l |: Prop(b)
+ }
+
+ /** Implicit method that makes a number of property operators on values of
+ * type `Any` available in the current scope.
+ * See [[Prop.ExtendedAny]] for documentation on the operators. */
+ implicit def AnyOperators[T <% Pretty](x: => T) = new ExtendedAny[T](x)
+
+ /** Implicit method that makes a number of property operators on boolean
+ * values available in the current scope. See [[Prop.ExtendedBoolean]] for
+ * documentation on the operators. */
+ implicit def BooleanOperators(b: => Boolean) = new ExtendedBoolean(b)
+
+ /** Implicit conversion of Boolean values to Prop values. */
+ implicit def propBoolean(b: Boolean): Prop = Prop(b)
+
+
+ // Private support functions
+
+ private def provedToTrue(r: Result) = r.status match {
+ case Proof => r.copy(status = True)
+ case _ => r
+ }
+
+
+ // Property combinators
+
+ /** A property that never is proved or falsified */
+ lazy val undecided = Prop(Result(status = Undecided))
+
+ /** A property that always is false */
+ lazy val falsified = Prop(Result(status = False))
+
+ /** A property that always is proved */
+ lazy val proved = Prop(Result(status = Proof))
+
+ /** A property that always is passed */
+ lazy val passed = Prop(Result(status = True))
+
+ /** A property that denotes an exception */
+ def exception(e: Throwable): Prop = Prop(Result(status = Exception(e)))
+
+ /** A property that denotes an exception */
+ lazy val exception: Prop = exception(null)
+
+ /** Create a property that compares to values. If the values aren't equal,
+ * the property will fail and report that first value doesn't match the
+ * expected (second) value. */
+ def ?=[T](x: T, y: T)(implicit pp: T => Pretty): Prop =
+ if(x == y) proved else falsified :| {
+ val exp = Pretty.pretty[T](y, Pretty.Params(0))
+ val act = Pretty.pretty[T](x, Pretty.Params(0))
+ "Expected "+exp+" but got "+act
+ }
+
+ /** Create a property that compares to values. If the values aren't equal,
+ * the property will fail and report that second value doesn't match the
+ * expected (first) value. */
+ def =?[T](x: T, y: T)(implicit pp: T => Pretty): Prop = ?=(y, x)
+
+ /** A property that depends on the generator size */
+ def sizedProp(f: Int => Prop): Prop = Prop { prms =>
+ // provedToTrue since if the property is proved for
+ // one size, it shouldn't be regarded as proved for
+ // all sizes.
+ provedToTrue(f(prms.size)(prms))
+ }
+
+ /** Implication with several conditions */
+ def imply[T](x: T, f: PartialFunction[T,Prop]): Prop = secure {
+ if(f.isDefinedAt(x)) f(x) else undecided
+ }
+
+ /** Property holds only if the given partial function is defined at
+ * `x`, and returns a property that holds */
+ def iff[T](x: T, f: PartialFunction[T,Prop]): Prop = secure {
+ if(f.isDefinedAt(x)) f(x) else falsified
+ }
+
+ /** Combines properties into one, which is true if and only if all the
+ * properties are true */
+ def all(ps: Prop*) = if(ps.isEmpty) proved else Prop(prms =>
+ ps.map(p => p(prms)).reduceLeft(_ && _)
+ )
+
+ /** Combines properties into one, which is true if at least one of the
+ * properties is true */
+ def atLeastOne(ps: Prop*) = if(ps.isEmpty) falsified else Prop(prms =>
+ ps.map(p => p(prms)).reduceLeft(_ || _)
+ )
+
+ /** A property that holds if at least one of the given generators
+ * fails generating a value */
+ def someFailing[T](gs: Seq[Gen[T]]) = atLeastOne(gs.map(_ == fail):_*)
+
+ /** A property that holds iff none of the given generators
+ * fails generating a value */
+ def noneFailing[T](gs: Seq[Gen[T]]) = all(gs.map(_ !== fail):_*)
+
+ /** Returns true if the given statement throws an exception
+ * of the specified type */
+ def throws[T <: Throwable](c: Class[T])(x: => Any): Boolean =
+ try { x; false } catch { case e if c.isInstance(e) => true }
+
+ /** Collect data for presentation in test report */
+ def collect[T, P <% Prop](f: T => P): T => Prop = t => Prop { prms =>
+ val prop = f(t)
+ prop(prms).collect(t)
+ }
+
+ /** Collect data for presentation in test report */
+ def collect[T](t: T)(prop: Prop) = Prop { prms =>
+ prop(prms).collect(t)
+ }
+
+ /** Collect data for presentation in test report */
+ def classify(c: => Boolean, ifTrue: Any)(prop: Prop): Prop =
+ if(c) collect(ifTrue)(prop) else collect(())(prop)
+
+ /** Collect data for presentation in test report */
+ def classify(c: => Boolean, ifTrue: Any, ifFalse: Any)(prop: Prop): Prop =
+ if(c) collect(ifTrue)(prop) else collect(ifFalse)(prop)
+
+ /** Wraps and protects a property */
+ def secure[P <% Prop](p: => P): Prop =
+ try (p: Prop) catch { case e: Throwable => exception(e) }
+
+ /** Existential quantifier for an explicit generator. */
+ def exists[A,P](f: A => P)(implicit
+ pv: P => Prop,
+ pp: A => Pretty,
+ aa: Arbitrary[A]
+ ): Prop = exists(aa.arbitrary)(f)
+
+ /** Existential quantifier for an explicit generator. */
+ def exists[A,P](g: Gen[A])(f: A => P)(implicit
+ pv: P => Prop,
+ pp: A => Pretty
+ ): Prop = Prop { prms =>
+ val gr = g.doApply(prms)
+ gr.retrieve match {
+ case None => undecided(prms)
+ case Some(x) =>
+ val p = secure(f(x))
+ val labels = gr.labels.mkString(",")
+ val r = p(prms).addArg(Arg(labels,x,0,x,pp(x),pp(x)))
+ r.status match {
+ case True => r.copy(status = Proof)
+ case False => r.copy(status = Undecided)
+ case _ => r
+ }
+ }
+ }
+
+ /** Universal quantifier for an explicit generator. Does not shrink failed
+ * test cases. */
+ def forAllNoShrink[T1,P](
+ g1: Gen[T1])(
+ f: T1 => P)(implicit
+ pv: P => Prop,
+ pp1: T1 => Pretty
+ ): Prop = Prop { prms =>
+ val gr = g1.doApply(prms)
+ gr.retrieve match {
+ case None => undecided(prms)
+ case Some(x) =>
+ val p = secure(f(x))
+ val labels = gr.labels.mkString(",")
+ provedToTrue(p(prms)).addArg(Arg(labels,x,0,x,pp1(x),pp1(x)))
+ }
+ }
+
+ /** Universal quantifier for two explicit generators.
+ * Does not shrink failed test cases. */
+ def forAllNoShrink[T1,T2,P](
+ g1: Gen[T1], g2: Gen[T2])(
+ f: (T1,T2) => P)(implicit
+ p: P => Prop,
+ pp1: T1 => Pretty,
+ pp2: T2 => Pretty
+ ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2)(f(t, _:T2)))
+
+ /** Universal quantifier for three explicit generators.
+ * Does not shrink failed test cases. */
+ def forAllNoShrink[T1,T2,T3,P](
+ g1: Gen[T1], g2: Gen[T2], g3: Gen[T3])(
+ f: (T1,T2,T3) => P)(implicit
+ p: P => Prop,
+ pp1: T1 => Pretty,
+ pp2: T2 => Pretty,
+ pp3: T3 => Pretty
+ ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2,g3)(f(t, _:T2, _:T3)))
+
+ /** Universal quantifier for four explicit generators.
+ * Does not shrink failed test cases. */
+ def forAllNoShrink[T1,T2,T3,T4,P](
+ g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4])(
+ f: (T1,T2,T3,T4) => P)(implicit
+ p: P => Prop,
+ pp1: T1 => Pretty,
+ pp2: T2 => Pretty,
+ pp3: T3 => Pretty,
+ pp4: T4 => Pretty
+ ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2,g3,g4)(f(t, _:T2, _:T3, _:T4)))
+
+ /** Universal quantifier for five explicit generators.
+ * Does not shrink failed test cases. */
+ def forAllNoShrink[T1,T2,T3,T4,T5,P](
+ g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5])(
+ f: (T1,T2,T3,T4,T5) => P)(implicit
+ p: P => Prop,
+ pp1: T1 => Pretty,
+ pp2: T2 => Pretty,
+ pp3: T3 => Pretty,
+ pp4: T4 => Pretty,
+ pp5: T5 => Pretty
+ ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2,g3,g4,g5)(f(t, _:T2, _:T3, _:T4, _:T5)))
+
+ /** Universal quantifier for six explicit generators.
+ * Does not shrink failed test cases. */
+ def forAllNoShrink[T1,T2,T3,T4,T5,T6,P](
+ g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5], g6: Gen[T6])(
+ f: (T1,T2,T3,T4,T5,T6) => P)(implicit
+ p: P => Prop,
+ pp1: T1 => Pretty,
+ pp2: T2 => Pretty,
+ pp3: T3 => Pretty,
+ pp4: T4 => Pretty,
+ pp5: T5 => Pretty,
+ pp6: T6 => Pretty
+ ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2,g3,g4,g5,g6)(f(t, _:T2, _:T3, _:T4, _:T5, _:T6)))
+
+ /** Universal quantifier for seven explicit generators.
+ * Does not shrink failed test cases. */
+ def forAllNoShrink[T1,T2,T3,T4,T5,T6,T7,P](
+ g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7])(
+ f: (T1,T2,T3,T4,T5,T6,T7) => P)(implicit
+ p: P => Prop,
+ pp1: T1 => Pretty,
+ pp2: T2 => Pretty,
+ pp3: T3 => Pretty,
+ pp4: T4 => Pretty,
+ pp5: T5 => Pretty,
+ pp6: T6 => Pretty,
+ pp7: T7 => Pretty
+ ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2,g3,g4,g5,g6,g7)(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7)))
+
+ /** Universal quantifier for eight explicit generators.
+ * Does not shrink failed test cases. */
+ def forAllNoShrink[T1,T2,T3,T4,T5,T6,T7,T8,P](
+ g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7], g8: Gen[T8])(
+ f: (T1,T2,T3,T4,T5,T6,T7,T8) => P)(implicit
+ p: P => Prop,
+ pp1: T1 => Pretty,
+ pp2: T2 => Pretty,
+ pp3: T3 => Pretty,
+ pp4: T4 => Pretty,
+ pp5: T5 => Pretty,
+ pp6: T6 => Pretty,
+ pp7: T7 => Pretty,
+ pp8: T8 => Pretty
+ ): Prop = forAllNoShrink(g1)(t => forAllNoShrink(g2,g3,g4,g5,g6,g7,g8)(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7, _:T8)))
+
+ /** Converts a function into a universally quantified property */
+ def forAllNoShrink[A1,P](
+ f: A1 => P)(implicit
+ pv: P => Prop,
+ a1: Arbitrary[A1], pp1: A1 => Pretty
+ ): Prop = forAllNoShrink(arbitrary[A1])(f)
+
+ /** Converts a function into a universally quantified property */
+ def forAllNoShrink[A1,A2,P](
+ f: (A1,A2) => P)(implicit
+ pv: P => Prop,
+ a1: Arbitrary[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], pp2: A2 => Pretty
+ ): Prop = forAllNoShrink(arbitrary[A1], arbitrary[A2])(f)
+
+ /** Converts a function into a universally quantified property */
+ def forAllNoShrink[A1,A2,A3,P](
+ f: (A1,A2,A3) => P)(implicit
+ pv: P => Prop,
+ a1: Arbitrary[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], pp2: A2 => Pretty,
+ a3: Arbitrary[A3], pp3: A3 => Pretty
+ ): Prop = forAllNoShrink(arbitrary[A1], arbitrary[A2], arbitrary[A3])(f)
+
+ /** Converts a function into a universally quantified property */
+ def forAllNoShrink[A1,A2,A3,A4,P](
+ f: (A1,A2,A3,A4) => P)(implicit
+ pv: P => Prop,
+ a1: Arbitrary[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], pp2: A2 => Pretty,
+ a3: Arbitrary[A3], pp3: A3 => Pretty,
+ a4: Arbitrary[A4], pp4: A4 => Pretty
+ ): Prop = forAllNoShrink(arbitrary[A1], arbitrary[A2], arbitrary[A3], arbitrary[A4])(f)
+
+ /** Converts a function into a universally quantified property */
+ def forAllNoShrink[A1,A2,A3,A4,A5,P](
+ f: (A1,A2,A3,A4,A5) => P)(implicit
+ pv: P => Prop,
+ a1: Arbitrary[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], pp2: A2 => Pretty,
+ a3: Arbitrary[A3], pp3: A3 => Pretty,
+ a4: Arbitrary[A4], pp4: A4 => Pretty,
+ a5: Arbitrary[A5], pp5: A5 => Pretty
+ ): Prop = forAllNoShrink(arbitrary[A1], arbitrary[A2], arbitrary[A3], arbitrary[A4], arbitrary[A5])(f)
+
+ /** Converts a function into a universally quantified property */
+ def forAllNoShrink[A1,A2,A3,A4,A5,A6,P](
+ f: (A1,A2,A3,A4,A5,A6) => P)(implicit
+ pv: P => Prop,
+ a1: Arbitrary[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], pp2: A2 => Pretty,
+ a3: Arbitrary[A3], pp3: A3 => Pretty,
+ a4: Arbitrary[A4], pp4: A4 => Pretty,
+ a5: Arbitrary[A5], pp5: A5 => Pretty,
+ a6: Arbitrary[A6], pp6: A6 => Pretty
+ ): Prop = forAllNoShrink(arbitrary[A1], arbitrary[A2], arbitrary[A3], arbitrary[A4], arbitrary[A5], arbitrary[A6])(f)
+
+ /** Converts a function into a universally quantified property */
+ def forAllNoShrink[A1,A2,A3,A4,A5,A6,A7,P](
+ f: (A1,A2,A3,A4,A5,A6,A7) => P)(implicit
+ pv: P => Prop,
+ a1: Arbitrary[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], pp2: A2 => Pretty,
+ a3: Arbitrary[A3], pp3: A3 => Pretty,
+ a4: Arbitrary[A4], pp4: A4 => Pretty,
+ a5: Arbitrary[A5], pp5: A5 => Pretty,
+ a6: Arbitrary[A6], pp6: A6 => Pretty,
+ a7: Arbitrary[A7], pp7: A7 => Pretty
+ ): Prop = {
+ forAllNoShrink(arbitrary[A1], arbitrary[A2], arbitrary[A3], arbitrary[A4], arbitrary[A5], arbitrary[A6],
+ arbitrary[A7])(f)
+ }
+
+ /** Converts a function into a universally quantified property */
+ def forAllNoShrink[A1,A2,A3,A4,A5,A6,A7,A8,P](
+ f: (A1,A2,A3,A4,A5,A6,A7,A8) => P)(implicit
+ pv: P => Prop,
+ a1: Arbitrary[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], pp2: A2 => Pretty,
+ a3: Arbitrary[A3], pp3: A3 => Pretty,
+ a4: Arbitrary[A4], pp4: A4 => Pretty,
+ a5: Arbitrary[A5], pp5: A5 => Pretty,
+ a6: Arbitrary[A6], pp6: A6 => Pretty,
+ a7: Arbitrary[A7], pp7: A7 => Pretty,
+ a8: Arbitrary[A8], pp8: A8 => Pretty
+ ): Prop = {
+ forAllNoShrink(arbitrary[A1], arbitrary[A2], arbitrary[A3], arbitrary[A4], arbitrary[A5], arbitrary[A6],
+ arbitrary[A7], arbitrary[A8])(f)
+ }
+
+ /** Universal quantifier for an explicit generator. Shrinks failed arguments
+ * with the given shrink function */
+ def forAllShrink[T, P](g: Gen[T],
+ shrink: T => Stream[T])(f: T => P
+ )(implicit pv: P => Prop, pp: T => Pretty
+ ): Prop = Prop { prms =>
+
+ val gr = g.doApply(prms)
+ val labels = gr.labels.mkString(",")
+
+ def result(x: T) = {
+ val p = secure(pv(f(x)))
+ provedToTrue(p(prms))
+ }
+
+ /** Returns the first failed result in Left or success in Right */
+ def getFirstFailure(xs: Stream[T]): Either[(T,Result),(T,Result)] = {
+ assert(!xs.isEmpty, "Stream cannot be empty")
+ val results = xs.map(x => (x, result(x)))
+ results.dropWhile(!_._2.failure).headOption match {
+ case None => Right(results.head)
+ case Some(xr) => Left(xr)
+ }
+ }
+
+ def shrinker(x: T, r: Result, shrinks: Int, orig: T): Result = {
+ val xs = shrink(x).filter(gr.sieve)
+ val res = r.addArg(Arg(labels,x,shrinks,orig,pp(x),pp(orig)))
+ if(xs.isEmpty) res else getFirstFailure(xs) match {
+ case Right((x2,r2)) => res
+ case Left((x2,r2)) => shrinker(x2, replOrig(r,r2), shrinks+1, orig)
+ }
+ }
+
+ def replOrig(r0: Result, r1: Result) = (r0.args,r1.args) match {
+ case (a0::_,a1::as) =>
+ r1.copy(
+ args = a1.copy(
+ origArg = a0.origArg,
+ prettyOrigArg = a0.prettyOrigArg
+ ) :: as
+ )
+ case _ => r1
+ }
+
+ gr.retrieve match {
+ case None => undecided(prms)
+ case Some(x) =>
+ val r = result(x)
+ if (!r.failure) r.addArg(Arg(labels,x,0,x,pp(x),pp(x)))
+ else shrinker(x,r,0,x)
+ }
+
+ }
+
+ /** Universal quantifier for an explicit generator. Shrinks failed arguments
+ * with the default shrink function for the type */
+ def forAll[T1,P](
+ g1: Gen[T1])(
+ f: T1 => P)(implicit
+ p: P => Prop,
+ s1: Shrink[T1],
+ pp1: T1 => Pretty
+ ): Prop = forAllShrink[T1,P](g1, shrink[T1])(f)
+
+ /** Universal quantifier for two explicit generators. Shrinks failed arguments
+ * with the default shrink function for the type */
+ def forAll[T1,T2,P](
+ g1: Gen[T1], g2: Gen[T2])(
+ f: (T1,T2) => P)(implicit
+ p: P => Prop,
+ s1: Shrink[T1], pp1: T1 => Pretty,
+ s2: Shrink[T2], pp2: T2 => Pretty
+ ): Prop = forAll(g1)(t => forAll(g2)(f(t, _:T2)))
+
+ /** Universal quantifier for three explicit generators. Shrinks failed arguments
+ * with the default shrink function for the type */
+ def forAll[T1,T2,T3,P](
+ g1: Gen[T1], g2: Gen[T2], g3: Gen[T3])(
+ f: (T1,T2,T3) => P)(implicit
+ p: P => Prop,
+ s1: Shrink[T1], pp1: T1 => Pretty,
+ s2: Shrink[T2], pp2: T2 => Pretty,
+ s3: Shrink[T3], pp3: T3 => Pretty
+ ): Prop = forAll(g1)(t => forAll(g2,g3)(f(t, _:T2, _:T3)))
+
+ /** Universal quantifier for four explicit generators. Shrinks failed arguments
+ * with the default shrink function for the type */
+ def forAll[T1,T2,T3,T4,P](
+ g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4])(
+ f: (T1,T2,T3,T4) => P)(implicit
+ p: P => Prop,
+ s1: Shrink[T1], pp1: T1 => Pretty,
+ s2: Shrink[T2], pp2: T2 => Pretty,
+ s3: Shrink[T3], pp3: T3 => Pretty,
+ s4: Shrink[T4], pp4: T4 => Pretty
+ ): Prop = forAll(g1)(t => forAll(g2,g3,g4)(f(t, _:T2, _:T3, _:T4)))
+
+ /** Universal quantifier for five explicit generators. Shrinks failed arguments
+ * with the default shrink function for the type */
+ def forAll[T1,T2,T3,T4,T5,P](
+ g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5])(
+ f: (T1,T2,T3,T4,T5) => P)(implicit
+ p: P => Prop,
+ s1: Shrink[T1], pp1: T1 => Pretty,
+ s2: Shrink[T2], pp2: T2 => Pretty,
+ s3: Shrink[T3], pp3: T3 => Pretty,
+ s4: Shrink[T4], pp4: T4 => Pretty,
+ s5: Shrink[T5], pp5: T5 => Pretty
+ ): Prop = forAll(g1)(t => forAll(g2,g3,g4,g5)(f(t, _:T2, _:T3, _:T4, _:T5)))
+
+ /** Universal quantifier for six explicit generators. Shrinks failed arguments
+ * with the default shrink function for the type */
+ def forAll[T1,T2,T3,T4,T5,T6,P](
+ g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5], g6: Gen[T6])(
+ f: (T1,T2,T3,T4,T5,T6) => P)(implicit
+ p: P => Prop,
+ s1: Shrink[T1], pp1: T1 => Pretty,
+ s2: Shrink[T2], pp2: T2 => Pretty,
+ s3: Shrink[T3], pp3: T3 => Pretty,
+ s4: Shrink[T4], pp4: T4 => Pretty,
+ s5: Shrink[T5], pp5: T5 => Pretty,
+ s6: Shrink[T6], pp6: T6 => Pretty
+ ): Prop = forAll(g1)(t => forAll(g2,g3,g4,g5,g6)(f(t, _:T2, _:T3, _:T4, _:T5, _:T6)))
+
+ /** Universal quantifier for seven explicit generators. Shrinks failed arguments
+ * with the default shrink function for the type */
+ def forAll[T1,T2,T3,T4,T5,T6,T7,P](
+ g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7])(
+ f: (T1,T2,T3,T4,T5,T6,T7) => P)(implicit
+ p: P => Prop,
+ s1: Shrink[T1], pp1: T1 => Pretty,
+ s2: Shrink[T2], pp2: T2 => Pretty,
+ s3: Shrink[T3], pp3: T3 => Pretty,
+ s4: Shrink[T4], pp4: T4 => Pretty,
+ s5: Shrink[T5], pp5: T5 => Pretty,
+ s6: Shrink[T6], pp6: T6 => Pretty,
+ s7: Shrink[T7], pp7: T7 => Pretty
+ ): Prop = forAll(g1)(t => forAll(g2,g3,g4,g5,g6,g7)(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7)))
+
+ /** Universal quantifier for eight explicit generators. Shrinks failed arguments
+ * with the default shrink function for the type */
+ def forAll[T1,T2,T3,T4,T5,T6,T7,T8,P](
+ g1: Gen[T1], g2: Gen[T2], g3: Gen[T3], g4: Gen[T4], g5: Gen[T5], g6: Gen[T6], g7: Gen[T7], g8: Gen[T8])(
+ f: (T1,T2,T3,T4,T5,T6,T7,T8) => P)(implicit
+ p: P => Prop,
+ s1: Shrink[T1], pp1: T1 => Pretty,
+ s2: Shrink[T2], pp2: T2 => Pretty,
+ s3: Shrink[T3], pp3: T3 => Pretty,
+ s4: Shrink[T4], pp4: T4 => Pretty,
+ s5: Shrink[T5], pp5: T5 => Pretty,
+ s6: Shrink[T6], pp6: T6 => Pretty,
+ s7: Shrink[T7], pp7: T7 => Pretty,
+ s8: Shrink[T8], pp8: T8 => Pretty
+ ): Prop = forAll(g1)(t => forAll(g2,g3,g4,g5,g6,g7,g8)(f(t, _:T2, _:T3, _:T4, _:T5, _:T6, _:T7, _:T8)))
+
+ /** Converts a function into a universally quantified property */
+ def forAll[A1,P] (
+ f: A1 => P)(implicit
+ p: P => Prop,
+ a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty
+ ): Prop = forAllShrink(arbitrary[A1],shrink[A1])(f andThen p)
+
+ /** Converts a function into a universally quantified property */
+ def forAll[A1,A2,P] (
+ f: (A1,A2) => P)(implicit
+ p: P => Prop,
+ a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty
+ ): Prop = forAll((a: A1) => forAll(f(a, _:A2)))
+
+ /** Converts a function into a universally quantified property */
+ def forAll[A1,A2,A3,P] (
+ f: (A1,A2,A3) => P)(implicit
+ p: P => Prop,
+ a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty,
+ a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty
+ ): Prop = forAll((a: A1) => forAll(f(a, _:A2, _:A3)))
+
+ /** Converts a function into a universally quantified property */
+ def forAll[A1,A2,A3,A4,P] (
+ f: (A1,A2,A3,A4) => P)(implicit
+ p: P => Prop,
+ a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty,
+ a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty,
+ a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty
+ ): Prop = forAll((a: A1) => forAll(f(a, _:A2, _:A3, _:A4)))
+
+ /** Converts a function into a universally quantified property */
+ def forAll[A1,A2,A3,A4,A5,P] (
+ f: (A1,A2,A3,A4,A5) => P)(implicit
+ p: P => Prop,
+ a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty,
+ a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty,
+ a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty,
+ a5: Arbitrary[A5], s5: Shrink[A5], pp5: A5 => Pretty
+ ): Prop = forAll((a: A1) => forAll(f(a, _:A2, _:A3, _:A4, _:A5)))
+
+ /** Converts a function into a universally quantified property */
+ def forAll[A1,A2,A3,A4,A5,A6,P] (
+ f: (A1,A2,A3,A4,A5,A6) => P)(implicit
+ p: P => Prop,
+ a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty,
+ a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty,
+ a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty,
+ a5: Arbitrary[A5], s5: Shrink[A5], pp5: A5 => Pretty,
+ a6: Arbitrary[A6], s6: Shrink[A6], pp6: A6 => Pretty
+ ): Prop = forAll((a: A1) => forAll(f(a, _:A2, _:A3, _:A4, _:A5, _:A6)))
+
+ /** Converts a function into a universally quantified property */
+ def forAll[A1,A2,A3,A4,A5,A6,A7,P] (
+ f: (A1,A2,A3,A4,A5,A6,A7) => P)(implicit
+ p: P => Prop,
+ a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty,
+ a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty,
+ a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty,
+ a5: Arbitrary[A5], s5: Shrink[A5], pp5: A5 => Pretty,
+ a6: Arbitrary[A6], s6: Shrink[A6], pp6: A6 => Pretty,
+ a7: Arbitrary[A7], s7: Shrink[A7], pp7: A7 => Pretty
+ ): Prop = forAll((a: A1) => forAll(f(a, _:A2, _:A3, _:A4, _:A5, _:A6, _:A7)))
+
+ /** Converts a function into a universally quantified property */
+ def forAll[A1,A2,A3,A4,A5,A6,A7,A8,P] (
+ f: (A1,A2,A3,A4,A5,A6,A7,A8) => P)(implicit
+ p: P => Prop,
+ a1: Arbitrary[A1], s1: Shrink[A1], pp1: A1 => Pretty,
+ a2: Arbitrary[A2], s2: Shrink[A2], pp2: A2 => Pretty,
+ a3: Arbitrary[A3], s3: Shrink[A3], pp3: A3 => Pretty,
+ a4: Arbitrary[A4], s4: Shrink[A4], pp4: A4 => Pretty,
+ a5: Arbitrary[A5], s5: Shrink[A5], pp5: A5 => Pretty,
+ a6: Arbitrary[A6], s6: Shrink[A6], pp6: A6 => Pretty,
+ a7: Arbitrary[A7], s7: Shrink[A7], pp7: A7 => Pretty,
+ a8: Arbitrary[A8], s8: Shrink[A8], pp8: A8 => Pretty
+ ): Prop = forAll((a: A1) => forAll(f(a, _:A2, _:A3, _:A4, _:A5, _:A6, _:A7, _:A8)))
+
+ /** Ensures that the property expression passed in completes within the given
+ * space of time. */
+ def within(maximumMs: Long)(wrappedProp: => Prop): Prop = new Prop {
+ @tailrec private def attempt(prms: Parameters, endTime: Long): Result = {
+ val result = wrappedProp.apply(prms)
+ if (System.currentTimeMillis > endTime) {
+ (if(result.failure) result else Result(status = False)).label("Timeout")
+ } else {
+ if (result.success) result
+ else attempt(prms, endTime)
+ }
+ }
+ def apply(prms: Parameters) = attempt(prms, System.currentTimeMillis + maximumMs)
+ }
+}
diff --git a/src/partest-extras/scala/org/scalacheck/Properties.scala b/src/partest-extras/scala/org/scalacheck/Properties.scala
new file mode 100644
index 0000000000..abaac61c7f
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/Properties.scala
@@ -0,0 +1,82 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck
+
+import util.ConsoleReporter
+
+/** Represents a collection of properties, with convenient methods
+ * for checking all properties at once. This class is itself a property, which
+ * holds if and only if all of the contained properties hold.
+ * <p>Properties are added in the following way:</p>
+ *
+ * {{{
+ * object MyProps extends Properties("MyProps") {
+ * property("myProp1") = forAll { (n:Int, m:Int) =>
+ * n+m == m+n
+ * }
+ * }
+ * }}}
+ */
+class Properties(val name: String) extends Prop {
+
+ private val props = new scala.collection.mutable.ListBuffer[(String,Prop)]
+
+ /** Returns one property which holds if and only if all of the
+ * properties in this property collection hold */
+ private def oneProperty: Prop = Prop.all((properties map (_._2)):_*)
+
+ /** Returns all properties of this collection in a list of name/property
+ * pairs. */
+ def properties: Seq[(String,Prop)] = props
+
+ def apply(p: Gen.Parameters) = oneProperty(p)
+
+ /** Convenience method that checks the properties with the given parameters
+ * and reports the result on the console. If you need to get the results
+ * from the test use the `check` methods in [[org.scalacheck.Test]]
+ * instead. */
+ override def check(prms: Test.Parameters): Unit = Test.checkProperties(
+ prms.withTestCallback(ConsoleReporter(1) chain prms.testCallback), this
+ )
+
+ /** Convenience method that checks the properties and reports the
+ * result on the console. If you need to get the results from the test use
+ * the `check` methods in [[org.scalacheck.Test]] instead. */
+ override def check: Unit = check(Test.Parameters.default)
+
+ /** The logic for main, separated out to make it easier to
+ * avoid System.exit calls. Returns exit code.
+ */
+ override def mainRunner(args: Array[String]): Int = {
+ Test.parseParams(args) match {
+ case Some(params) =>
+ val res = Test.checkProperties(params, this)
+ val failed = res.filter(!_._2.passed).size
+ failed
+ case None =>
+ println("Incorrect options")
+ -1
+ }
+ }
+
+ /** Adds all properties from another property collection to this one. */
+ def include(ps: Properties) = for((n,p) <- ps.properties) property(n) = p
+
+ /** Used for specifying properties. Usage:
+ * {{{
+ * property("myProp") = ...
+ * }}}
+ */
+ class PropertySpecifier() {
+ def update(propName: String, p: Prop) = props += ((name+"."+propName, p))
+ }
+
+ lazy val property = new PropertySpecifier()
+}
diff --git a/src/partest-extras/scala/org/scalacheck/ScalaCheckFramework.scala b/src/partest-extras/scala/org/scalacheck/ScalaCheckFramework.scala
new file mode 100644
index 0000000000..754b67764d
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/ScalaCheckFramework.scala
@@ -0,0 +1,93 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck
+
+import util.Pretty
+
+import org.scalatools.testing._
+
+class ScalaCheckFramework extends Framework {
+
+ private def mkFP(mod: Boolean, cname: String) =
+ new SubclassFingerprint {
+ val superClassName = cname
+ val isModule = mod
+ }
+
+ val name = "ScalaCheck"
+
+ val tests = Array[Fingerprint](
+ mkFP(true, "org.scalacheck.Properties"),
+ mkFP(false, "org.scalacheck.Prop"),
+ mkFP(false, "org.scalacheck.Properties"),
+ mkFP(true, "org.scalacheck.Prop")
+ )
+
+ def testRunner(loader: ClassLoader, loggers: Array[Logger]) = new Runner2 {
+
+ private def asEvent(nr: (String, Test.Result)) = nr match {
+ case (n: String, r: Test.Result) => new Event {
+ val testName = n
+ val description = n
+ val result = r.status match {
+ case Test.Passed => Result.Success
+ case _:Test.Proved => Result.Success
+ case _:Test.Failed => Result.Failure
+ case Test.Exhausted => Result.Skipped
+ case _:Test.PropException | _:Test.GenException => Result.Error
+ }
+ val error = r.status match {
+ case Test.PropException(_, e, _) => e
+ case _:Test.Failed => new Exception(Pretty.pretty(r,Pretty.Params(0)))
+ case _ => null
+ }
+ }
+ }
+
+ def run(testClassName: String, fingerprint: Fingerprint, handler: EventHandler, args: Array[String]) {
+
+ val testCallback = new Test.TestCallback {
+ override def onPropEval(n: String, w: Int, s: Int, d: Int) = {}
+
+ override def onTestResult(n: String, r: Test.Result) = {
+ for (l <- loggers) {
+ import Pretty._
+ val verbosityOpts = Set("-verbosity", "-v")
+ val verbosity = args.grouped(2).filter(twos => verbosityOpts(twos.head)).toSeq.headOption.map(_.last).map(_.toInt).getOrElse(0)
+ l.info(
+ (if (r.passed) "+ " else "! ") + n + ": " + pretty(r, Params(verbosity))
+ )
+ }
+ handler.handle(asEvent((n,r)))
+ }
+ }
+
+ val prms = Test.parseParams(args) match {
+ case Some(params) =>
+ params.withTestCallback(testCallback).withCustomClassLoader(Some(loader))
+ // TODO: Maybe handle this a bit better than throwing exception?
+ case None => throw new Exception()
+ }
+
+ fingerprint match {
+ case fp: SubclassFingerprint =>
+ val obj =
+ if(fp.isModule) Class.forName(testClassName + "$", true, loader).getField("MODULE$").get(null)
+ else Class.forName(testClassName, true, loader).newInstance
+ if(obj.isInstanceOf[Properties])
+ Test.checkProperties(prms, obj.asInstanceOf[Properties])
+ else
+ handler.handle(asEvent((testClassName, Test.check(prms, obj.asInstanceOf[Prop]))))
+ }
+ }
+
+ }
+
+}
diff --git a/src/partest-extras/scala/org/scalacheck/Shrink.scala b/src/partest-extras/scala/org/scalacheck/Shrink.scala
new file mode 100644
index 0000000000..8ec28f4c4b
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/Shrink.scala
@@ -0,0 +1,215 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck
+
+import util.{Buildable,Buildable2}
+import scala.collection.{ JavaConversions => jcl }
+
+sealed abstract class Shrink[T] {
+ def shrink(x: T): Stream[T]
+}
+
+object Shrink {
+
+ import Stream.{cons, empty}
+ import scala.collection._
+ import java.util.ArrayList
+
+ /** Interleaves two streams */
+ private def interleave[T](xs: Stream[T], ys: Stream[T]): Stream[T] =
+ if(xs.isEmpty) ys
+ else if(ys.isEmpty) xs
+ else cons(xs.head, cons(ys.head, interleave(xs.tail, ys.tail)))
+
+ /** Shrink instance factory */
+ def apply[T](s: T => Stream[T]): Shrink[T] = new Shrink[T] {
+ override def shrink(x: T) = s(x)
+ }
+
+ /** Shrink a value */
+ def shrink[T](x: T)(implicit s: Shrink[T]): Stream[T] = s.shrink(x)
+
+ /** Default shrink instance */
+ implicit def shrinkAny[T]: Shrink[T] = Shrink(x => empty)
+
+ /** Shrink instance of container */
+ implicit def shrinkContainer[C[_],T](implicit v: C[T] => Traversable[T], s: Shrink[T],
+ b: Buildable[T,C]
+ ): Shrink[C[T]] = Shrink { xs: C[T] =>
+ val ys = v(xs)
+ val zs = ys.toStream
+ removeChunks(ys.size,zs).append(shrinkOne(zs)).map(b.fromIterable)
+ }
+
+ /** Shrink instance of container2 */
+ implicit def shrinkContainer2[C[_,_],T,U](implicit v: C[T,U] => Traversable[(T,U)], s: Shrink[(T,U)],
+ b: Buildable2[T,U,C]
+ ): Shrink[C[T,U]] = Shrink { xs: C[T,U] =>
+ val ys = v(xs)
+ val zs = ys.toStream
+ removeChunks(ys.size,zs).append(shrinkOne(zs)).map(b.fromIterable)
+ }
+
+ private def removeChunks[T](n: Int, xs: Stream[T]): Stream[Stream[T]] =
+ if (xs.isEmpty) empty
+ else if (xs.tail.isEmpty) cons(empty, empty)
+ else {
+ val n1 = n / 2
+ val n2 = n - n1
+ lazy val xs1 = xs.take(n1)
+ lazy val xs2 = xs.drop(n1)
+ lazy val xs3 =
+ for (ys1 <- removeChunks(n1, xs1) if !ys1.isEmpty) yield ys1 append xs2
+ lazy val xs4 =
+ for (ys2 <- removeChunks(n2, xs2) if !ys2.isEmpty) yield xs1 append ys2
+
+ cons(xs1, cons(xs2, interleave(xs3, xs4)))
+ }
+
+ private def shrinkOne[T : Shrink](zs: Stream[T]): Stream[Stream[T]] =
+ if (zs.isEmpty) empty
+ else {
+ val x = zs.head
+ val xs = zs.tail
+ shrink(x).map(cons(_,xs)).append(shrinkOne(xs).map(cons(x,_)))
+ }
+
+ /** Shrink instance of integer */
+ implicit lazy val shrinkInt: Shrink[Int] = Shrink { n =>
+
+ def halfs(n: Int): Stream[Int] =
+ if(n == 0) empty else cons(n, halfs(n/2))
+
+ if(n == 0) empty else {
+ val ns = halfs(n/2).map(n - _)
+ cons(0, interleave(ns, ns.map(-1 * _)))
+ }
+ }
+
+ /** Shrink instance of String */
+ implicit lazy val shrinkString: Shrink[String] = Shrink { s =>
+ shrinkContainer[List,Char].shrink(s.toList).map(_.mkString)
+ }
+
+ /** Shrink instance of Option */
+ implicit def shrinkOption[T : Shrink]: Shrink[Option[T]] = Shrink {
+ case None => empty
+ case Some(x) => cons(None, for(y <- shrink(x)) yield Some(y))
+ }
+
+ /** Shrink instance of 2-tuple */
+ implicit def shrinkTuple2[
+ T1:Shrink, T2:Shrink
+ ]: Shrink[(T1,T2)] =
+ Shrink { case (t1,t2) =>
+ shrink(t1).map((_,t2)) append
+ shrink(t2).map((t1,_))
+ }
+
+ /** Shrink instance of 3-tuple */
+ implicit def shrinkTuple3[
+ T1:Shrink, T2:Shrink, T3:Shrink
+ ]: Shrink[(T1,T2,T3)] =
+ Shrink { case (t1,t2,t3) =>
+ shrink(t1).map((_, t2, t3)) append
+ shrink(t2).map((t1, _, t3)) append
+ shrink(t3).map((t1, t2, _))
+ }
+
+ /** Shrink instance of 4-tuple */
+ implicit def shrinkTuple4[
+ T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink
+ ]: Shrink[(T1,T2,T3,T4)] =
+ Shrink { case (t1,t2,t3,t4) =>
+ shrink(t1).map((_, t2, t3, t4)) append
+ shrink(t2).map((t1, _, t3, t4)) append
+ shrink(t3).map((t1, t2, _, t4)) append
+ shrink(t4).map((t1, t2, t3, _))
+ }
+
+ /** Shrink instance of 5-tuple */
+ implicit def shrinkTuple5[
+ T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink
+ ]: Shrink[(T1,T2,T3,T4,T5)] =
+ Shrink { case (t1,t2,t3,t4,t5) =>
+ shrink(t1).map((_, t2, t3, t4, t5)) append
+ shrink(t2).map((t1, _, t3, t4, t5)) append
+ shrink(t3).map((t1, t2, _, t4, t5)) append
+ shrink(t4).map((t1, t2, t3, _, t5)) append
+ shrink(t5).map((t1, t2, t3, t4, _))
+ }
+
+ /** Shrink instance of 6-tuple */
+ implicit def shrinkTuple6[
+ T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink, T6:Shrink
+ ]: Shrink[(T1,T2,T3,T4,T5,T6)] =
+ Shrink { case (t1,t2,t3,t4,t5,t6) =>
+ shrink(t1).map((_, t2, t3, t4, t5, t6)) append
+ shrink(t2).map((t1, _, t3, t4, t5, t6)) append
+ shrink(t3).map((t1, t2, _, t4, t5, t6)) append
+ shrink(t4).map((t1, t2, t3, _, t5, t6)) append
+ shrink(t5).map((t1, t2, t3, t4, _, t6)) append
+ shrink(t6).map((t1, t2, t3, t4, t5, _))
+ }
+
+ /** Shrink instance of 7-tuple */
+ implicit def shrinkTuple7[
+ T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink, T6:Shrink, T7:Shrink
+ ]: Shrink[(T1,T2,T3,T4,T5,T6,T7)] =
+ Shrink { case (t1,t2,t3,t4,t5,t6,t7) =>
+ shrink(t1).map((_, t2, t3, t4, t5, t6, t7)) append
+ shrink(t2).map((t1, _, t3, t4, t5, t6, t7)) append
+ shrink(t3).map((t1, t2, _, t4, t5, t6, t7)) append
+ shrink(t4).map((t1, t2, t3, _, t5, t6, t7)) append
+ shrink(t5).map((t1, t2, t3, t4, _, t6, t7)) append
+ shrink(t6).map((t1, t2, t3, t4, t5, _, t7)) append
+ shrink(t7).map((t1, t2, t3, t4, t5, t6, _))
+ }
+
+ /** Shrink instance of 8-tuple */
+ implicit def shrinkTuple8[
+ T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink, T6:Shrink,
+ T7:Shrink, T8:Shrink
+ ]: Shrink[(T1,T2,T3,T4,T5,T6,T7,T8)] =
+ Shrink { case (t1,t2,t3,t4,t5,t6,t7,t8) =>
+ shrink(t1).map((_, t2, t3, t4, t5, t6, t7, t8)) append
+ shrink(t2).map((t1, _, t3, t4, t5, t6, t7, t8)) append
+ shrink(t3).map((t1, t2, _, t4, t5, t6, t7, t8)) append
+ shrink(t4).map((t1, t2, t3, _, t5, t6, t7, t8)) append
+ shrink(t5).map((t1, t2, t3, t4, _, t6, t7, t8)) append
+ shrink(t6).map((t1, t2, t3, t4, t5, _, t7, t8)) append
+ shrink(t7).map((t1, t2, t3, t4, t5, t6, _, t8)) append
+ shrink(t8).map((t1, t2, t3, t4, t5, t6, t7, _))
+ }
+
+ /** Shrink instance of 9-tuple */
+ implicit def shrinkTuple9[
+ T1:Shrink, T2:Shrink, T3:Shrink, T4:Shrink, T5:Shrink, T6:Shrink,
+ T7:Shrink, T8:Shrink, T9:Shrink
+ ]: Shrink[(T1,T2,T3,T4,T5,T6,T7,T8,T9)] =
+ Shrink { case (t1,t2,t3,t4,t5,t6,t7,t8,t9) =>
+ shrink(t1).map((_, t2, t3, t4, t5, t6, t7, t8, t9)) append
+ shrink(t2).map((t1, _, t3, t4, t5, t6, t7, t8, t9)) append
+ shrink(t3).map((t1, t2, _, t4, t5, t6, t7, t8, t9)) append
+ shrink(t4).map((t1, t2, t3, _, t5, t6, t7, t8, t9)) append
+ shrink(t5).map((t1, t2, t3, t4, _, t6, t7, t8, t9)) append
+ shrink(t6).map((t1, t2, t3, t4, t5, _, t7, t8, t9)) append
+ shrink(t7).map((t1, t2, t3, t4, t5, t6, _, t8, t9)) append
+ shrink(t8).map((t1, t2, t3, t4, t5, t6, t7, _, t9)) append
+ shrink(t9).map((t1, t2, t3, t4, t5, t6, t7, t8, _))
+ }
+
+ /** Transform a Shrink[T] to a Shrink[U] where T and U are two isomorphic types
+ * whose relationship is described by the provided transformation functions.
+ * (exponential functor map) */
+ def xmap[T, U](from: T => U, to: U => T)(implicit st: Shrink[T]): Shrink[U] = Shrink[U] { u: U ⇒
+ st.shrink(to(u)).map(from)
+ }
+}
diff --git a/src/partest-extras/scala/org/scalacheck/Test.scala b/src/partest-extras/scala/org/scalacheck/Test.scala
new file mode 100644
index 0000000000..9a9c62b93f
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/Test.scala
@@ -0,0 +1,372 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck
+
+import Prop.Arg
+
+object Test {
+
+ import util.{FreqMap, ConsoleReporter}
+
+ /** Test parameters used by the check methods. Default
+ * parameters are defined by [[Test.Parameters.Default]]. */
+ trait Parameters {
+ /** The minimum number of tests that must succeed for ScalaCheck to
+ * consider a property passed. */
+ val minSuccessfulTests: Int
+
+ /** Create a copy of this [[Test.Parameters]] instance with
+ * [[Test.Parameters.minSuccessfulTests]] set to the specified value. */
+ def withMinSuccessfulTests(minSuccessfulTests: Int): Parameters = cp(
+ minSuccessfulTests = minSuccessfulTests
+ )
+
+ /** The starting size given as parameter to the generators. */
+ val minSize: Int
+
+ /** Create a copy of this [[Test.Parameters]] instance with
+ * [[Test.Parameters.minSize]] set to the specified value. */
+ def withMinSize(minSize: Int): Parameters = cp(
+ minSize = minSize
+ )
+
+ /** The maximum size given as parameter to the generators. */
+ val maxSize: Int
+
+ /** Create a copy of this [[Test.Parameters]] instance with
+ * [[Test.Parameters.maxSize]] set to the specified value. */
+ def withMaxSize(maxSize: Int): Parameters = cp(
+ maxSize = maxSize
+ )
+
+ /** The random number generator used. */
+ val rng: scala.util.Random
+
+ /** Create a copy of this [[Test.Parameters]] instance with
+ * [[Test.Parameters.rng]] set to the specified value. */
+ def withRng(rng: scala.util.Random): Parameters = cp(
+ rng = rng
+ )
+
+ /** The number of tests to run in parallel. */
+ val workers: Int
+
+ /** Create a copy of this [[Test.Parameters]] instance with
+ * [[Test.Parameters.workers]] set to the specified value. */
+ def withWorkers(workers: Int): Parameters = cp(
+ workers = workers
+ )
+
+ /** A callback that ScalaCheck calls each time a test is executed. */
+ val testCallback: TestCallback
+
+ /** Create a copy of this [[Test.Parameters]] instance with
+ * [[Test.Parameters.testCallback]] set to the specified value. */
+ def withTestCallback(testCallback: TestCallback): Parameters = cp(
+ testCallback = testCallback
+ )
+
+ /** The maximum ratio between discarded and passed tests allowed before
+ * ScalaCheck gives up and discards the property. At least
+ * `minSuccesfulTests` will always be run, though. */
+ val maxDiscardRatio: Float
+
+ /** Create a copy of this [[Test.Parameters]] instance with
+ * [[Test.Parameters.maxDiscardRatio]] set to the specified value. */
+ def withMaxDiscardRatio(maxDiscardRatio: Float): Parameters = cp(
+ maxDiscardRatio = maxDiscardRatio
+ )
+
+ /** A custom class loader that should be used during test execution. */
+ val customClassLoader: Option[ClassLoader]
+
+ /** Create a copy of this [[Test.Parameters]] instance with
+ * [[Test.Parameters.customClassLoader]] set to the specified value. */
+ def withCustomClassLoader(customClassLoader: Option[ClassLoader]
+ ): Parameters = cp(
+ customClassLoader = customClassLoader
+ )
+
+ // private since we can't guarantee binary compatibility for this one
+ private case class cp(
+ minSuccessfulTests: Int = minSuccessfulTests,
+ minSize: Int = minSize,
+ maxSize: Int = maxSize,
+ rng: scala.util.Random = rng,
+ workers: Int = workers,
+ testCallback: TestCallback = testCallback,
+ maxDiscardRatio: Float = maxDiscardRatio,
+ customClassLoader: Option[ClassLoader] = customClassLoader
+ ) extends Parameters
+ }
+
+ /** Test parameters used by the check methods. Default
+ * parameters are defined by [[Test.Parameters.Default]]. */
+ object Parameters {
+ /** Default test parameters trait. This can be overriden if you need to
+ * tweak the parameters:
+ *
+ * {{{
+ * val myParams = new Parameters.Default {
+ * override val minSuccesfulTests = 600
+ * override val maxDiscardRatio = 8
+ * }
+ * }}}
+ *
+ * You can also use the withXXX-methods in
+ * [[org.scalacheck.Test.Parameters]] to achieve
+ * the same thing:
+ *
+ * {{{
+ * val myParams = Parameters.default
+ * .withMinSuccessfulTests(600)
+ * .withMaxDiscardRatio(8)
+ * }}} */
+ trait Default extends Parameters {
+ val minSuccessfulTests: Int = 100
+ val minSize: Int = 0
+ val maxSize: Int = Gen.Parameters.default.size
+ val rng: scala.util.Random = Gen.Parameters.default.rng
+ val workers: Int = 1
+ val testCallback: TestCallback = new TestCallback {}
+ val maxDiscardRatio: Float = 5
+ val customClassLoader: Option[ClassLoader] = None
+ }
+
+ /** Default test parameters instance. */
+ val default: Parameters = new Default {}
+
+ /** Verbose console reporter test parameters instance. */
+ val defaultVerbose: Parameters = new Default {
+ override val testCallback = ConsoleReporter(2)
+ }
+ }
+
+ /** Test statistics */
+ case class Result(
+ status: Status,
+ succeeded: Int,
+ discarded: Int,
+ freqMap: FreqMap[Set[Any]],
+ time: Long = 0
+ ) {
+ def passed = status match {
+ case Passed => true
+ case Proved(_) => true
+ case _ => false
+ }
+ }
+
+ /** Test status */
+ sealed trait Status
+
+ /** ScalaCheck found enough cases for which the property holds, so the
+ * property is considered correct. (It is not proved correct, though). */
+ case object Passed extends Status
+
+ /** ScalaCheck managed to prove the property correct */
+ sealed case class Proved(args: List[Arg[Any]]) extends Status
+
+ /** The property was proved wrong with the given concrete arguments. */
+ sealed case class Failed(args: List[Arg[Any]], labels: Set[String]) extends Status
+
+ /** The property test was exhausted, it wasn't possible to generate enough
+ * concrete arguments satisfying the preconditions to get enough passing
+ * property evaluations. */
+ case object Exhausted extends Status
+
+ /** An exception was raised when trying to evaluate the property with the
+ * given concrete arguments. If an exception was raised before or during
+ * argument generation, the argument list will be empty. */
+ sealed case class PropException(args: List[Arg[Any]], e: Throwable,
+ labels: Set[String]) extends Status
+
+ /** An exception was raised when trying to generate concrete arguments
+ * for evaluating the property.
+ * @deprecated Not used. The type PropException is used for all exceptions.
+ */
+ @deprecated("Not used. The type PropException is used for all exceptions.", "1.11.2")
+ sealed case class GenException(e: Throwable) extends Status
+
+ trait TestCallback { self =>
+ /** Called each time a property is evaluated */
+ def onPropEval(name: String, threadIdx: Int, succeeded: Int,
+ discarded: Int): Unit = ()
+
+ /** Called whenever a property has finished testing */
+ def onTestResult(name: String, result: Result): Unit = ()
+
+ def chain(testCallback: TestCallback) = new TestCallback {
+ override def onPropEval(name: String, threadIdx: Int,
+ succeeded: Int, discarded: Int
+ ): Unit = {
+ self.onPropEval(name,threadIdx,succeeded,discarded)
+ testCallback.onPropEval(name,threadIdx,succeeded,discarded)
+ }
+
+ override def onTestResult(name: String, result: Result): Unit = {
+ self.onTestResult(name,result)
+ testCallback.onTestResult(name,result)
+ }
+ }
+ }
+
+ private def assertParams(prms: Parameters) = {
+ import prms._
+ if(
+ minSuccessfulTests <= 0 ||
+ maxDiscardRatio <= 0 ||
+ minSize < 0 ||
+ maxSize < minSize ||
+ workers <= 0
+ ) throw new IllegalArgumentException("Invalid test parameters")
+ }
+
+ private def secure[T](x: => T): Either[T,Throwable] =
+ try { Left(x) } catch { case e: Throwable => Right(e) }
+
+ def parseParams(args: Array[String]): Option[Parameters] = {
+ var params = Parameters.default
+ args.grouped(2).filter(_.size > 1).map(a => (a(0), a(1))).foreach {
+ case ("-workers" | "-w", n) => params = params.withWorkers(n.toInt)
+ case ("-minSize" | "-n", n) => params = params.withMinSize(n.toInt)
+ case ("-maxSize" | "-x", n) => params = params.withMaxSize(n.toInt)
+ case ("-verbosity" | "-v", n) => params = params.withTestCallback(ConsoleReporter(n.toInt))
+ case ("-maxDiscardRatio" | "-r", n) => params = params.withMaxDiscardRatio(n.toFloat)
+ case ("-minSuccessfulTests" | "-s", n) => params = params.withMinSuccessfulTests(n.toInt)
+ case _ =>
+ }
+ Some(params)
+ }
+
+ /** Tests a property with parameters that are calculated by applying
+ * the provided function to [[Test.Parameters.default]].
+ * Example use:
+ *
+ * {{{
+ * Test.check(p) { _.
+ * withMinSuccessfulTests(80000).
+ * withWorkers(4)
+ * }
+ * }}}
+ */
+ def check(p: Prop)(f: Parameters => Parameters): Result =
+ check(f(Parameters.default), p)
+
+ /** Tests a property with the given testing parameters, and returns
+ * the test results. */
+ def check(params: Parameters, p: Prop): Result = {
+ import params._
+ import concurrent._
+
+ assertParams(params)
+ if(workers > 1) {
+ assert(!p.isInstanceOf[Commands], "Commands cannot be checked multi-threaded")
+ }
+
+ val iterations = math.ceil(minSuccessfulTests / (workers: Double))
+ val sizeStep = (maxSize-minSize) / (iterations*workers)
+ var stop = false
+ val genPrms = new Gen.Parameters.Default { override val rng = params.rng }
+ val tp = java.util.concurrent.Executors.newFixedThreadPool(workers)
+ implicit val ec = ExecutionContext.fromExecutor(tp)
+
+ def workerFun(workerIdx: Int): Result = {
+ var n = 0 // passed tests
+ var d = 0 // discarded tests
+ var res: Result = null
+ var fm = FreqMap.empty[Set[Any]]
+ while(!stop && res == null && n < iterations) {
+ val size = (minSize: Double) + (sizeStep * (workerIdx + (workers*(n+d))))
+ val propRes = p(genPrms.withSize(size.round.toInt))
+ fm = if(propRes.collected.isEmpty) fm else fm + propRes.collected
+ propRes.status match {
+ case Prop.Undecided =>
+ d += 1
+ testCallback.onPropEval("", workerIdx, n, d)
+ // The below condition is kind of hacky. We have to have
+ // some margin, otherwise workers might stop testing too
+ // early because they have been exhausted, but the overall
+ // test has not.
+ if (n+d > minSuccessfulTests && 1+workers*maxDiscardRatio*n < d)
+ res = Result(Exhausted, n, d, fm)
+ case Prop.True =>
+ n += 1
+ testCallback.onPropEval("", workerIdx, n, d)
+ case Prop.Proof =>
+ n += 1
+ res = Result(Proved(propRes.args), n, d, fm)
+ stop = true
+ case Prop.False =>
+ res = Result(Failed(propRes.args,propRes.labels), n, d, fm)
+ stop = true
+ case Prop.Exception(e) =>
+ res = Result(PropException(propRes.args,e,propRes.labels), n, d, fm)
+ stop = true
+ }
+ }
+ if (res == null) {
+ if (maxDiscardRatio*n > d) Result(Passed, n, d, fm)
+ else Result(Exhausted, n, d, fm)
+ } else res
+ }
+
+ def mergeResults(r1: Result, r2: Result): Result = {
+ val Result(st1, s1, d1, fm1, _) = r1
+ val Result(st2, s2, d2, fm2, _) = r2
+ if (st1 != Passed && st1 != Exhausted)
+ Result(st1, s1+s2, d1+d2, fm1++fm2, 0)
+ else if (st2 != Passed && st2 != Exhausted)
+ Result(st2, s1+s2, d1+d2, fm1++fm2, 0)
+ else {
+ if (s1+s2 >= minSuccessfulTests && maxDiscardRatio*(s1+s2) >= (d1+d2))
+ Result(Passed, s1+s2, d1+d2, fm1++fm2, 0)
+ else
+ Result(Exhausted, s1+s2, d1+d2, fm1++fm2, 0)
+ }
+ }
+
+ try {
+ val start = System.currentTimeMillis
+ val r =
+ if(workers < 2) workerFun(0)
+ else {
+ val fs = List.range(0,workers) map (idx => Future {
+ params.customClassLoader.map(
+ Thread.currentThread.setContextClassLoader(_)
+ )
+ blocking { workerFun(idx) }
+ })
+ val zeroRes = Result(Passed,0,0,FreqMap.empty[Set[Any]],0)
+ val res = Future.fold(fs)(zeroRes)(mergeResults)
+ Await.result(res, concurrent.duration.Duration.Inf)
+ }
+ val timedRes = r.copy(time = System.currentTimeMillis-start)
+ params.testCallback.onTestResult("", timedRes)
+ timedRes
+ } finally {
+ stop = true
+ tp.shutdown()
+ }
+ }
+
+ /** Check a set of properties. */
+ def checkProperties(prms: Parameters, ps: Properties): Seq[(String,Result)] =
+ ps.properties.map { case (name,p) =>
+ val testCallback = new TestCallback {
+ override def onPropEval(n: String, t: Int, s: Int, d: Int) =
+ prms.testCallback.onPropEval(name,t,s,d)
+ override def onTestResult(n: String, r: Result) =
+ prms.testCallback.onTestResult(name,r)
+ }
+ val res = check(prms.withTestCallback(testCallback), p)
+ (name,res)
+ }
+}
diff --git a/src/partest-extras/scala/org/scalacheck/util/Buildable.scala b/src/partest-extras/scala/org/scalacheck/util/Buildable.scala
new file mode 100644
index 0000000000..6a275b05c2
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/util/Buildable.scala
@@ -0,0 +1,77 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck.util
+
+import collection._
+
+trait Buildable[T,C[_]] {
+ def builder: mutable.Builder[T,C[T]]
+ def fromIterable(it: Traversable[T]): C[T] = {
+ val b = builder
+ b ++= it
+ b.result()
+ }
+}
+
+trait Buildable2[T,U,C[_,_]] {
+ def builder: mutable.Builder[(T,U),C[T,U]]
+ def fromIterable(it: Traversable[(T,U)]): C[T,U] = {
+ val b = builder
+ b ++= it
+ b.result()
+ }
+}
+
+object Buildable {
+ import generic.CanBuildFrom
+
+ implicit def buildableCanBuildFrom[T, C[_]](implicit c: CanBuildFrom[C[_], T, C[T]]) =
+ new Buildable[T, C] {
+ def builder = c.apply
+ }
+
+ import java.util.ArrayList
+ implicit def buildableArrayList[T] = new Buildable[T,ArrayList] {
+ def builder = new mutable.Builder[T,ArrayList[T]] {
+ val al = new ArrayList[T]
+ def +=(x: T) = {
+ al.add(x)
+ this
+ }
+ def clear() = al.clear()
+ def result() = al
+ }
+ }
+
+}
+
+object Buildable2 {
+
+ implicit def buildableMutableMap[T,U] = new Buildable2[T,U,mutable.Map] {
+ def builder = mutable.Map.newBuilder
+ }
+
+ implicit def buildableImmutableMap[T,U] = new Buildable2[T,U,immutable.Map] {
+ def builder = immutable.Map.newBuilder
+ }
+
+ implicit def buildableMap[T,U] = new Buildable2[T,U,Map] {
+ def builder = Map.newBuilder
+ }
+
+ implicit def buildableImmutableSortedMap[T: Ordering, U] = new Buildable2[T,U,immutable.SortedMap] {
+ def builder = immutable.SortedMap.newBuilder
+ }
+
+ implicit def buildableSortedMap[T: Ordering, U] = new Buildable2[T,U,SortedMap] {
+ def builder = SortedMap.newBuilder
+ }
+
+}
diff --git a/src/partest-extras/scala/org/scalacheck/util/CmdLineParser.scala b/src/partest-extras/scala/org/scalacheck/util/CmdLineParser.scala
new file mode 100644
index 0000000000..45b6ac6948
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/util/CmdLineParser.scala
@@ -0,0 +1,41 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck.util
+
+import scala.collection.Set
+import org.scalacheck.Test
+
+private[scalacheck] trait CmdLineParser {
+
+ type Elem = String
+
+ trait Opt[+T] {
+ val default: T
+ val names: Set[String]
+ val help: String
+ }
+ trait Flag extends Opt[Unit]
+ trait IntOpt extends Opt[Int]
+ trait FloatOpt extends Opt[Float]
+ trait StrOpt extends Opt[String]
+
+ class OptMap {
+ private val opts = new collection.mutable.HashMap[Opt[_], Any]
+ def apply(flag: Flag): Boolean = opts.contains(flag)
+ def apply[T](opt: Opt[T]): T = opts.get(opt) match {
+ case None => opt.default
+ case Some(v) => v.asInstanceOf[T]
+ }
+ def update[T](opt: Opt[T], optVal: T) = opts.update(opt, optVal)
+ }
+
+ val opts: Set[Opt[_]]
+
+}
diff --git a/src/partest-extras/scala/org/scalacheck/util/ConsoleReporter.scala b/src/partest-extras/scala/org/scalacheck/util/ConsoleReporter.scala
new file mode 100644
index 0000000000..89858dfb64
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/util/ConsoleReporter.scala
@@ -0,0 +1,44 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck.util
+
+import Pretty.{Params, pretty, format}
+import org.scalacheck.{Prop, Properties, Test}
+
+/** A [[org.scalacheck.Test.TestCallback]] implementation that prints
+ * test results directly to the console. This is the callback used
+ * by ScalaCheck's command line test runner, and when you run [[org.scalacheck.Prop!.check:Unit*]]
+ */
+class ConsoleReporter(val verbosity: Int) extends Test.TestCallback {
+
+ private val prettyPrms = Params(verbosity)
+
+ override def onTestResult(name: String, res: Test.Result) = {
+ if(verbosity > 0) {
+ if(name == "") {
+ val s = (if(res.passed) "+ " else "! ") + pretty(res, prettyPrms)
+ printf("\r%s\n", format(s, "", "", 75))
+ } else {
+ val s = (if(res.passed) "+ " else "! ") + name + ": " +
+ pretty(res, prettyPrms)
+ printf("\r%s\n", format(s, "", "", 75))
+ }
+ }
+ }
+
+}
+
+object ConsoleReporter {
+
+ /** Factory method, creates a ConsoleReporter with the
+ * the given verbosity */
+ def apply(verbosity: Int = 0) = new ConsoleReporter(verbosity)
+
+}
diff --git a/src/partest-extras/scala/org/scalacheck/util/FreqMap.scala b/src/partest-extras/scala/org/scalacheck/util/FreqMap.scala
new file mode 100644
index 0000000000..2a9f36f1e5
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/util/FreqMap.scala
@@ -0,0 +1,65 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck.util
+
+trait FreqMap[T] {
+ protected val underlying: scala.collection.immutable.Map[T,Int]
+ val total: Int
+
+ def +(t: T) = new FreqMap[T] {
+ private val n = FreqMap.this.underlying.get(t) match {
+ case None => 1
+ case Some(n) => n+1
+ }
+ val underlying = FreqMap.this.underlying + (t -> n)
+ val total = FreqMap.this.total + 1
+ }
+
+ def -(t: T) = new FreqMap[T] {
+ val underlying = FreqMap.this.underlying.get(t) match {
+ case None => FreqMap.this.underlying
+ case Some(n) => FreqMap.this.underlying + (t -> (n-1))
+ }
+ val total = FreqMap.this.total + 1
+ }
+
+ def ++(fm: FreqMap[T]) = new FreqMap[T] {
+ private val keys = FreqMap.this.underlying.keySet ++ fm.underlying.keySet
+ private val mappings = keys.toStream.map { x =>
+ (x, fm.getCount(x).getOrElse(0) + FreqMap.this.getCount(x).getOrElse(0))
+ }
+ val underlying = scala.collection.immutable.Map(mappings: _*)
+ val total = FreqMap.this.total + fm.total
+ }
+
+ def --(fm: FreqMap[T]) = new FreqMap[T] {
+ val underlying = FreqMap.this.underlying transform {
+ case (x,n) => n - fm.getCount(x).getOrElse(0)
+ }
+ lazy val total = (0 /: underlying.valuesIterator) (_ + _)
+ }
+
+ def getCount(t: T) = underlying.get(t)
+
+ def getCounts: List[(T,Int)] = underlying.toList.sortBy(-_._2)
+
+ def getRatio(t: T) = for(c <- getCount(t)) yield (c: Float)/total
+
+ def getRatios = for((t,c) <- getCounts) yield (t, (c: Float)/total)
+
+ override def toString = underlying.toString
+}
+
+object FreqMap {
+ def empty[T] = new FreqMap[T] {
+ val underlying = scala.collection.immutable.Map.empty[T,Int]
+ val total = 0
+ }
+}
diff --git a/src/partest-extras/scala/org/scalacheck/util/Pretty.scala b/src/partest-extras/scala/org/scalacheck/util/Pretty.scala
new file mode 100644
index 0000000000..13a1b44b51
--- /dev/null
+++ b/src/partest-extras/scala/org/scalacheck/util/Pretty.scala
@@ -0,0 +1,129 @@
+/*-------------------------------------------------------------------------*\
+** ScalaCheck **
+** Copyright (c) 2007-2014 Rickard Nilsson. All rights reserved. **
+** http://www.scalacheck.org **
+** **
+** This software is released under the terms of the Revised BSD License. **
+** There is NO WARRANTY. See the file LICENSE for the full text. **
+\*------------------------------------------------------------------------ */
+
+package org.scalacheck.util
+
+import org.scalacheck.Prop.Arg
+import org.scalacheck.Test
+
+import math.round
+
+
+sealed trait Pretty {
+ def apply(prms: Pretty.Params): String
+
+ def map(f: String => String) = Pretty(prms => f(Pretty.this(prms)))
+
+ def flatMap(f: String => Pretty) = Pretty(prms => f(Pretty.this(prms))(prms))
+}
+
+object Pretty {
+
+ case class Params(verbosity: Int)
+
+ val defaultParams = Params(0)
+
+ def apply(f: Params => String) = new Pretty { def apply(p: Params) = f(p) }
+
+ def pretty[T <% Pretty](t: T, prms: Params): String = t(prms)
+
+ def pretty[T <% Pretty](t: T): String = t(defaultParams)
+
+ implicit def strBreak(s1: String) = new {
+ def /(s2: String) = if(s2 == "") s1 else s1+"\n"+s2
+ }
+
+ def pad(s: String, c: Char, length: Int) =
+ if(s.length >= length) s
+ else s + List.fill(length-s.length)(c).mkString
+
+ def break(s: String, lead: String, length: Int): String =
+ if(s.length <= length) s
+ else s.substring(0, length) / break(lead+s.substring(length), lead, length)
+
+ def format(s: String, lead: String, trail: String, width: Int) =
+ s.lines.map(l => break(lead+l+trail, " ", width)).mkString("\n")
+
+ implicit def prettyAny(t: Any) = Pretty { p => t.toString }
+
+ implicit def prettyString(t: String) = Pretty { p => "\""++t++"\"" }
+
+ implicit def prettyList(l: List[Any]) = Pretty { p =>
+ l.map("\""+_+"\"").mkString("List(", ", ", ")")
+ }
+
+ implicit def prettyThrowable(e: Throwable) = Pretty { prms =>
+ val strs = e.getStackTrace.map { st =>
+ import st._
+ getClassName+"."+getMethodName + "("+getFileName+":"+getLineNumber+")"
+ }
+
+ val strs2 =
+ if(prms.verbosity <= 0) Array[String]()
+ else if(prms.verbosity <= 1) strs.take(5)
+ else strs
+
+ e.getClass.getName + ": " + e.getMessage / strs2.mkString("\n")
+ }
+
+ def prettyArgs(args: Seq[Arg[Any]]): Pretty = Pretty { prms =>
+ if(args.isEmpty) "" else {
+ for((a,i) <- args.zipWithIndex) yield {
+ val l = "> "+(if(a.label == "") "ARG_"+i else a.label)
+ val s =
+ if(a.shrinks == 0) ""
+ else "\n"+l+"_ORIGINAL: "+a.prettyOrigArg(prms)
+ l+": "+a.prettyArg(prms)+""+s
+ }
+ }.mkString("\n")
+ }
+
+ implicit def prettyFreqMap(fm: FreqMap[Set[Any]]) = Pretty { prms =>
+ if(fm.total == 0) ""
+ else {
+ "> Collected test data: " / {
+ for {
+ (xs,r) <- fm.getRatios
+ ys = xs - (())
+ if !ys.isEmpty
+ } yield round(r*100)+"% " + ys.mkString(", ")
+ }.mkString("\n")
+ }
+ }
+
+ implicit def prettyTestRes(res: Test.Result) = Pretty { prms =>
+ def labels(ls: collection.immutable.Set[String]) =
+ if(ls.isEmpty) ""
+ else "> Labels of failing property: " / ls.mkString("\n")
+ val s = res.status match {
+ case Test.Proved(args) => "OK, proved property."/prettyArgs(args)(prms)
+ case Test.Passed => "OK, passed "+res.succeeded+" tests."
+ case Test.Failed(args, l) =>
+ "Falsified after "+res.succeeded+" passed tests."/labels(l)/prettyArgs(args)(prms)
+ case Test.Exhausted =>
+ "Gave up after only "+res.succeeded+" passed tests. " +
+ res.discarded+" tests were discarded."
+ case Test.PropException(args,e,l) =>
+ "Exception raised on property evaluation."/labels(l)/prettyArgs(args)(prms)/
+ "> Exception: "+pretty(e,prms)
+ case Test.GenException(e) =>
+ "Exception raised on argument generation."/
+ "> Exception: "+pretty(e,prms)
+ }
+ val t = if(prms.verbosity <= 1) "" else "Elapsed time: "+prettyTime(res.time)
+ s/t/pretty(res.freqMap,prms)
+ }
+
+ def prettyTime(millis: Long): String = {
+ val min = millis/(60*1000)
+ val sec = (millis-(60*1000*min)) / 1000d
+ if(min <= 0) "%.3f sec ".format(sec)
+ else "%d min %.3f sec ".format(min, sec)
+ }
+}
diff --git a/versions.properties b/versions.properties
index 488535c991..3b8077ab88 100644
--- a/versions.properties
+++ b/versions.properties
@@ -31,7 +31,9 @@ scala-asm.version=5.0.4-scala-3
# external modules, used internally (not shipped)
partest.version.number=1.0.16
-scalacheck.version.number=1.11.6
+# We've embedded these sources in partest-extras for now. After 2.12.0 is released
+# we can switch to a public release.
+# scalacheck.version.number=1.11.6
# TODO: modularize the compiler
#scala-compiler-doc.version.number=1.0.0-RC1