From fa54a449fe2f08facf1197e39054d58c60d93182 Mon Sep 17 00:00:00 2001 From: satorg Date: Sat, 3 Jun 2023 17:01:18 -0700 Subject: [PATCH 1/3] re-enable scalafmt --- .scalafmt.conf | 2 -- 1 file changed, 2 deletions(-) diff --git a/.scalafmt.conf b/.scalafmt.conf index 45690abb..58d85e4e 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -30,5 +30,3 @@ fileOverride { project.excludeFilters = [ "scalafix/*" ] - -project.includePaths = [] # temporarily disable formatting From ccd98e22a078e1282dbb2c1acfb40fe3afee01b6 Mon Sep 17 00:00:00 2001 From: satorg Date: Sat, 3 Jun 2023 17:43:03 -0700 Subject: [PATCH 2/3] apply scalafmtAll --- .../scala/org/scalacheck/bench/GenBench.scala | 63 +- build.sbt | 18 +- .../main/scala/org/scalacheck/Platform.scala | 10 +- .../main/scala/org/scalacheck/Platform.scala | 35 +- .../scalacheck/ArbitrarySpecification.scala | 2 +- .../org/scalacheck/ChooseSpecification.scala | 18 +- .../org/scalacheck/CogenSpecification.scala | 30 +- .../org/scalacheck/GenSpecification.scala | 179 ++- .../PropertyFilterSpecification.scala | 86 +- .../SerializabilitySpecification.scala | 85 +- .../scalacheck/ShrinkSpecificationJVM.scala | 4 +- .../org/scalacheck/TestSpecification.scala | 41 +- .../CommandsShrinkSpecification.scala | 16 +- .../commands/CommandsSpecification.scala | 17 +- .../org/scalacheck/examples/IntMapSpec.scala | 11 +- .../org/scalacheck/examples/StringUtils.scala | 26 +- .../scalacheck/rng/SeedSpecification.scala | 6 +- .../scalacheck/time/ShrinkSpecification.scala | 5 +- .../main/scala/org/scalacheck/Platform.scala | 10 +- .../org/scalacheck/ScalaVersionSpecific.scala | 2 +- .../util/BuildableVersionSpecific.scala | 10 +- .../org/scalacheck/ScalaVersionSpecific.scala | 1 + .../util/BuildableVersionSpecific.scala | 14 +- .../main/scala/org/scalacheck/Arbitrary.scala | 240 +-- .../src/main/scala/org/scalacheck/Cogen.scala | 49 +- .../src/main/scala/org/scalacheck/Gen.scala | 1089 ++++++------- .../src/main/scala/org/scalacheck/Prop.scala | 1405 ++++++++++------- .../scala/org/scalacheck/Properties.scala | 87 +- .../org/scalacheck/ScalaCheckFramework.scala | 102 +- .../main/scala/org/scalacheck/Shrink.scala | 218 +-- .../src/main/scala/org/scalacheck/Test.scala | 270 ++-- .../org/scalacheck/commands/Commands.scala | 365 +++-- .../main/scala/org/scalacheck/rng/Seed.scala | 108 +- .../scalacheck/time/JavaTimeArbitrary.scala | 18 +- .../org/scalacheck/time/JavaTimeChoose.scala | 78 +- .../org/scalacheck/time/JavaTimeCogen.scala | 10 +- .../org/scalacheck/time/JavaTimeShrink.scala | 3 +- .../scala/org/scalacheck/util/Buildable.scala | 7 +- .../org/scalacheck/util/CmdLineParser.scala | 40 +- .../org/scalacheck/util/ConsoleReporter.scala | 27 +- .../scala/org/scalacheck/util/FreqMap.scala | 16 +- .../scala/org/scalacheck/util/Pretty.scala | 100 +- .../time/OrderingVersionSpecific.scala | 3 +- .../time/OrderingVersionSpecific.scala | 5 +- .../NoPropertyNestingSpecification.scala | 10 +- .../org/scalacheck/PropSpecification.scala | 71 +- .../org/scalacheck/ShrinkSpecification.scala | 21 +- .../org/scalacheck/examples/Examples.scala | 17 +- .../org/scalacheck/examples/MathSpec.scala | 7 +- .../util/BuildableSpecification.scala | 5 +- project/codegen.scala | 292 ++-- 51 files changed, 2851 insertions(+), 2501 deletions(-) diff --git a/bench/src/main/scala/org/scalacheck/bench/GenBench.scala b/bench/src/main/scala/org/scalacheck/bench/GenBench.scala index fe18ee34..c9043bf5 100644 --- a/bench/src/main/scala/org/scalacheck/bench/GenBench.scala +++ b/bench/src/main/scala/org/scalacheck/bench/GenBench.scala @@ -16,44 +16,31 @@ import org.scalacheck.Arbitrary.arbitrary import org.scalacheck.Gen import org.scalacheck.rng.Seed -/** - * Generator benchmarks - * - * Since generators may run very quickly (or very slowly) depending on - * the seed and size parameter used, we want to make sure these are - * held constant across runs. Otherwise, we might believe a particular - * change made a given generator faster (or slower) when in fact we - * just got lucky (or unlucky). - * - * We use `seedCount` to choose how many seeds we will benchmark with. - * For each seed, we run the given generator. So if `seedCount` is - * 100, the average time we get is the time to generate values for the - * 100 seeds we started with. - * - * The size parameter also plays a major role in how long generators - * take. ScalaCheck's default parameters start with 100. You can - * benchmark additional size parameters to see how changes to this - * parameter effect generator run time. - * - * Finally, a generator's `apply` method may fail to generate a value. - * This might allow a slow generator that fails 50% of the time to - * appear faster than other generators that don't fail. Since we - * expect all generators to be able to succeed, we benchmark using - * `pureApply`, which will retry up to 100 times before crashing. This - * way, there's no chance that a flaky generator gets an advantage - * during benchmarking. - * - * In theory, we should do as much work as possible outside the - * benchmark methods to avoid benchmarking construction time. However, - * since many generators are constructed inside of `flatMap` calls - * during generation we do want these constructors to also run as - * quickly as possible. For that reason, we mostly choose to assemble - * our generators inside the benchmark methods. - * - * Prefer to add new benchmarks instead of modifying existing ones. - * This will enable us to compare the results for a given benchmark - * over time. - */ +/** Generator benchmarks + * + * Since generators may run very quickly (or very slowly) depending on the seed and size parameter used, we want to + * make sure these are held constant across runs. Otherwise, we might believe a particular change made a given + * generator faster (or slower) when in fact we just got lucky (or unlucky). + * + * We use `seedCount` to choose how many seeds we will benchmark with. For each seed, we run the given generator. So if + * `seedCount` is 100, the average time we get is the time to generate values for the 100 seeds we started with. + * + * The size parameter also plays a major role in how long generators take. ScalaCheck's default parameters start with + * 100. You can benchmark additional size parameters to see how changes to this parameter effect generator run time. + * + * Finally, a generator's `apply` method may fail to generate a value. This might allow a slow generator that fails 50% + * of the time to appear faster than other generators that don't fail. Since we expect all generators to be able to + * succeed, we benchmark using `pureApply`, which will retry up to 100 times before crashing. This way, there's no + * chance that a flaky generator gets an advantage during benchmarking. + * + * In theory, we should do as much work as possible outside the benchmark methods to avoid benchmarking construction + * time. However, since many generators are constructed inside of `flatMap` calls during generation we do want these + * constructors to also run as quickly as possible. For that reason, we mostly choose to assemble our generators inside + * the benchmark methods. + * + * Prefer to add new benchmarks instead of modifying existing ones. This will enable us to compare the results for a + * given benchmark over time. + */ @State(Scope.Benchmark) @BenchmarkMode(Array(Mode.AverageTime)) @OutputTimeUnit(TimeUnit.MICROSECONDS) diff --git a/build.sbt b/build.sbt index a0453f09..e66c9ce4 100644 --- a/build.sbt +++ b/build.sbt @@ -9,10 +9,10 @@ ThisBuild / homepage := Some(url("http://www.scalacheck.org")) ThisBuild / licenses := Seq("BSD-3-Clause" -> url("https://opensource.org/licenses/BSD-3-Clause")) ThisBuild / developers := List( Developer( - id = "rickynils", - name = "Rickard Nilsson", + id = "rickynils", + name = "Rickard Nilsson", email = "rickynils@gmail.com", - url = url("https://github.com/rickynils") + url = url("https://github.com/rickynils") ) ) @@ -40,8 +40,8 @@ ThisBuild / githubWorkflowAddedJobs ++= Seq( "for d in */ ; do cd \"$d\" && sbt test:compile && cd ../ ; done"), name = Some("Build examples"))), javas = List(Java8), - scalas = List((ThisBuild / scalaVersion).value)), - + scalas = List((ThisBuild / scalaVersion).value) + ), WorkflowJob( "bench", "Bench", @@ -50,7 +50,9 @@ ThisBuild / githubWorkflowAddedJobs ++= Seq( List("bench/jmh:run -p genSize=0 -p seedCount=0 -bs 1 -wi 0 -i 1 -f 0 -t 1 -r 0 org.scalacheck.bench.GenBench"), name = Some("Build benchmark suite"))), javas = List(Java8), - scalas = List((ThisBuild / scalaVersion).value))) + scalas = List((ThisBuild / scalaVersion).value) + ) +) ThisBuild / tlBaseVersion := "1.17" ThisBuild / tlMimaPreviousVersions ++= Set( @@ -63,7 +65,7 @@ ThisBuild / tlMimaPreviousVersions ++= Set( "1.15.1", "1.15.2", "1.15.3", - "1.15.4", + "1.15.4" ) ThisBuild / tlVersionIntroduced := Map("3" -> "1.15.3") @@ -115,6 +117,6 @@ lazy val bench = project.in(file("bench")) .dependsOn(core.jvm) .settings( name := "scalacheck-bench", - fork := true, + fork := true ) .enablePlugins(NoPublishPlugin, JmhPlugin) diff --git a/core/js/src/main/scala/org/scalacheck/Platform.scala b/core/js/src/main/scala/org/scalacheck/Platform.scala index 80ed9441..ce214456 100644 --- a/core/js/src/main/scala/org/scalacheck/Platform.scala +++ b/core/js/src/main/scala/org/scalacheck/Platform.scala @@ -9,18 +9,18 @@ package org.scalacheck -import Test._ - import scala.annotation.nowarn import scala.scalajs.reflect.Reflect +import Test._ + private[scalacheck] object Platform { @nowarn("msg=is never used") def runWorkers( - params: Parameters, - workerFun: Int => Result, - stop: () => Unit + params: Parameters, + workerFun: Int => Result, + stop: () => Unit ): Result = { workerFun(0) } diff --git a/core/jvm/src/main/scala/org/scalacheck/Platform.scala b/core/jvm/src/main/scala/org/scalacheck/Platform.scala index a0242460..8f9aaaf0 100644 --- a/core/jvm/src/main/scala/org/scalacheck/Platform.scala +++ b/core/jvm/src/main/scala/org/scalacheck/Platform.scala @@ -18,9 +18,9 @@ private[scalacheck] object Platform { import util.FreqMap def runWorkers( - params: Parameters, - workerFun: Int => Result, - stop: () => Unit + params: Parameters, + workerFun: Int => Result, + stop: () => Unit ): Result = { import params._ @@ -28,30 +28,31 @@ private[scalacheck] object Platform { 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) + Result(st1, s1 + s2, d1 + d2, fm1 ++ fm2) else if (st2 != Passed && st2 != Exhausted) - Result(st2, s1+s2, d1+d2, fm1++fm2) + Result(st2, s1 + s2, d1 + d2, fm1 ++ fm2) else { - if (s1+s2 >= minSuccessfulTests && maxDiscardRatio*(s1+s2) >= (d1+d2)) - Result(Passed, s1+s2, d1+d2, fm1++fm2) + if (s1 + s2 >= minSuccessfulTests && maxDiscardRatio * (s1 + s2) >= (d1 + d2)) + Result(Passed, s1 + s2, d1 + d2, fm1 ++ fm2) else - Result(Exhausted, s1+s2, d1+d2, fm1++fm2) + Result(Exhausted, s1 + s2, d1 + d2, fm1 ++ fm2) } } - if(workers < 2) workerFun(0) + if (workers < 2) workerFun(0) else { import concurrent._ val tp = java.util.concurrent.Executors.newFixedThreadPool(workers) implicit val ec: ExecutionContextExecutor = ExecutionContext.fromExecutor(tp) try { - val fs = List.range(0,workers) map (idx => Future { - params.customClassLoader.foreach( - Thread.currentThread.setContextClassLoader(_) - ) - blocking { workerFun(idx) } - }) - val zeroRes = Result(Passed,0,0,FreqMap.empty[Set[Any]]) + val fs = List.range(0, workers) map (idx => + Future { + params.customClassLoader.foreach( + Thread.currentThread.setContextClassLoader(_) + ) + blocking { workerFun(idx) } + }) + val zeroRes = Result(Passed, 0, 0, FreqMap.empty[Set[Any]]) val res = if (fs.isEmpty) Future.successful(zeroRes) else Future.sequence(fs).map(_.foldLeft(zeroRes)(mergeResults)) @@ -65,7 +66,7 @@ private[scalacheck] object Platform { @nowarn("msg=is never used") def newInstance(name: String, loader: ClassLoader, paramTypes: Seq[Class[_]])(args: Seq[AnyRef]): AnyRef = - if(args.nonEmpty) ??? + if (args.nonEmpty) ??? else Class.forName(name, true, loader).getDeclaredConstructor().newInstance().asInstanceOf[AnyRef] def loadModule(name: String, loader: ClassLoader): AnyRef = diff --git a/core/jvm/src/test/scala/org/scalacheck/ArbitrarySpecification.scala b/core/jvm/src/test/scala/org/scalacheck/ArbitrarySpecification.scala index 4788652c..6249fced 100644 --- a/core/jvm/src/test/scala/org/scalacheck/ArbitrarySpecification.scala +++ b/core/jvm/src/test/scala/org/scalacheck/ArbitrarySpecification.scala @@ -26,7 +26,7 @@ object ArbitrarySpecification extends Properties("Arbitrary") { property("arbChar") = Prop.forAll { (c: Char) => - 0x0000 <= c && c <= 0xD7FF || 0xE000 <= c && c <= 0xFFFD + 0x0000 <= c && c <= 0xd7ff || 0xe000 <= c && c <= 0xfffd } property("arbString") = diff --git a/core/jvm/src/test/scala/org/scalacheck/ChooseSpecification.scala b/core/jvm/src/test/scala/org/scalacheck/ChooseSpecification.scala index 5420b82c..f3e28f4b 100644 --- a/core/jvm/src/test/scala/org/scalacheck/ChooseSpecification.scala +++ b/core/jvm/src/test/scala/org/scalacheck/ChooseSpecification.scala @@ -9,12 +9,14 @@ package org.scalacheck -import Gen._ - import java.time._ import java.time.temporal.ChronoUnit import java.util.Date -import scala.util.{Try, Success, Failure} +import scala.util.Failure +import scala.util.Success +import scala.util.Try + +import Gen._ object ChooseSpecification extends Properties("Choose") with time.OrderingVersionSpecific { @@ -58,9 +60,8 @@ object ChooseSpecification extends Properties("Choose") with time.OrderingVersio property("choose[ZonedDateTime]") = chooseProp[ZonedDateTime] - /** Generate a duration which is at least 1 second smaller than the max - * duration the type can support. We use this to avoid the incredibly - * unlikely event of overflowing in the handle-min-nanos-duration test. + /** Generate a duration which is at least 1 second smaller than the max duration the type can support. We use this to + * avoid the incredibly unlikely event of overflowing in the handle-min-nanos-duration test. */ lazy val genOneSecondLessThanMaxDuration: Gen[Duration] = Gen.choose(Duration.ofSeconds(Long.MinValue), Duration.ofSeconds(Long.MaxValue - 1L, 999999999L)) @@ -78,9 +79,8 @@ object ChooseSpecification extends Properties("Choose") with time.OrderingVersio checkChoose(min, max) } - /** Generate an Instant which is at least 1 second smaller than the max - * Instant the type can support. We use this to avoid the incredibly - * unlikely event of overflowing in the handle-min-nanos-instant test. + /** Generate an Instant which is at least 1 second smaller than the max Instant the type can support. We use this to + * avoid the incredibly unlikely event of overflowing in the handle-min-nanos-instant test. */ lazy val genOneSecondLessThanMaxInstant: Gen[Instant] = Gen.choose(Instant.MIN, Instant.MAX.minusSeconds(1L)) diff --git a/core/jvm/src/test/scala/org/scalacheck/CogenSpecification.scala b/core/jvm/src/test/scala/org/scalacheck/CogenSpecification.scala index 72e9c576..7446e727 100644 --- a/core/jvm/src/test/scala/org/scalacheck/CogenSpecification.scala +++ b/core/jvm/src/test/scala/org/scalacheck/CogenSpecification.scala @@ -14,15 +14,15 @@ import org.scalacheck.Gen.listOfN import org.scalacheck.GenSpecification.arbSeed import org.scalacheck.Prop.forAll import org.scalacheck.rng.Seed -import ScalaVersionSpecific._ +import java.time._ +import java.util.UUID import scala.collection.immutable.SortedMap import scala.collection.immutable.SortedSet -import scala.concurrent.duration.{Duration, FiniteDuration} +import scala.concurrent.duration.Duration +import scala.concurrent.duration.FiniteDuration import scala.util.Try - -import java.time._ -import java.util.UUID +import ScalaVersionSpecific._ object CogenSpecification extends Properties("Cogen") { @@ -82,7 +82,7 @@ object CogenSpecification extends Properties("Cogen") { implicit def arbFunction0[A: Arbitrary]: Arbitrary[() => A] = Arbitrary(arbitrary[A].map(() => _)) - implicit def arbCogen[A: Arbitrary : Cogen]: Arbitrary[Cogen[A]] = + implicit def arbCogen[A: Arbitrary: Cogen]: Arbitrary[Cogen[A]] = Arbitrary(arbitrary[A => A].map(Cogen[A].contramap(_))) // Cogens should follow these laws. @@ -94,19 +94,19 @@ object CogenSpecification extends Properties("Cogen") { In particular, if the space of the input is larger than the space of the seed (2^256) there is a possibility of legitimate collisions, but this is vanishingly small for the sample sizes we are using. */ - def uniqueness[A: Equal : Arbitrary : Cogen]: Prop = + def uniqueness[A: Equal: Arbitrary: Cogen]: Prop = forAll { (seed: Seed, as: List[A]) => as.map(Cogen[A].perturb(seed, _)).toSet.size == distinct(as).size } // A Cogen should always generate the same output for a given seed and input. - def consistency[A: Arbitrary : Cogen]: Prop = + def consistency[A: Arbitrary: Cogen]: Prop = forAll { (seed: Seed, a: A) => Cogen[A].perturb(seed, a) == Cogen[A].perturb(seed, a) } } - def cogenLaws[A: Equal : Arbitrary : Cogen]: Properties = + def cogenLaws[A: Equal: Arbitrary: Cogen]: Properties = new Properties("cogenLaws") { property("uniqueness") = CogenLaws.uniqueness[A] property("consistency") = CogenLaws.consistency[A] @@ -116,16 +116,18 @@ object CogenSpecification extends Properties("Cogen") { object ContravariantLaws { // Contramapping over a Cogen with the identity function should return the Cogen unchanged. - def identity[A: Equal : Arbitrary : Cogen]: Prop = + def identity[A: Equal: Arbitrary: Cogen]: Prop = forAll { (fa: Cogen[A]) => Equal[Cogen[A]].equal(fa.contramap(a => a), fa) } // Contramapping with f and g is the same as contramapping with the composition of f and g. - def composition[A, B, C](implicit eq: Equal[Cogen[C]], - arb1: Arbitrary[Cogen[A]], - arb2: Arbitrary[B => A], - arb3: Arbitrary[C => B]): Prop = + def composition[A, B, C](implicit + eq: Equal[Cogen[C]], + arb1: Arbitrary[Cogen[A]], + arb2: Arbitrary[B => A], + arb3: Arbitrary[C => B] + ): Prop = forAll { (fa: Cogen[A], f: B => A, g: C => B) => Equal[Cogen[C]].equal(fa.contramap(f).contramap(g), fa.contramap(f compose g)) } diff --git a/core/jvm/src/test/scala/org/scalacheck/GenSpecification.scala b/core/jvm/src/test/scala/org/scalacheck/GenSpecification.scala index 06a612e7..45a9dace 100644 --- a/core/jvm/src/test/scala/org/scalacheck/GenSpecification.scala +++ b/core/jvm/src/test/scala/org/scalacheck/GenSpecification.scala @@ -9,13 +9,15 @@ package org.scalacheck -import rng.Seed +import scala.util.Failure +import scala.util.Success +import scala.util.Try +import rng.Seed import Gen._ import Prop.{forAll, forAllNoShrink, someFailing, noneFailing, sizedProp, secure, propBoolean} import Arbitrary._ import Shrink._ -import scala.util.{Try, Success, Failure} object GenSpecification extends Properties("Gen") with GenSpecificationVersionSpecific { @@ -27,7 +29,8 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp def testCase[A](gen: Gen[A]): Prop = sizedProp { sz => val g = Gen.function1(gen)(Cogen[Int]) - if (sz > 0) forAll(g) { f => f(999); true } else Prop(true) + if (sz > 0) forAll(g) { f => f(999); true } + else Prop(true) } val p0 = testCase(arbitrary[Int].suchThat(_ != 0)) val p1 = testCase(arbitrary[String].suchThat(_ != "")) @@ -38,10 +41,9 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp } property("sequence") = - forAll(listOf(frequency((10,const(arbitrary[Int])),(1,const(fail)))))(l => - (someFailing(l) && (sequence[List[Int],Int](l) == fail)) || - (noneFailing(l) && forAll(sequence[List[Int],Int](l)) { _.length == l.length }) - ) + forAll(listOf(frequency((10, const(arbitrary[Int])), (1, const(fail)))))(l => + (someFailing(l) && (sequence[List[Int], Int](l) == fail)) || + (noneFailing(l) && forAll(sequence[List[Int], Int](l)) { _.length == l.length })) property("frequency 1") = { val g = frequency((10, const(0)), (5, const(1))) @@ -53,8 +55,8 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp forAll(g) { _ => true } } - property("frequency 3") = forAll(choose(1,100000)) { n => - forAll(frequency(List.fill(n)((1,const(0))): _*)) { _ == 0 } + property("frequency 3") = forAll(choose(1, 100000)) { n => + forAll(frequency(List.fill(n)((1, const(0))): _*)) { _ == 0 } } property("frequency 4") = @@ -76,7 +78,7 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp property("retryUntil requires valid parameters") = forAll((g: Gen[Int]) => Try(g.retryUntil(_ => false, 0)).isFailure) - property("const") = forAll { (x:Int, prms:Parameters, seed: Seed) => + property("const") = forAll { (x: Int, prms: Parameters, seed: Seed) => const(x)(prms, seed) == Some(x) } @@ -84,7 +86,7 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp fail(prms, seed) == None } - property("parameterized") = forAll((g: Gen[Int]) => parameterized(_=>g) == g) + property("parameterized") = forAll((g: Gen[Int]) => parameterized(_ => g) == g) property("sized") = forAll((g: Gen[Int]) => sized(_ => g) == g) @@ -92,7 +94,7 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp val g = Gen.resize(sz, Gen.posNum[Int]) forAllNoShrink(g) { n => if (sz > 0) n <= sz && n >= 0 - else n == 1 + else n == 1 } } @@ -100,28 +102,28 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp val g = Gen.resize(sz, Gen.negNum[Int]) forAllNoShrink(g) { n => if (sz > 0) n >= -sz && n <= 0 - else n == -1 + else n == -1 } } property("resize(sz, buildableOf)") = { val g = Gen.size.flatMap(sz => Gen.oneOf(-sz, sz)) - val gs = Gen.buildableOf[Seq[Int],Int](Arbitrary.arbitrary[Int]) + val gs = Gen.buildableOf[Seq[Int], Int](Arbitrary.arbitrary[Int]) Prop.forAll(g) { (sz: Int) => forAllNoShrink(Gen.resize(sz, gs)) { (l) => if (sz > 0) l.size <= sz && l.size >= 0 - else l.size == 0 + else l.size == 0 } } } property("resize(sz, nonEmptyBuilableOf)") = { val g = Gen.size.flatMap(sz => Gen.oneOf(-sz, sz)) - val gs = Gen.nonEmptyBuildableOf[Seq[Int],Int](Arbitrary.arbitrary[Int]) + val gs = Gen.nonEmptyBuildableOf[Seq[Int], Int](Arbitrary.arbitrary[Int]) Prop.forAll(g) { (sz: Int) => forAllNoShrink(Gen.resize(sz, gs)) { (l) => if (sz > 0) l.size <= sz && l.size >= 1 - else l.size == 1 + else l.size == 1 } } } @@ -131,7 +133,7 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp forAll(g, Gen.alphaChar) { (sz: Int, c: Char) => forAllNoShrink(Gen.resize(sz, Gen.stringOf(c))) { (s) => if (sz > 0) sz >= s.size && s.size >= 0 && s.forall(_ == c) - else s.size == 0 + else s.size == 0 } } } @@ -141,7 +143,7 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp forAll(g, Gen.alphaChar) { (sz: Int, c: Char) => forAllNoShrink(Gen.stringOfN(sz, c)) { (s) => if (sz > 0) s.size == sz && s.forall(_ == c) - else s.size == 0 + else s.size == 0 } } } @@ -151,7 +153,7 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp forAll(g, Gen.alphaChar) { (sz: Int, c: Char) => forAllNoShrink(Gen.resize(sz, Gen.nonEmptyStringOf(c))) { (s) => if (sz > 0) sz >= s.size && s.size >= 1 && s.forall(_ == c) - else s.size == 1 + else s.size == 1 } } } @@ -170,11 +172,11 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp } } - property("oneOf 2") = forAll { (n1:Int, n2:Int) => + property("oneOf 2") = forAll { (n1: Int, n2: Int) => forAll(oneOf(n1, n2)) { n => n == n1 || n == n2 } } - property("oneOf 2 gens") = forAll { (n1:Int, n2:Int) => + property("oneOf 2 gens") = forAll { (n1: Int, n2: Int) => val g1 = Gen.const(n1) val g2 = Gen.const(n2) forAll(oneOf(g1, g2)) { n => n == n1 || n == n2 } @@ -188,20 +190,20 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp property("nonEmptyListOf") = sizedProp { sz => forAll(nonEmptyListOf(arbitrary[Int])) { l => - l.length > 0 && l.length <= math.max(1,sz) + l.length > 0 && l.length <= math.max(1, sz) } } - property("listOfN") = forAll(choose(0,100)) { n => + property("listOfN") = forAll(choose(0, 100)) { n => forAll(listOfN(n, arbitrary[Int])) { _.length == n } } - property("setOfN") = forAll(choose(0,100)) { n => - forAll(containerOfN[Set,Int](n, arbitrary[Int])) { _.size <= n } + property("setOfN") = forAll(choose(0, 100)) { n => + forAll(containerOfN[Set, Int](n, arbitrary[Int])) { _.size <= n } } - property("mapOfN") = forAll(choose(0,100)) { n => - forAll(mapOfN(n, arbitrary[(Int,Int)])) { _.size <= n } + property("mapOfN") = forAll(choose(0, 100)) { n => + forAll(mapOfN(n, arbitrary[(Int, Int)])) { _.size <= n } } property("empty listOfN") = forAll(listOfN(0, arbitrary[Int])) { l => @@ -270,13 +272,14 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp } } - /** - * Expect: - * 25% 1, 2, 3 - * 25% 1, 2, 4 - * 25% 1, 4, 3 - * 25% 4, 2, 3 - */ + /** Expect: + * {{{ + * 25% 1, 2, 3 + * 25% 1, 2, 4 + * 25% 1, 4, 3 + * 25% 4, 2, 3 + * }}} + */ property("distributed pick") = { val lst = (1 to 4).toIterable val n = 3 @@ -325,15 +328,15 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp property("asciiPrintableChar") = forAll(asciiPrintableChar) { ch => val charType = Character.getType(ch) Character.isLetterOrDigit(ch) || Character.isSpaceChar(ch) || - charType == Character.CONNECTOR_PUNCTUATION || charType == Character.DASH_PUNCTUATION || - charType == Character.START_PUNCTUATION || charType == Character.END_PUNCTUATION || - charType == Character.INITIAL_QUOTE_PUNCTUATION || charType == Character.FINAL_QUOTE_PUNCTUATION || - charType == Character.OTHER_PUNCTUATION || - charType == Character.MATH_SYMBOL || charType == Character.CURRENCY_SYMBOL || - charType == Character.MODIFIER_SYMBOL || charType == Character.OTHER_SYMBOL + charType == Character.CONNECTOR_PUNCTUATION || charType == Character.DASH_PUNCTUATION || + charType == Character.START_PUNCTUATION || charType == Character.END_PUNCTUATION || + charType == Character.INITIAL_QUOTE_PUNCTUATION || charType == Character.FINAL_QUOTE_PUNCTUATION || + charType == Character.OTHER_PUNCTUATION || + charType == Character.MATH_SYMBOL || charType == Character.CURRENCY_SYMBOL || + charType == Character.MODIFIER_SYMBOL || charType == Character.OTHER_SYMBOL } - property("hexChar") = forAll(hexChar){ ch => + property("hexChar") = forAll(hexChar) { ch => val l: Long = java.lang.Long.parseLong(ch.toString, 16) l < 16 && l >= 0 } @@ -371,12 +374,12 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp s.length >= 0 && s.forall { ch => val charType = Character.getType(ch) Character.isLetterOrDigit(ch) || Character.isSpaceChar(ch) || - charType == Character.CONNECTOR_PUNCTUATION || charType == Character.DASH_PUNCTUATION || - charType == Character.START_PUNCTUATION || charType == Character.END_PUNCTUATION || - charType == Character.INITIAL_QUOTE_PUNCTUATION || charType == Character.FINAL_QUOTE_PUNCTUATION || - charType == Character.OTHER_PUNCTUATION || - charType == Character.MATH_SYMBOL || charType == Character.CURRENCY_SYMBOL || - charType == Character.MODIFIER_SYMBOL || charType == Character.OTHER_SYMBOL + charType == Character.CONNECTOR_PUNCTUATION || charType == Character.DASH_PUNCTUATION || + charType == Character.START_PUNCTUATION || charType == Character.END_PUNCTUATION || + charType == Character.INITIAL_QUOTE_PUNCTUATION || charType == Character.FINAL_QUOTE_PUNCTUATION || + charType == Character.OTHER_PUNCTUATION || + charType == Character.MATH_SYMBOL || charType == Character.CURRENCY_SYMBOL || + charType == Character.MODIFIER_SYMBOL || charType == Character.OTHER_SYMBOL } } @@ -386,8 +389,7 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp case Success(bi) => bi >= BigInt(0L) case _ => false } - } - else { + } else { true } } @@ -425,14 +427,13 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp } property("tailRecM") = forAll { (init: Int, seeds: List[Seed]) => - val g: ((Int, Int)) => Gen[Either[(Int, Int), Int]] = - { - case (c, x) if c <= 0 => - Gen.const(Right(x)) - case (c, x) => - val g = Gen.choose(Int.MinValue, x) - g.map { i => Left(((c - 1), i)) } - } + val g: ((Int, Int)) => Gen[Either[(Int, Int), Int]] = { + case (c, x) if c <= 0 => + Gen.const(Right(x)) + case (c, x) => + val g = Gen.choose(Int.MinValue, x) + g.map { i => Left(((c - 1), i)) } + } val g1 = Gen.tailRecM((10, init))(g) def g2(x: (Int, Int)): Gen[Int] = g(x).flatMap { @@ -442,7 +443,6 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp val finalG2 = g2((10, init)) - val params = Gen.Parameters.default seeds.forall { seed => @@ -475,15 +475,21 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp property("uuid version 4") = forAll(uuid) { _.version == 4 } property("uuid unique") = forAll(uuid, uuid) { - case (u1,u2) => u1 != u2 + case (u1, u2) => u1 != u2 } property("zip9") = forAll(zip( - const(1), const(2), const(3), const(4), - const(5), const(6), const(7), const(8), + const(1), + const(2), + const(3), + const(4), + const(5), + const(6), + const(7), + const(8), const(9) )) { - _ == ((1,2,3,4,5,6,7,8,9)) + _ == ((1, 2, 3, 4, 5, 6, 7, 8, 9)) } //// See https://github.com/typelevel/scalacheck/issues/79 @@ -512,9 +518,28 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp //// case class Full22( - i1:Int,i2:Int,i3:Int,i4:Int,i5:Int,i6:Int,i7:Int,i8:Int,i9:Int,i10:Int, - i11:Int,i12:Int,i13:Int,i14:Int,i15:Int,i16:Int,i17:Int,i18:Int,i19:Int,i20:Int, - i21:Int,i22:Int + i1: Int, + i2: Int, + i3: Int, + i4: Int, + i5: Int, + i6: Int, + i7: Int, + i8: Int, + i9: Int, + i10: Int, + i11: Int, + i12: Int, + i13: Int, + i14: Int, + i15: Int, + i16: Int, + i17: Int, + i18: Int, + i19: Int, + i20: Int, + i21: Int, + i22: Int ) property("22 field case class works") = @@ -551,7 +576,7 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp var sum = 0d var seed = rng.Seed(n.toLong) while (i < n) { - val (d,s1) = seed.double + val (d, s1) = seed.double sum += d i += 1 seed = s1 @@ -567,7 +592,7 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp var sum = 0d var seed = rng.Seed(n.toLong) while (i < n) { - val (l,s1) = seed.long + val (l, s1) = seed.long sum += math.abs(l).toDouble * scale i += 1 seed = s1 @@ -607,22 +632,18 @@ object GenSpecification extends Properties("Gen") with GenSpecificationVersionSp b <- Gen.finiteDuration } yield if (a < b) (a, b) else (b, a) - Prop.forAll(g){ case (low, high) => - Prop.forAll(Gen.choose(low, high)){ d => + Prop.forAll(g) { case (low, high) => + Prop.forAll(Gen.choose(low, high)) { d => d >= low && d <= high } } } - /** - * Ensure that the given generator runs deterministically with the - * same initialSeed parameter or the same seed. - * - * This test should be run with a generator that can produce - * multiple values, and where the odds of 30 trials coming back with - * the same result is low enough that the test won't produce many - * false positives. - */ + /** Ensure that the given generator runs deterministically with the same initialSeed parameter or the same seed. + * + * This test should be run with a generator that can produce multiple values, and where the odds of 30 trials coming + * back with the same result is low enough that the test won't produce many false positives. + */ def testDeterministicGen[A](g: Gen[A]): Prop = { val params0 = Gen.Parameters.default val params1 = params0.withInitialSeed(1248163264L) diff --git a/core/jvm/src/test/scala/org/scalacheck/PropertyFilterSpecification.scala b/core/jvm/src/test/scala/org/scalacheck/PropertyFilterSpecification.scala index 5cdb1ada..091c72d4 100644 --- a/core/jvm/src/test/scala/org/scalacheck/PropertyFilterSpecification.scala +++ b/core/jvm/src/test/scala/org/scalacheck/PropertyFilterSpecification.scala @@ -26,17 +26,19 @@ object PropertyFilterSpecification extends Properties("PropertyFilter") { val nl = System.lineSeparator - private def diff(filter: Option[String], actual: collection.Seq[String], - expected: collection.Seq[String]): String = { + private def diff(filter: Option[String], actual: collection.Seq[String], expected: collection.Seq[String]): String = { s"filter: ${filter.getOrElse("not supplied")}" + - s"${nl}expected values:$nl" + - s"\t${expected.mkString(s"$nl\t")}" + - s"${nl}actual values:$nl" + - s"\t${actual.mkString(s"$nl\t")}" + s"${nl}expected values:$nl" + + s"\t${expected.mkString(s"$nl\t")}" + + s"${nl}actual values:$nl" + + s"\t${actual.mkString(s"$nl\t")}" } - private def prop(filter: Option[String], actualNames: collection.Seq[String], - expectedNames: collection.Seq[String]): Prop = { + private def prop( + filter: Option[String], + actualNames: collection.Seq[String], + expectedNames: collection.Seq[String] + ): Prop = { def lengthProp = actualNames.length == expectedNames.length def props = actualNames.forall(expectedNames.contains) @@ -50,39 +52,37 @@ object PropertyFilterSpecification extends Properties("PropertyFilter") { Gen.oneOf( "PropertyFilterSample.*numbers", "PropertyFilterSample.*alpha"))) { pf => - - val testParams = - Test.Parameters.default. - withPropFilter(pf) - - val props = - Test.checkProperties( - testParams, - PropertyFilterSampleSpecification - ) - - val propNames = props.map(_._1) - - if (pf.exists(_.contains("*numbers"))) { - val expected = - Seq( - "PropertyFilterSample.positive numbers", - "PropertyFilterSample.negative numbers" - ) - - prop(pf, propNames, expected) - } else if (pf.exists(_.contains("*alpha"))) { - val expected = Seq("PropertyFilterSample.lowercase alpha characters") - - prop(pf, propNames, expected) - } else { //no filter - val expected = Seq( - "PropertyFilterSample.positive numbers", - "PropertyFilterSample.negative numbers", - "PropertyFilterSample.lowercase alpha characters" - ) - - prop(pf, propNames, expected) - } - } + val testParams = + Test.Parameters.default.withPropFilter(pf) + + val props = + Test.checkProperties( + testParams, + PropertyFilterSampleSpecification + ) + + val propNames = props.map(_._1) + + if (pf.exists(_.contains("*numbers"))) { + val expected = + Seq( + "PropertyFilterSample.positive numbers", + "PropertyFilterSample.negative numbers" + ) + + prop(pf, propNames, expected) + } else if (pf.exists(_.contains("*alpha"))) { + val expected = Seq("PropertyFilterSample.lowercase alpha characters") + + prop(pf, propNames, expected) + } else { // no filter + val expected = Seq( + "PropertyFilterSample.positive numbers", + "PropertyFilterSample.negative numbers", + "PropertyFilterSample.lowercase alpha characters" + ) + + prop(pf, propNames, expected) + } + } } diff --git a/core/jvm/src/test/scala/org/scalacheck/SerializabilitySpecification.scala b/core/jvm/src/test/scala/org/scalacheck/SerializabilitySpecification.scala index 36454d6b..9f7bf080 100644 --- a/core/jvm/src/test/scala/org/scalacheck/SerializabilitySpecification.scala +++ b/core/jvm/src/test/scala/org/scalacheck/SerializabilitySpecification.scala @@ -10,6 +10,7 @@ package org.scalacheck import org.apache.commons.lang3.SerializationUtils + import java.io.Serializable import util.SerializableCanBuildFroms._ @@ -58,9 +59,31 @@ object SerializabilitySpecification extends Properties("Serializability") { serializableArbitrary[Boolean]("Boolean") serializableArbitrary[Int => Int]("Int => Int") serializableArbitrary[List[Int]]("List[Int]") - serializableArbitrary[(String,Int)]("(String,Int)") - serializableArbitrary[(Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int)]("Tuple22[Int]") - serializableArbitrary[List[(String,Int)]]("List[(String,Int)]") + serializableArbitrary[(String, Int)]("(String,Int)") + serializableArbitrary[( + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int)]("Tuple22[Int]") + serializableArbitrary[List[(String, Int)]]("List[(String,Int)]") serializableGen("Gen.identifier", Gen.identifier) serializableGen("Gen.oneOf", Gen.oneOf(true, false)) @@ -74,9 +97,31 @@ object SerializabilitySpecification extends Properties("Serializability") { serializableCogen[Boolean]("Boolean") serializableCogen[Int => Int]("Int => Int") serializableCogen[List[Int]]("List[Int]") - serializableCogen[(String,Int)]("(String,Int)") - serializableCogen[(Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int)]("Tuple22[Int]") - serializableCogen[List[(String,Int)]]("List[(String,Int)]") + serializableCogen[(String, Int)]("(String,Int)") + serializableCogen[( + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int)]("Tuple22[Int]") + serializableCogen[List[(String, Int)]]("List[(String,Int)]") serializableShrink[String]("String") serializableShrink[Int]("Int") @@ -84,9 +129,31 @@ object SerializabilitySpecification extends Properties("Serializability") { serializableShrink[Boolean]("Boolean") serializableShrink[Int => Int]("Int => Int") serializableShrink[List[Int]]("List[Int]") - serializableShrink[(String,Int)]("(String,Int)") - serializableShrink[(Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int,Int)]("Tuple22[Int])") - serializableShrink[List[(String,Int)]]("List[(String,Int)]") + serializableShrink[(String, Int)]("(String,Int)") + serializableShrink[( + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int, + Int)]("Tuple22[Int])") + serializableShrink[List[(String, Int)]]("List[(String,Int)]") property("Seed(1L)") = { serializable(rng.Seed(1L)) diff --git a/core/jvm/src/test/scala/org/scalacheck/ShrinkSpecificationJVM.scala b/core/jvm/src/test/scala/org/scalacheck/ShrinkSpecificationJVM.scala index 4c667227..e8449cde 100644 --- a/core/jvm/src/test/scala/org/scalacheck/ShrinkSpecificationJVM.scala +++ b/core/jvm/src/test/scala/org/scalacheck/ShrinkSpecificationJVM.scala @@ -13,8 +13,8 @@ import Prop.{forAll, propBoolean} import Shrink.shrink import ShrinkSpecification.shrinkClosure -/** - * @todo should work not only JVM but also Scala.js +/** @todo + * should work not only JVM but also Scala.js */ object ShrinkSpecificationJVM extends Properties("Shrink JVM") { diff --git a/core/jvm/src/test/scala/org/scalacheck/TestSpecification.scala b/core/jvm/src/test/scala/org/scalacheck/TestSpecification.scala index bf22d684..77f55b74 100644 --- a/core/jvm/src/test/scala/org/scalacheck/TestSpecification.scala +++ b/core/jvm/src/test/scala/org/scalacheck/TestSpecification.scala @@ -18,21 +18,20 @@ object TestSpecification extends Properties("Test") { val proved: Prop = 1 + 1 == 2 - val passing = forAll( (n: Int) => n == n ) + val passing = forAll((n: Int) => n == n) - val failing = forAll( (_: Int) => false ) + val failing = forAll((_: Int) => false) - val exhausted = forAll( (n: Int) => - (n > 0 && n < 0) ==> (n == n) - ) + val exhausted = forAll((n: Int) => + (n > 0 && n < 0) ==> (n == n)) - val shrunk = forAll( (_: (Int,Int,Int)) => false ) + val shrunk = forAll((_: (Int, Int, Int)) => false) - val propException = forAll { (_:Int) => throw new java.lang.Exception } + val propException = forAll { (_: Int) => throw new java.lang.Exception } - val undefinedInt = for{ + val undefinedInt = for { n <- arbitrary[Int] - } yield n/0 + } yield n / 0 val genException = forAll(undefinedInt)((_: Int) => true) @@ -41,7 +40,7 @@ object TestSpecification extends Properties("Test") { val cb = new Test.TestCallback { override def onPropEval(n: String, threadIdx: Int, s: Int, d: Int) = { - res = res && threadIdx >= 0 && threadIdx <= (prms.workers-1) + res = res && threadIdx >= 0 && threadIdx <= (prms.workers - 1) } } @@ -55,23 +54,23 @@ object TestSpecification extends Properties("Test") { forAll { (prms: Test.Parameters, p: Prop) => val r = Test.check(prms, p) s"${r.status}, s=${r.succeeded}, d=${r.discarded}, " + - s"minSuccessful=${prms.minSuccessfulTests}, " + - s"maxDiscardRatio=${prms.maxDiscardRatio}, " + - s"actualDiscardRatio=${r.discarded.toFloat / r.succeeded}, " + - s"workers=${prms.workers}" |: f(prms,r) + s"minSuccessful=${prms.minSuccessfulTests}, " + + s"maxDiscardRatio=${prms.maxDiscardRatio}, " + + s"actualDiscardRatio=${r.discarded.toFloat / r.succeeded}, " + + s"workers=${prms.workers}" |: f(prms, r) } property("stopCondition") = resultInvariant { (prms, r) => r.status match { case Passed => (r.succeeded >= prms.minSuccessfulTests) && - (r.discarded <= prms.maxDiscardRatio*r.succeeded) + (r.discarded <= prms.maxDiscardRatio * r.succeeded) case Exhausted => (r.discarded > r.succeeded * prms.maxDiscardRatio) && (r.discarded >= prms.minSuccessfulTests * prms.maxDiscardRatio) case _ => (r.succeeded < prms.minSuccessfulTests) && - (r.discarded <= prms.maxDiscardRatio*r.succeeded) + (r.discarded <= prms.maxDiscardRatio * r.succeeded) } } @@ -82,7 +81,7 @@ object TestSpecification extends Properties("Test") { property("propFailing") = forAll { (prms: Test.Parameters) => Test.check(prms, failing).status match { - case _:Failed => true + case _: Failed => true case _ => false } } @@ -93,7 +92,7 @@ object TestSpecification extends Properties("Test") { property("propProved") = forAll { (prms: Test.Parameters) => Test.check(prms, proved).status match { - case _:Test.Proved => true + case _: Test.Proved => true case _ => false } } @@ -104,21 +103,21 @@ object TestSpecification extends Properties("Test") { property("propPropException") = forAll { (prms: Test.Parameters) => Test.check(prms, propException).status match { - case _:PropException => true + case _: PropException => true case _ => false } } property("propGenException") = forAll { (prms: Test.Parameters) => Test.check(prms, genException).status match { - case x:PropException => true :| x.toString + case x: PropException => true :| x.toString case x => false :| x.toString } } property("propShrunk") = forAll { (prms: Test.Parameters) => Test.check(prms, shrunk).status match { - case Failed(Arg(_,(x:Int,y:Int,z:Int),_,_,_,_)::Nil,_) => + case Failed(Arg(_, (x: Int, y: Int, z: Int), _, _, _, _) :: Nil, _) => x == 0 && y == 0 && z == 0 case _ => false } diff --git a/core/jvm/src/test/scala/org/scalacheck/commands/CommandsShrinkSpecification.scala b/core/jvm/src/test/scala/org/scalacheck/commands/CommandsShrinkSpecification.scala index 460e6cf3..910e1236 100644 --- a/core/jvm/src/test/scala/org/scalacheck/commands/CommandsShrinkSpecification.scala +++ b/core/jvm/src/test/scala/org/scalacheck/commands/CommandsShrinkSpecification.scala @@ -9,11 +9,17 @@ package org.scalacheck.commands +import org.scalacheck.Arbitrary +import org.scalacheck.Gen +import org.scalacheck.Prop import org.scalacheck.Prop.forAll +import org.scalacheck.Properties +import org.scalacheck.Shrink import org.scalacheck.rng.Seed -import org.scalacheck.{Arbitrary, Gen, Prop, Properties, Shrink} + import scala.reflect.ClassTag -import scala.util.{Success, Try} +import scala.util.Success +import scala.util.Try object CommandsShrinkSpecification extends Properties("Commands Shrinking") { @@ -134,9 +140,9 @@ object CommandsShrinkSpecification extends Properties("Commands Shrinking") { ).suchThat(_.capacity >= 0) def canCreateNewSut( - newState: State, - initSuts: Traversable[State], - runningSuts: Traversable[Sut] + newState: State, + initSuts: Traversable[State], + runningSuts: Traversable[Sut] ): Boolean = true diff --git a/core/jvm/src/test/scala/org/scalacheck/commands/CommandsSpecification.scala b/core/jvm/src/test/scala/org/scalacheck/commands/CommandsSpecification.scala index 711c6002..0bd7309d 100644 --- a/core/jvm/src/test/scala/org/scalacheck/commands/CommandsSpecification.scala +++ b/core/jvm/src/test/scala/org/scalacheck/commands/CommandsSpecification.scala @@ -28,8 +28,8 @@ object CommandsSpecification extends Properties("Commands") { val lock = new java.util.concurrent.locks.ReentrantLock def inc = { lock.lock; n += 1; lock.unlock; n } def dec = { lock.lock; n -= 1; lock.unlock; n } - //def inc = { n += 1; n } - //def dec = { n -= 1; n } + // def inc = { n += 1; n } + // def dec = { n -= 1; n } def get = n } @@ -38,8 +38,7 @@ object CommandsSpecification extends Properties("Commands") { override def shrinkState: Shrink[Int] = implicitly - def canCreateNewSut(newState: State, initSuts: Traversable[State], - runningSuts: Traversable[Sut]) = true + def canCreateNewSut(newState: State, initSuts: Traversable[State], runningSuts: Traversable[Sut]) = true def newSut(state: State): Sut = Counter(state) @@ -47,7 +46,7 @@ object CommandsSpecification extends Properties("Commands") { def initialPreCondition(state: State) = true - val genInitialState = Gen.choose(0,100) + val genInitialState = Gen.choose(0, 100) def genCommand(state: State): Gen[Command] = Gen.oneOf(Get, Inc, Dec) @@ -63,17 +62,17 @@ object CommandsSpecification extends Properties("Commands") { case object Inc extends SuccessCommand { type Result = Int def run(sut: Sut) = sut.inc - def nextState(state: State) = state+1 + def nextState(state: State) = state + 1 def preCondition(state: State) = true - def postCondition(state: State, result: Result) = result == (state+1) + def postCondition(state: State, result: Result) = result == (state + 1) } case object Dec extends SuccessCommand { type Result = Int def run(sut: Sut) = sut.dec - def nextState(state: State) = state-1 + def nextState(state: State) = state - 1 def preCondition(state: State) = true - def postCondition(state: State, result: Result) = result == (state-1) + def postCondition(state: State, result: Result) = result == (state - 1) } } diff --git a/core/jvm/src/test/scala/org/scalacheck/examples/IntMapSpec.scala b/core/jvm/src/test/scala/org/scalacheck/examples/IntMapSpec.scala index 267792ad..86d6c281 100644 --- a/core/jvm/src/test/scala/org/scalacheck/examples/IntMapSpec.scala +++ b/core/jvm/src/test/scala/org/scalacheck/examples/IntMapSpec.scala @@ -9,14 +9,17 @@ package org.scalacheck +import org.scalacheck.Prop.AnyOperators +import org.scalacheck.Prop.forAll + import java.util.HashMap import scala.collection.JavaConverters._ import scala.collection.immutable.IntMap -import org.scalacheck.Prop.{forAll, AnyOperators} object IntMapSpec extends org.scalacheck.Properties("IntMap") { + /** Compare a HashMap and an IntMap for equality */ - private def eqMaps(hm: HashMap[Int,Any], im: IntMap[Any]) = { + private def eqMaps(hm: HashMap[Int, Any], im: IntMap[Any]) = { im.keys.forall(hm.containsKey) && hm.keySet.containsAll(im.keys.asJavaCollection) && im.keys.forall(k => im(k) == hm.asScala(k)) @@ -24,10 +27,10 @@ object IntMapSpec extends org.scalacheck.Properties("IntMap") { /** Create an IntMap and a HashMap with the same contents */ private def createMaps(l: List[Int]) = { - val mappings = for(n <- l) yield (n, new Object) + val mappings = for (n <- l) yield (n, new Object) val im = IntMap(mappings: _*) val hm = new HashMap[Int, Any] - for((n,x) <- mappings) hm.put(n,x) + for ((n, x) <- mappings) hm.put(n, x) (hm, im) } diff --git a/core/jvm/src/test/scala/org/scalacheck/examples/StringUtils.scala b/core/jvm/src/test/scala/org/scalacheck/examples/StringUtils.scala index b0a5002f..0ac49ad2 100644 --- a/core/jvm/src/test/scala/org/scalacheck/examples/StringUtils.scala +++ b/core/jvm/src/test/scala/org/scalacheck/examples/StringUtils.scala @@ -15,13 +15,13 @@ object StringUtils extends Properties("Examples.StringUtils") { private object StringUtils { def truncate(s: String, n: Int) = { - if(s.length <= n) s + if (s.length <= n) s else s.substring(0, n) ++ "..." } def truncate2(s: String, n: Int) = { - if(n < 0) "" - else if(s.length <= n) s + if (n < 0) "" + else if (s.length <= n) s else s.substring(0, n) ++ "..." } @@ -30,7 +30,7 @@ object StringUtils extends Properties("Examples.StringUtils") { val st = new java.util.StringTokenizer(s, delimStr) val tokens = Array.ofDim[String](st.countTokens) var i = 0; - while(st.hasMoreTokens) { + while (st.hasMoreTokens) { tokens(i) = st.nextToken() i += 1; } @@ -44,11 +44,11 @@ object StringUtils extends Properties("Examples.StringUtils") { property("truncate") = Prop.forAll { (s: String, n: Int) => lazy val t = StringUtils.truncate(s, n) - if(n < 0) + if (n < 0) Prop.throws(classOf[StringIndexOutOfBoundsException]) { t } - else + else (s.length <= n && t == s) || - (s.length > n && t == s.take(n)+"...") + (s.length > n && t == s.take(n) + "...") } property("truncate.precond") = Prop.forAll { (s: String, n: Int) => @@ -56,29 +56,29 @@ object StringUtils extends Properties("Examples.StringUtils") { (n >= 0) ==> { val t = StringUtils.truncate(s, n) (s.length <= n && t == s) || - (s.length > n && t == s.take(n)+"...") + (s.length > n && t == s.take(n) + "...") } } property("truncate2") = Prop.forAll { (s: String, n: Int) => val t = StringUtils.truncate2(s, n) - if(n < 0) + if (n < 0) t == "" else (s.length <= n && t == s) || - (s.length > n && t == s.take(n)+"...") + (s.length > n && t == s.take(n) + "...") } - //property("tokenize") = { + // property("tokenize") = { // import Prop.AnyOperators // Prop.forAll(Gen.listOf(Gen.alphaStr), Gen.numChar) { (ts, d) => // val str = ts.mkString(d.toString) // StringUtils.tokenize(str, d).toList ?= ts // } - //} + // } property("contains") = Prop.forAll { (s1: String, s2: String, s3: String) => - StringUtils.contains(s1+s2+s3, s2) + StringUtils.contains(s1 + s2 + s3, s2) } } diff --git a/core/jvm/src/test/scala/org/scalacheck/rng/SeedSpecification.scala b/core/jvm/src/test/scala/org/scalacheck/rng/SeedSpecification.scala index 6a3f9451..a26b95cb 100644 --- a/core/jvm/src/test/scala/org/scalacheck/rng/SeedSpecification.scala +++ b/core/jvm/src/test/scala/org/scalacheck/rng/SeedSpecification.scala @@ -10,9 +10,10 @@ package org.scalacheck package rng +import scala.util.Try + import Prop.forAll import Arbitrary.arbitrary -import scala.util.Try object SeedSpecification extends Properties("Seed") { @@ -42,7 +43,8 @@ object SeedSpecification extends Properties("Seed") { val base = b.value def countZeros(s0: Seed, i: Int, seen0: Int): Int = - if (i <= 0) seen0 else { + if (i <= 0) seen0 + else { val (x, s1) = s0.long val n = x % base val seen = if (n == 0) seen0 + 1 else seen0 diff --git a/core/jvm/src/test/scala/org/scalacheck/time/ShrinkSpecification.scala b/core/jvm/src/test/scala/org/scalacheck/time/ShrinkSpecification.scala index c773f09d..fe362cb0 100644 --- a/core/jvm/src/test/scala/org/scalacheck/time/ShrinkSpecification.scala +++ b/core/jvm/src/test/scala/org/scalacheck/time/ShrinkSpecification.scala @@ -9,12 +9,13 @@ package org.scalacheck.time -import java.time._ import org.scalacheck.Prop._ import org.scalacheck.Shrink._ import org.scalacheck._ -object ShrinkSpecification extends Properties ("time.Shrink"){ +import java.time._ + +object ShrinkSpecification extends Properties("time.Shrink") { property("shrink[Duration]") = forAll { (n: Duration) => !shrink(n).contains(n) } diff --git a/core/native/src/main/scala/org/scalacheck/Platform.scala b/core/native/src/main/scala/org/scalacheck/Platform.scala index 0b49dcfa..93263013 100644 --- a/core/native/src/main/scala/org/scalacheck/Platform.scala +++ b/core/native/src/main/scala/org/scalacheck/Platform.scala @@ -9,18 +9,18 @@ package org.scalacheck -import Test._ - import scala.annotation.nowarn import scala.scalanative.reflect.Reflect +import Test._ + private[scalacheck] object Platform { @nowarn("msg=is never used") def runWorkers( - params: Parameters, - workerFun: Int => Result, - stop: () => Unit + params: Parameters, + workerFun: Int => Result, + stop: () => Unit ): Result = { workerFun(0) } diff --git a/core/shared/src/main/scala-2.12-/org/scalacheck/ScalaVersionSpecific.scala b/core/shared/src/main/scala-2.12-/org/scalacheck/ScalaVersionSpecific.scala index bd59d048..7cdcb298 100644 --- a/core/shared/src/main/scala-2.12-/org/scalacheck/ScalaVersionSpecific.scala +++ b/core/shared/src/main/scala-2.12-/org/scalacheck/ScalaVersionSpecific.scala @@ -17,7 +17,7 @@ private[scalacheck] object ScalaVersionSpecific { def toLazyList[T](i: TraversableOnce[T]) = i.toStream type LazyList[+A] = Stream[A] - val LazyList = Stream + val LazyList = Stream implicit class StreamExt[+A](val s: Stream[A]) extends AnyVal { def lazyAppendedAll[B >: A](rest: => TraversableOnce[B]): Stream[B] = s.append(rest) diff --git a/core/shared/src/main/scala-2.12-/org/scalacheck/util/BuildableVersionSpecific.scala b/core/shared/src/main/scala-2.12-/org/scalacheck/util/BuildableVersionSpecific.scala index ad16c272..43ffcb9a 100644 --- a/core/shared/src/main/scala-2.12-/org/scalacheck/util/BuildableVersionSpecific.scala +++ b/core/shared/src/main/scala-2.12-/org/scalacheck/util/BuildableVersionSpecific.scala @@ -16,8 +16,8 @@ import generic.CanBuildFrom import scala.collection.mutable.Builder private[util] trait BuildableVersionSpecific { - implicit def buildableCanBuildFrom[T,F,C](implicit c: CanBuildFrom[F,T,C]): Buildable[T,C] = - new Buildable[T,C] { + implicit def buildableCanBuildFrom[T, F, C](implicit c: CanBuildFrom[F, T, C]): Buildable[T, C] = + new Buildable[T, C] { def builder = c.apply } } @@ -32,10 +32,8 @@ private[util] class ArrayListBuilder[T] extends Builder[T, ArrayList[T]] { def result(): ArrayList[T] = al } -/** - * CanBuildFrom instances implementing Serializable, so that the objects capturing those can be - * serializable too. - */ +/** CanBuildFrom instances implementing Serializable, so that the objects capturing those can be serializable too. + */ object SerializableCanBuildFroms { implicit def listCanBuildFrom[T]: CanBuildFrom[List[T], T, List[T]] = new CanBuildFrom[List[T], T, List[T]] with Serializable { diff --git a/core/shared/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala b/core/shared/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala index e3c96d8b..ab7bc499 100644 --- a/core/shared/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala +++ b/core/shared/src/main/scala-2.13+/org/scalacheck/ScalaVersionSpecific.scala @@ -40,6 +40,7 @@ private[scalacheck] trait CogenVersionSpecific { } private[scalacheck] trait ShrinkVersionSpecific { + /** Forward to Shrink instance factory */ def withLazyList[T](s: T => LazyList[T]): Shrink[T] = Shrink(s.andThen(_.toStream)) } diff --git a/core/shared/src/main/scala-2.13+/org/scalacheck/util/BuildableVersionSpecific.scala b/core/shared/src/main/scala-2.13+/org/scalacheck/util/BuildableVersionSpecific.scala index f70d7ce8..1e95b7e5 100644 --- a/core/shared/src/main/scala-2.13+/org/scalacheck/util/BuildableVersionSpecific.scala +++ b/core/shared/src/main/scala-2.13+/org/scalacheck/util/BuildableVersionSpecific.scala @@ -10,14 +10,12 @@ package org.scalacheck.util import java.util.ArrayList - -import collection.{Map => _, _} import scala.collection.mutable.Builder - +import scala.collection.{Map => _, _} private[util] trait BuildableVersionSpecific { - implicit def buildableFactory[T,C](implicit f: Factory[T,C]): Buildable[T,C] = - new Buildable[T,C] { + implicit def buildableFactory[T, C](implicit f: Factory[T, C]): Buildable[T, C] = + new Buildable[T, C] { def builder = f.newBuilder } } @@ -32,10 +30,8 @@ private[util] class ArrayListBuilder[T] extends Builder[T, ArrayList[T]] { def result(): ArrayList[T] = al } -/** - * Factory instances implementing Serializable, so that the objects capturing those can be - * serializable too. - */ +/** Factory instances implementing Serializable, so that the objects capturing those can be serializable too. + */ // Named `...CanBuildFroms` for 2.12 source compatibility (`import SerializableCanBuildFroms._`) // Can be renamed to `SerializableFactories` in a major release. object SerializableCanBuildFroms { diff --git a/core/shared/src/main/scala/org/scalacheck/Arbitrary.scala b/core/shared/src/main/scala/org/scalacheck/Arbitrary.scala index 98b8625b..753424d1 100644 --- a/core/shared/src/main/scala/org/scalacheck/Arbitrary.scala +++ b/core/shared/src/main/scala/org/scalacheck/Arbitrary.scala @@ -9,80 +9,76 @@ package org.scalacheck -import concurrent.Future -import scala.util.{Failure, Success, Try} -import scala.concurrent.duration.{Duration, FiniteDuration} +import scala.concurrent.duration.Duration +import scala.concurrent.duration.FiniteDuration +import scala.util.Failure +import scala.util.Success +import scala.util.Try +import concurrent.Future import util.Buildable import util.SerializableCanBuildFroms._ -/** - * Define an arbitrary generator for properties - * - * The [[Arbitrary]] module defines implicit generator instances for - * common types. - * - * The implicit definitions of [[Arbitrary]] provide type-directed - * [[Gen]]s so they are available for properties, generators, or other - * definitions of [[Arbitrary]]. - * - * ScalaCheck expects an implicit [[Arbitrary]] instance is in scope - * for [[Prop]]s that are defined with functions, like [[Prop$.forAll[T1,P](g1* - * Prop.forAll]] and so on. - * - * For instance, the definition for `Arbitrary[Boolean]` is used by - * `Prop.forAll` to automatically provide a `Gen[Boolean]` when one - * of the parameters is a `Boolean`: - * - * {{{ - * Prop.forAll { (b: Boolean) => - * b || !b - * } - * }}} - * - * Thanks to `Arbitrary`, you don't need to provide an explicit - * `Gen` instance to `Prop.forAll`. For instance, this is - * unnecessary: - * - * {{{ - * val genBool: Gen[Boolean] = Gen.oneOf(true,false) - * Prop.forAll(genBool) { (b: Boolean) => - * b || !b - * } - * }}} - * - * Since an arbitrary `Gen` for `Boolean` is defined in `Arbitrary`, - * it can be summoned with `Arbitrary.arbitrary` in cases where you - * need to provide one explicitly: - * - * {{{ - * val genBool: Gen[Boolean] = Arbitrary.arbitrary[Boolean] - * val genSmallInt: Gen[Int] = Gen.choose(0, 9) - * Prop.forAll(genBool, genSmallInt) { (b: Boolean, i: Int) => - * i < 10 && b || !b - * } - * }}} - * - * For a user-defined `MyClass`, writing the following requires that - * there exists an implicit `Arbitrary[MyClass]` instance: - * - * {{{ - * Prop.forAll { (myClass: MyClass) => - * ... - * } - * }}} - * - * The implicit definition of `Arbitrary[MyClass]` would look like: - * - * {{{ - * implicit val arbMyClass: Arbitrary[MyClass] = Arbitrary { - * ... - * } - * }}} - * - * The factory method `Arbitrary(...)` expects a generator of type - * `Gen[MyClass]` then it will return an instance of `Arbitrary[MyClass]`. - */ +/** Define an arbitrary generator for properties + * + * The [[Arbitrary]] module defines implicit generator instances for common types. + * + * The implicit definitions of [[Arbitrary]] provide type-directed [[Gen]]s so they are available for properties, + * generators, or other definitions of [[Arbitrary]]. + * + * ScalaCheck expects an implicit [[Arbitrary]] instance is in scope for [[Prop]]s that are defined with functions, + * like [[Prop$.forAll[T1,P](g1* Prop.forAll]] and so on. + * + * For instance, the definition for `Arbitrary[Boolean]` is used by `Prop.forAll` to automatically provide a + * `Gen[Boolean]` when one of the parameters is a `Boolean`: + * + * {{{ + * Prop.forAll { (b: Boolean) => + * b || !b + * } + * }}} + * + * Thanks to `Arbitrary`, you don't need to provide an explicit `Gen` instance to `Prop.forAll`. For instance, this is + * unnecessary: + * + * {{{ + * val genBool: Gen[Boolean] = Gen.oneOf(true,false) + * Prop.forAll(genBool) { (b: Boolean) => + * b || !b + * } + * }}} + * + * Since an arbitrary `Gen` for `Boolean` is defined in `Arbitrary`, it can be summoned with `Arbitrary.arbitrary` in + * cases where you need to provide one explicitly: + * + * {{{ + * val genBool: Gen[Boolean] = Arbitrary.arbitrary[Boolean] + * val genSmallInt: Gen[Int] = Gen.choose(0, 9) + * Prop.forAll(genBool, genSmallInt) { (b: Boolean, i: Int) => + * i < 10 && b || !b + * } + * }}} + * + * For a user-defined `MyClass`, writing the following requires that there exists an implicit `Arbitrary[MyClass]` + * instance: + * + * {{{ + * Prop.forAll { (myClass: MyClass) => + * ... + * } + * }}} + * + * The implicit definition of `Arbitrary[MyClass]` would look like: + * + * {{{ + * implicit val arbMyClass: Arbitrary[MyClass] = Arbitrary { + * ... + * } + * }}} + * + * The factory method `Arbitrary(...)` expects a generator of type `Gen[MyClass]` then it will return an instance of + * `Arbitrary[MyClass]`. + */ sealed abstract class Arbitrary[T] extends Serializable { def arbitrary: Gen[T] } @@ -91,7 +87,7 @@ object Arbitrary extends ArbitraryLowPriority with ArbitraryArities with time.Ja /** Arbitrary instance of the Function0 type. */ implicit def arbFunction0[T](implicit a: Arbitrary[T]): Arbitrary[() => T] = - Arbitrary(arbitrary[T].map(() => _)) + Arbitrary(arbitrary[T].map(() => _)) } /** separate trait to have same priority as ArbitraryArities */ @@ -106,12 +102,19 @@ private[scalacheck] sealed trait ArbitraryLowPriority { /** 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 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[Unit], + arbitrary[Boolean], + arbitrary[Char], + arbitrary[Byte], + arbitrary[Short], + arbitrary[Int], + arbitrary[Long], + arbitrary[Float], arbitrary[Double] )) @@ -153,7 +156,7 @@ private[scalacheck] sealed trait ArbitraryLowPriority { // // ((0xFFFD + 1) - 0xE000) + ((0xD7FF + 1) - 0x0000) - 1 choose(0, 63485).map { i => - if (i <= 0xD7FF) i.toChar + if (i <= 0xd7ff) i.toChar else (i + 2048).toChar } } @@ -170,7 +173,8 @@ private[scalacheck] sealed trait ArbitraryLowPriority { implicit lazy val arbUnit: Arbitrary[Unit] = Arbitrary(Gen.const(())) - /**** Arbitrary instances of other common types ****/ + /** Arbitrary instances of other common types + */ /** Arbitrary instance of String */ implicit lazy val arbString: Arbitrary[String] = @@ -224,7 +228,8 @@ private[scalacheck] sealed trait ArbitraryLowPriority { BigInt(Long.MaxValue), BigInt(Long.MinValue), BigInt(Long.MaxValue) + 1, - BigInt(Long.MinValue) - 1) + BigInt(Long.MinValue) - 1 + ) Arbitrary(frequency((5, gen0), (5, gen1), (4, gen2), (3, gen3), (2, gen4))) } @@ -260,9 +265,10 @@ private[scalacheck] sealed trait ArbitraryLowPriority { } yield { try { BigDecimal(n, scale, mc) - } catch { case _: ArithmeticException => - // Handle the case where scale/precision conflict - BigDecimal(n, scale, UNLIMITED) + } catch { + case _: ArithmeticException => + // Handle the case where scale/precision conflict + BigDecimal(n, scale, UNLIMITED) } } @@ -284,8 +290,12 @@ private[scalacheck] sealed trait ArbitraryLowPriority { /** 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[Byte], + arbitrary[Short], + arbitrary[Int], + arbitrary[Long], + arbitrary[Float], + arbitrary[Double] ) Arbitrary(gen.map(_.asInstanceOf[Number])) // XXX TODO - restore BigInt and BigDecimal @@ -296,12 +306,11 @@ private[scalacheck] sealed trait ArbitraryLowPriority { implicit lazy val arbFiniteDuration: Arbitrary[FiniteDuration] = Arbitrary(Gen.finiteDuration) - /** - * Arbitrary instance of Duration. - * - * In addition to `FiniteDuration` values, this can generate `Duration.Inf`, - * `Duration.MinusInf`, and `Duration.Undefined`. - */ + /** Arbitrary instance of Duration. + * + * In addition to `FiniteDuration` values, this can generate `Duration.Inf`, `Duration.MinusInf`, and + * `Duration.Undefined`. + */ implicit lazy val arbDuration: Arbitrary[Duration] = Arbitrary(Gen.duration) @@ -324,19 +333,18 @@ private[scalacheck] sealed trait ArbitraryLowPriority { /** 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) + _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) + _workers <- choose(1, 4) } yield Test.Parameters.default - .withMinSuccessfulTests(_minSuccTests) - .withMaxDiscardRatio(_maxDiscardRatio) - .withMinSize(_minSize) - .withMaxSize(_maxSize) - .withWorkers(_workers) - ) + .withMinSuccessfulTests(_minSuccTests) + .withMaxDiscardRatio(_maxDiscardRatio) + .withMinSize(_minSize) + .withMaxSize(_maxSize) + .withWorkers(_workers)) /** Arbitrary instance of gen params */ implicit lazy val arbGenParams: Arbitrary[Gen.Parameters] = @@ -344,15 +352,13 @@ private[scalacheck] sealed trait ArbitraryLowPriority { sz <- arbitrary[Int].suchThat(_ >= 0) } yield Gen.Parameters.default.withSize(sz)) - // Specialised collections // /** Arbitrary instance of scala.collection.BitSet */ implicit lazy val arbBitSet: Arbitrary[collection.BitSet] = Arbitrary( - buildableOf[collection.BitSet,Int](sized(sz => choose(0,sz))) + buildableOf[collection.BitSet, Int](sized(sz => choose(0, sz))) ) - // Higher-order types // /** Arbitrary instance of [[org.scalacheck.Gen]] */ @@ -378,19 +384,23 @@ private[scalacheck] sealed trait ArbitraryLowPriority { implicit def arbTry[T](implicit a: Arbitrary[T]): Arbitrary[Try[T]] = Arbitrary(Gen.oneOf(arbitrary[T].map(Success(_)), arbitrary[Throwable].map(Failure(_)))) - /** Arbitrary instance of any [[org.scalacheck.util.Buildable]] container - * (such as lists, arrays, streams / lazy lists, 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]], t: C[T] => Traversable[T] - ): Arbitrary[C[T]] = Arbitrary(buildableOf[C[T],T](arbitrary[T])) - - /** Arbitrary instance of any [[org.scalacheck.util.Buildable]] container - * (such as maps). The maximum size of the container depends on the size - * generation parameter. */ - implicit def arbContainer2[C[_,_],T,U](implicit - a: Arbitrary[(T,U)], b: Buildable[(T,U),C[T,U]], t: C[T,U] => Traversable[(T,U)] - ): Arbitrary[C[T,U]] = Arbitrary(buildableOf[C[T,U],(T,U)](arbitrary[(T,U)])) + /** Arbitrary instance of any [[org.scalacheck.util.Buildable]] container (such as lists, arrays, streams / lazy + * lists, 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]], + t: C[T] => Traversable[T] + ): Arbitrary[C[T]] = Arbitrary(buildableOf[C[T], T](arbitrary[T])) + + /** Arbitrary instance of any [[org.scalacheck.util.Buildable]] container (such as maps). The maximum size of the + * container depends on the size generation parameter. + */ + implicit def arbContainer2[C[_, _], T, U](implicit + a: Arbitrary[(T, U)], + b: Buildable[(T, U), C[T, U]], + t: C[T, U] => Traversable[(T, U)] + ): Arbitrary[C[T, U]] = Arbitrary(buildableOf[C[T, U], (T, U)](arbitrary[(T, U)])) implicit def arbEnum[A <: java.lang.Enum[A]](implicit A: reflect.ClassTag[A]): Arbitrary[A] = { val values = A.runtimeClass.getEnumConstants.asInstanceOf[Array[A]] diff --git a/core/shared/src/main/scala/org/scalacheck/Cogen.scala b/core/shared/src/main/scala/org/scalacheck/Cogen.scala index 4af7a93a..86cb3aab 100644 --- a/core/shared/src/main/scala/org/scalacheck/Cogen.scala +++ b/core/shared/src/main/scala/org/scalacheck/Cogen.scala @@ -9,15 +9,19 @@ package org.scalacheck -import scala.annotation.tailrec -import scala.collection.immutable.BitSet -import scala.util.{Failure, Success, Try} -import scala.concurrent.duration.{Duration, FiniteDuration} import java.math.BigInteger import java.util.UUID -import rng.Seed +import scala.annotation.tailrec +import scala.collection.immutable.BitSet import scala.collection.immutable.SortedMap import scala.collection.immutable.SortedSet +import scala.concurrent.duration.Duration +import scala.concurrent.duration.FiniteDuration +import scala.util.Failure +import scala.util.Success +import scala.util.Try + +import rng.Seed sealed trait Cogen[T] extends Serializable { @@ -94,7 +98,7 @@ object Cogen extends CogenArities with CogenLowPriority with CogenVersionSpecifi else { val (unscaled, scale) = normalize(n.bigDecimal.unscaledValue, n.scale) Cogen[(Int, Array[Byte])].perturb(seed, (scale, unscaled.toByteArray)) - }) + }) } implicit lazy val bitSet: Cogen[BitSet] = @@ -126,16 +130,14 @@ object Cogen extends CogenArities with CogenLowPriority with CogenVersionSpecifi implicit def cogenSet[A: Cogen: Ordering]: Cogen[Set[A]] = Cogen[SortedSet[A]].contramap(value => - value.foldLeft(SortedSet.empty[A])(_ + _) - ) + value.foldLeft(SortedSet.empty[A])(_ + _)) implicit def cogenSortedSet[A: Cogen]: Cogen[SortedSet[A]] = Cogen.it(_.iterator) implicit def cogenMap[K: Cogen: Ordering, V: Cogen]: Cogen[Map[K, V]] = Cogen[SortedMap[K, V]].contramap(value => - value.foldLeft(SortedMap.empty[K, V])(_ + _) - ) + value.foldLeft(SortedMap.empty[K, V])(_ + _)) implicit def cogenSortedMap[K: Cogen, V: Cogen]: Cogen[SortedMap[K, V]] = Cogen.it(_.iterator) @@ -150,30 +152,31 @@ object Cogen extends CogenArities with CogenLowPriority with CogenVersionSpecifi Cogen[String].contramap(_.toString) implicit def cogenTry[A: Cogen]: Cogen[Try[A]] = - Cogen((seed: Seed, x: Try[A]) => x match { - case Success(a) => Cogen[A].perturb(seed.next, a) - case Failure(e) => Cogen[Throwable].perturb(seed, e) - }) + Cogen((seed: Seed, x: Try[A]) => + x match { + case Success(a) => Cogen[A].perturb(seed.next, a) + case Failure(e) => Cogen[Throwable].perturb(seed, e) + }) implicit val cogenFiniteDuration: Cogen[FiniteDuration] = Cogen[Long].contramap(_.toNanos) implicit val cogenDuration: Cogen[Duration] = - Cogen((seed: Seed, x: Duration) => x match { - case d: FiniteDuration => Cogen[FiniteDuration].perturb(seed, d) - // Undefined -> NaN, Inf -> PositiveInfinity, MinusInf -> NegativeInf - // We could just use `toUnit` for finite durations too, but the Long => Double - // conversion is lossy, so this approach may be better. - case d => Cogen[Double].perturb(seed, d.toUnit(java.util.concurrent.TimeUnit.NANOSECONDS)) - }) + Cogen((seed: Seed, x: Duration) => + x match { + case d: FiniteDuration => Cogen[FiniteDuration].perturb(seed, d) + // Undefined -> NaN, Inf -> PositiveInfinity, MinusInf -> NegativeInf + // We could just use `toUnit` for finite durations too, but the Long => Double + // conversion is lossy, so this approach may be better. + case d => Cogen[Double].perturb(seed, d.toUnit(java.util.concurrent.TimeUnit.NANOSECONDS)) + }) implicit def cogenPartialFunction[A: Arbitrary, B: Cogen]: Cogen[PartialFunction[A, B]] = Cogen[A => Option[B]].contramap(_.lift) implicit val cogenUUID: Cogen[UUID] = Cogen[(Long, Long)].contramap(value => - (value.getLeastSignificantBits, value.getMostSignificantBits) - ) + (value.getLeastSignificantBits, value.getMostSignificantBits)) def perturbPair[A, B](seed: Seed, ab: (A, B))(implicit A: Cogen[A], B: Cogen[B]): Seed = B.perturb(A.perturb(seed, ab._1), ab._2) diff --git a/core/shared/src/main/scala/org/scalacheck/Gen.scala b/core/shared/src/main/scala/org/scalacheck/Gen.scala index 94f2cd84..69d2091d 100644 --- a/core/shared/src/main/scala/org/scalacheck/Gen.scala +++ b/core/shared/src/main/scala/org/scalacheck/Gen.scala @@ -9,213 +9,202 @@ package org.scalacheck -import rng.Seed -import util.Buildable -import util.SerializableCanBuildFroms._ -import ScalaVersionSpecific._ - +import java.math.BigInteger +import java.math.{BigDecimal => JavaDecimal} +import java.util.Calendar +import java.util.UUID import scala.annotation.tailrec import scala.collection.immutable.TreeMap import scala.collection.mutable.ArrayBuffer -import scala.concurrent.duration.{Duration, FiniteDuration} +import scala.concurrent.duration.Duration +import scala.concurrent.duration.FiniteDuration -import java.util.{ Calendar, UUID } -import java.math.{BigInteger, BigDecimal => JavaDecimal} +import rng.Seed +import util.Buildable +import util.SerializableCanBuildFroms._ +import ScalaVersionSpecific._ -/** - * A generator produces values for [[Prop]]s - * - * This module provides: - * 1. Definitions for non-arbitrary generators, - * 1. Factories to construct generators, - * 1. Methods to modify a generator, and - * 1. Various combinators for producing generators of values for more - * complex data types. - * - * Explicit generators aren't required to write [[Prop]]s: - * - * {{{ - * Prop.forAll { (n: Int) => - * n == n - * } - * }}} - * - * The [[Prop]] above is defined with parameters only and without an - * explicit generator, because generators are implicitly provided by - * [[Arbitrary]] for various data types. - * - * However, it's not uncommon to need to write explicit custom - * generators: - * - * {{{ - * val genInt: Gen[Int] = Gen.choose(1,10) - * Prop.forAll(genInt) { (n: Int) => - * 1 <= n && n <= 10 - * } - * }}} - * - * This is a simple definition of a generator for booleans: - * {{{ - * val genBool: Gen[Boolean] = Gen.oneOf(true,false) - * }}} - * - * The above definition isn't necessary, though. The same boolean - * generator is defined in [[Arbitrary]] as an implicit declaration - * for automatically parameterizing [[Prop]]s. Instead, use the - * generator that is defined in [[Arbitrary]] and available from the - * polymorphic method [[Arbitrary.arbitrary]] with an explicit type - * parameter: - * - * {{{ - * val genBool: Gen[Boolean] = Arbitrary.arbitrary[Boolean] - * }}} - * - * Alternatively, this is a boolean generator, but one that always - * produces true: - * {{{ - * val genBool = Gen.const(true) - * }}} - * - * This is a generator of booleans that is true at a 2-to-1 ratio: - * {{{ - * val genBool = Gen.frequency(2 -> true, 1 -> false) - * }}} - * - * This is a boolean generator that will produce true 75% of the time: - * {{{ - * val genBool = Gen.prob(0.75) - * }}} - * - * For more information on designing custom generators and the - * motivations for doing so, see chapter 6, ''Generators in Detail'', - * of the book ''ScalaCheck: The Definitive Guide'' (2013) by Rickard - * Nilsson published by Artima Press. - * - * This is an example of a custom generator for integers: - * {{{ - * val genSmallInt: Gen[Int] = Gen.choose(-100,100) - * }}} - * - * This can be used to generate different collections of zero or more small integers: - * {{{ - * val genListOfInts: Gen[List[Int]] = Gen.listOf(genSmallInt) - * - * val genSeqOfInts: Gen[Seq[Int]] = Gen.someOf(-100 to 100) - * - * val genVectorOfInts: Gen[Vector[Int]] = Gen.containerOf[Vector,Int](genSmallInt) - * - * val genMap: Gen[Map[Int,Boolean]] = Gen.mapOf(Gen.zip(genSmallInt, genBool)) - * - * val genOptionalInt: Gen[Option[Int]] = Gen.option(genSmallInt) - * }}} - * - * Or collections of one or more small integers: - * {{{ - * val genListOfInts: Gen[List[Int]] = Gen.nonEmptyListOf(genSmallInt) - * - * val genSeqOfInts: Gen[Seq[Int]] = Gen.atLeastOne(-100 to 100) - * - * val genVectorOfInts: Gen[Vector[Int]] = Gen.nonEmptyContainerOf[Vector,Int](genSmallInt) - * - * val genMap: Gen[Map[Int,Boolean]] = Gen.nonEmptyMap(Gen.zip(genSmallInt, genBool)) - * - * val genOptionalInt: Gen[Option[Int]] = Gen.some(genSmallInt) - * }}} - * - * The class methods for [[Gen]] should be familiar with those in the - * [[scala.collection Scala collections API]]: - * - * - [[map]] - Apply a function to generated values - * - [[flatMap]] - Apply a function that returns a generator - * - [[filter]] - Use values that satisfy a predicate - * - * The [[Gen]] class also supports for-comprehensions to compose - * complex generators: - * - * {{{ - * val genPerson = for { - * firstName <- Gen.oneOf("Alan", "Ada", "Alonzo") - * lastName <- Gen.oneOf("Lovelace", "Turing", "Church") - * age <- Gen.choose(0,100) if (age >= 18) - * } yield Person(firstName, lastName, age) - * }}} - * - * Constructors and factories for generators: - * - [[Gen$.const const]] - Always generates a single value - * - [[Gen$.oneOf[T](t0* oneOf]] - Generate a value from a list of values - * - [[Gen$.atLeastOne[T](g1* atLeastOne]] - Generate a collection with at least one value from a list - * - [[Gen$.someOf[T](l* someOf]] - Generate a collection with zero or more values from a list - * - [[Gen$.choose choose]] - Generate numeric values in an (inclusive) range - * - [[Gen$.frequency frequency]] - Choose from multiple values with a weighted distribution - * - * Combinators of generators: - * - [[Gen$.buildableOf buildableOf]] - Generates a collection with a generator - * - [[Gen$.buildableOfN buildableOfN]] - Generates a collection of at most ''n'' elements - * - [[Gen$.nonEmptyBuildableOf nonEmptyBuildableOf]] - Generates a non-empty collection - * - [[Gen$.containerOf containerOf]] - Generates a collection with a generator - * - [[Gen$.containerOfN containerOfN]] - Generates a collection of at most ''n'' elements - * - [[Gen$.nonEmptyContainerOf nonEmptyContainerOf]] - Generates a non-empty collection - * - [[Gen$.either either]] - Generate a disjoint union of [[scala.util.Either]] - * - infiniteLazyList - Generates an infinite lazy list - * - [[Gen$.infiniteStream infiniteStream]] - Generates an infinite stream - * - [[Gen$.listOf listOf]] - Generates a list of random length - * - [[Gen$.listOfN listOfN]] - Generates a list of at most ''n'' elements - * - [[Gen$.nonEmptyListOf nonEmptyListOf]] - Generates a non-empty list of random length. - * - [[Gen$.mapOf mapOf]] - Generates a [[scala.collection.Map]] - * - [[Gen$.mapOfN mapOfN]] - Generates a [[scala.collection.Map]] with at most ''n'' elements - * - [[Gen$.nonEmptyMap nonEmptyMap]] - Generates a non-empty map of random length - * - [[Gen$.option option]] - Generate values of [[scala.Some]] and [[scala.None]] - * - [[Gen$.pick[T](n:Int,g1* pick]] - A generator that randomly picks ''n'' elements from a list - * - [[Gen$.sequence sequence]] - Sequences generators. - * - [[Gen$.some some]] - A generator of [[scala.Some]] - * - [[Gen.someOf[T](g1* someOf]] - A generator that picks a random number of elements from a list - * - [[Gen$.stringOf stringOf]] - Generate string of characters - * - [[Gen$.stringOfN stringOfN]] - Generate string of at most ''n'' characters - * - [[Gen$.nonEmptyStringOf nonEmptyStringOf]] - Generate a non-empty string of characters - * - * Methods for working with [[Gen]] internals: - * - [[Gen$.resize resize]] - Creates a resized version of a generator - * - [[Gen$.parameterized parameterized]] - Generator with the parameters - * - [[Gen$.size size]] - Generate with the value of the default size parameter - * - [[Gen$.sized sized]] - Build a generator using the default size parameter - - * Methods for probabilistic generators: - * - [[Gen$.exponential exponential]] - Generate numbers according to an exponential distribution - * - [[Gen$.gaussian gaussian]] - Generates numbers according to a Gaussian distribution - * - [[Gen$.geometric geometric]] - Generates numbers according to a geometric distribution - * - [[Gen$.poisson poisson]] - Generates numbers according to a Poisson distribution - * - [[Gen$.prob prob]] - Generates a boolean for the probability of true - * - * Definitions for generating various, non-arbitrary, common values of - * strings and characters: - * - [[Gen$.alphaChar alphaChar]] - Generates an alpha character - * - [[Gen$.alphaStr alphaStr]] - Generates a string of alpha characters - * - [[Gen$.numChar numChar]] - Generates a numerical character - * - [[Gen$.numStr numStr]] - Generates a string of digits - * - [[Gen$.alphaNumChar alphaNumChar]] - Generates an alphanumerical character - * - [[Gen$.alphaNumStr alphaNumStr]] - Generates a string of alphanumerical characters - * - [[Gen$.alphaLowerChar alphaLowerChar]] - Generates a lower-case alpha character - * - [[Gen$.alphaLowerStr alphaLowerStr]] - Generates a string of lower-case alpha characters - * - [[Gen$.alphaUpperChar alphaUpperChar]] - Generates an upper-case alpha character - * - [[Gen$.alphaUpperStr alphaUpperStr]] - Generates a string of upper-case alpha characters - * - [[Gen$.asciiChar asciiChar]] - Generates an ASCII character - * - [[Gen$.asciiStr asciiStr]] - Generates a string of ASCII characters - * - [[Gen$.identifier identifier]] - Generates an identifier - * - [[Gen$.uuid uuid]] - Generates a UUID - * - [[Gen$.hexChar hexChar]] - Generates a character of a hexadecimal digit - * - [[Gen$.hexStr hexStr]] - Generates a string of hexadecimal digits - * - * Definitions for generating arbitrary values of commonly used types in - * Scala are defined elsewhere, see [[Arbitrary]]. - * - * There are a couple of factory methods that are for advanced uses of generators: - * - [[Gen$.delay delay]] - Generate a value of an expression by-name - * - [[Gen$.lzy lzy]] - Lazily generate a value of an expression - * - [[Gen$.fail fail]] - Fail to generate any values of a type - * - [[Gen$.recursive recursive]] - A fixed point generator - * - [[Gen$.resultOf[T,R0](f* resultOf]] - Generate values with a function or class - * - [[Gen$.zip[T1](g1* zip]] - Generate tuples - */ +/** A generator produces values for [[Prop]]s + * + * This module provides: + * 1. Definitions for non-arbitrary generators, + * 1. Factories to construct generators, + * 1. Methods to modify a generator, and + * 1. Various combinators for producing generators of values for more complex data types. + * + * Explicit generators aren't required to write [[Prop]]s: + * + * {{{ + * Prop.forAll { (n: Int) => + * n == n + * } + * }}} + * + * The [[Prop]] above is defined with parameters only and without an explicit generator, because generators are + * implicitly provided by [[Arbitrary]] for various data types. + * + * However, it's not uncommon to need to write explicit custom generators: + * + * {{{ + * val genInt: Gen[Int] = Gen.choose(1,10) + * Prop.forAll(genInt) { (n: Int) => + * 1 <= n && n <= 10 + * } + * }}} + * + * This is a simple definition of a generator for booleans: + * {{{ + * val genBool: Gen[Boolean] = Gen.oneOf(true,false) + * }}} + * + * The above definition isn't necessary, though. The same boolean generator is defined in [[Arbitrary]] as an implicit + * declaration for automatically parameterizing [[Prop]]s. Instead, use the generator that is defined in [[Arbitrary]] + * and available from the polymorphic method [[Arbitrary.arbitrary]] with an explicit type parameter: + * + * {{{ + * val genBool: Gen[Boolean] = Arbitrary.arbitrary[Boolean] + * }}} + * + * Alternatively, this is a boolean generator, but one that always produces true: + * {{{ + * val genBool = Gen.const(true) + * }}} + * + * This is a generator of booleans that is true at a 2-to-1 ratio: + * {{{ + * val genBool = Gen.frequency(2 -> true, 1 -> false) + * }}} + * + * This is a boolean generator that will produce true 75% of the time: + * {{{ + * val genBool = Gen.prob(0.75) + * }}} + * + * For more information on designing custom generators and the motivations for doing so, see chapter 6, ''Generators in + * Detail'', of the book ''ScalaCheck: The Definitive Guide'' (2013) by Rickard Nilsson published by Artima Press. + * + * This is an example of a custom generator for integers: + * {{{ + * val genSmallInt: Gen[Int] = Gen.choose(-100,100) + * }}} + * + * This can be used to generate different collections of zero or more small integers: + * {{{ + * val genListOfInts: Gen[List[Int]] = Gen.listOf(genSmallInt) + * + * val genSeqOfInts: Gen[Seq[Int]] = Gen.someOf(-100 to 100) + * + * val genVectorOfInts: Gen[Vector[Int]] = Gen.containerOf[Vector,Int](genSmallInt) + * + * val genMap: Gen[Map[Int,Boolean]] = Gen.mapOf(Gen.zip(genSmallInt, genBool)) + * + * val genOptionalInt: Gen[Option[Int]] = Gen.option(genSmallInt) + * }}} + * + * Or collections of one or more small integers: + * {{{ + * val genListOfInts: Gen[List[Int]] = Gen.nonEmptyListOf(genSmallInt) + * + * val genSeqOfInts: Gen[Seq[Int]] = Gen.atLeastOne(-100 to 100) + * + * val genVectorOfInts: Gen[Vector[Int]] = Gen.nonEmptyContainerOf[Vector,Int](genSmallInt) + * + * val genMap: Gen[Map[Int,Boolean]] = Gen.nonEmptyMap(Gen.zip(genSmallInt, genBool)) + * + * val genOptionalInt: Gen[Option[Int]] = Gen.some(genSmallInt) + * }}} + * + * The class methods for [[Gen]] should be familiar with those in the [[scala.collection Scala collections API]]: + * + * - [[map]] - Apply a function to generated values + * - [[flatMap]] - Apply a function that returns a generator + * - [[filter]] - Use values that satisfy a predicate + * + * The [[Gen]] class also supports for-comprehensions to compose complex generators: + * + * {{{ + * val genPerson = for { + * firstName <- Gen.oneOf("Alan", "Ada", "Alonzo") + * lastName <- Gen.oneOf("Lovelace", "Turing", "Church") + * age <- Gen.choose(0,100) if (age >= 18) + * } yield Person(firstName, lastName, age) + * }}} + * + * Constructors and factories for generators: + * - [[Gen$.const const]] - Always generates a single value + * - [[Gen$.oneOf[T](t0* oneOf]] - Generate a value from a list of values + * - [[Gen$.atLeastOne[T](g1* atLeastOne]] - Generate a collection with at least one value from a list + * - [[Gen$.someOf[T](l* someOf]] - Generate a collection with zero or more values from a list + * - [[Gen$.choose choose]] - Generate numeric values in an (inclusive) range + * - [[Gen$.frequency frequency]] - Choose from multiple values with a weighted distribution + * + * Combinators of generators: + * - [[Gen$.buildableOf buildableOf]] - Generates a collection with a generator + * - [[Gen$.buildableOfN buildableOfN]] - Generates a collection of at most ''n'' elements + * - [[Gen$.nonEmptyBuildableOf nonEmptyBuildableOf]] - Generates a non-empty collection + * - [[Gen$.containerOf containerOf]] - Generates a collection with a generator + * - [[Gen$.containerOfN containerOfN]] - Generates a collection of at most ''n'' elements + * - [[Gen$.nonEmptyContainerOf nonEmptyContainerOf]] - Generates a non-empty collection + * - [[Gen$.either either]] - Generate a disjoint union of [[scala.util.Either]] + * - infiniteLazyList - Generates an infinite lazy list + * - [[Gen$.infiniteStream infiniteStream]] - Generates an infinite stream + * - [[Gen$.listOf listOf]] - Generates a list of random length + * - [[Gen$.listOfN listOfN]] - Generates a list of at most ''n'' elements + * - [[Gen$.nonEmptyListOf nonEmptyListOf]] - Generates a non-empty list of random length. + * - [[Gen$.mapOf mapOf]] - Generates a [[scala.collection.Map]] + * - [[Gen$.mapOfN mapOfN]] - Generates a [[scala.collection.Map]] with at most ''n'' elements + * - [[Gen$.nonEmptyMap nonEmptyMap]] - Generates a non-empty map of random length + * - [[Gen$.option option]] - Generate values of [[scala.Some]] and [[scala.None]] + * - [[Gen$.pick[T](n:Int,g1* pick]] - A generator that randomly picks ''n'' elements from a list + * - [[Gen$.sequence sequence]] - Sequences generators. + * - [[Gen$.some some]] - A generator of [[scala.Some]] + * - [[Gen.someOf[T](g1* someOf]] - A generator that picks a random number of elements from a list + * - [[Gen$.stringOf stringOf]] - Generate string of characters + * - [[Gen$.stringOfN stringOfN]] - Generate string of at most ''n'' characters + * - [[Gen$.nonEmptyStringOf nonEmptyStringOf]] - Generate a non-empty string of characters + * + * Methods for working with [[Gen]] internals: + * - [[Gen$.resize resize]] - Creates a resized version of a generator + * - [[Gen$.parameterized parameterized]] - Generator with the parameters + * - [[Gen$.size size]] - Generate with the value of the default size parameter + * - [[Gen$.sized sized]] - Build a generator using the default size parameter + * + * Methods for probabilistic generators: + * - [[Gen$.exponential exponential]] - Generate numbers according to an exponential distribution + * - [[Gen$.gaussian gaussian]] - Generates numbers according to a Gaussian distribution + * - [[Gen$.geometric geometric]] - Generates numbers according to a geometric distribution + * - [[Gen$.poisson poisson]] - Generates numbers according to a Poisson distribution + * - [[Gen$.prob prob]] - Generates a boolean for the probability of true + * + * Definitions for generating various, non-arbitrary, common values of strings and characters: + * - [[Gen$.alphaChar alphaChar]] - Generates an alpha character + * - [[Gen$.alphaStr alphaStr]] - Generates a string of alpha characters + * - [[Gen$.numChar numChar]] - Generates a numerical character + * - [[Gen$.numStr numStr]] - Generates a string of digits + * - [[Gen$.alphaNumChar alphaNumChar]] - Generates an alphanumerical character + * - [[Gen$.alphaNumStr alphaNumStr]] - Generates a string of alphanumerical characters + * - [[Gen$.alphaLowerChar alphaLowerChar]] - Generates a lower-case alpha character + * - [[Gen$.alphaLowerStr alphaLowerStr]] - Generates a string of lower-case alpha characters + * - [[Gen$.alphaUpperChar alphaUpperChar]] - Generates an upper-case alpha character + * - [[Gen$.alphaUpperStr alphaUpperStr]] - Generates a string of upper-case alpha characters + * - [[Gen$.asciiChar asciiChar]] - Generates an ASCII character + * - [[Gen$.asciiStr asciiStr]] - Generates a string of ASCII characters + * - [[Gen$.identifier identifier]] - Generates an identifier + * - [[Gen$.uuid uuid]] - Generates a UUID + * - [[Gen$.hexChar hexChar]] - Generates a character of a hexadecimal digit + * - [[Gen$.hexStr hexStr]] - Generates a string of hexadecimal digits + * + * Definitions for generating arbitrary values of commonly used types in Scala are defined elsewhere, see + * [[Arbitrary]]. + * + * There are a couple of factory methods that are for advanced uses of generators: + * - [[Gen$.delay delay]] - Generate a value of an expression by-name + * - [[Gen$.lzy lzy]] - Lazily generate a value of an expression + * - [[Gen$.fail fail]] - Fail to generate any values of a type + * - [[Gen$.recursive recursive]] - A fixed point generator + * - [[Gen$.resultOf[T,R0](f* resultOf]] - Generate values with a function or class + * - [[Gen$.zip[T1](g1* zip]] - Generate tuples + */ sealed abstract class Gen[+T] extends Serializable { self => //// Private interface //// @@ -251,16 +240,13 @@ sealed abstract class Gen[+T] extends Serializable { self => loop(doApply(p, seed), retries) } - /** - * Evaluate this generator with the given parameters. - * - * The generator will attempt to generate a valid `T` value. If a - * valid value is not produced it may retry several times, - * determined by the `retries` parameter (which defaults to 100). - * - * If all the retries fail it will throw a `Gen.RetrievalError` - * exception. - */ + /** Evaluate this generator with the given parameters. + * + * The generator will attempt to generate a valid `T` value. If a valid value is not produced it may retry several + * times, determined by the `retries` parameter (which defaults to 100). + * + * If all the retries fail it will throw a `Gen.RetrievalError` exception. + */ def pureApply(p: Gen.Parameters, seed: Seed, retries: Int = 100): T = doPureApply(p, seed, retries).retrieve.get @@ -273,26 +259,25 @@ sealed abstract class Gen[+T] extends Serializable { self => rt.flatMap(t => f(t).doApply(p, rt.seed)) } - /** 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). Also, make sure that the provided - * test property is side-effect free, e.g. it should not use external vars. */ + /** 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). Also, make sure that the provided test property is + * side-effect free, e.g. it should not use external vars. + */ def filter(p: T => Boolean): Gen[T] = suchThat(p) - /** Create a new generator that uses this generator to produce a value - * that doesn't fulfill the given condition. If the condition is fulfilled, - * the generator fails (returns None). Also, make sure that the provided - * test property is side-effect free, e.g. it should not use external vars. */ + /** Create a new generator that uses this generator to produce a value that doesn't fulfill the given condition. If + * the condition is fulfilled, the generator fails (returns None). Also, make sure that the provided test property is + * side-effect free, e.g. it should not use external vars. + */ def filterNot(p: T => Boolean): Gen[T] = suchThat(x => !p(x)) /** 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). Also, make sure that the provided - * test property is side-effect free, e.g. it should not use external vars. - * This method is identical to [Gen.filter]. */ + /** 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). Also, make sure that the provided test property is + * side-effect free, e.g. it should not use external vars. This method is identical to [Gen.filter]. + */ def suchThat(f: T => Boolean): Gen[T] = new Gen[T] { def doApply(p: Gen.Parameters, seed: Seed): Gen.R[T] = @@ -304,45 +289,39 @@ sealed abstract class Gen[+T] extends Serializable { self => case class RetryUntilException(n: Int) extends RuntimeException(s"retryUntil failed after $n attempts") - /** - * Create a generator that calls this generator repeatedly until the - * given condition is fulfilled. The generated value is then - * returned. Make sure that the provided test property is - * side-effect free (it should not use external vars). - * - * If the generator fails more than maxTries, a RetryUntilException - * will be thrown. - */ + /** Create a generator that calls this generator repeatedly until the given condition is fulfilled. The generated + * value is then returned. Make sure that the provided test property is side-effect free (it should not use external + * vars). + * + * If the generator fails more than maxTries, a RetryUntilException will be thrown. + */ def retryUntil(p: T => Boolean, maxTries: Int): Gen[T] = { require(maxTries > 0) def loop(params: Gen.Parameters, seed: Seed, tries: Int): R[T] = - if (tries > maxTries) throw RetryUntilException(tries) else { + if (tries > maxTries) throw RetryUntilException(tries) + else { val r = self.doApply(params, seed) if (r.retrieve.exists(p)) r else loop(params, r.seed, tries + 1) } Gen.gen((params, seed) => loop(params, seed, 1)) } - /** - * Create a generator that calls this generator repeatedly until the - * given condition is fulfilled. The generated value is then - * returned. Make sure that the provided test property is - * side-effect free (it should not use external vars). - * - * - * If the generator fails more than 10000 times, a - * RetryUntilException will be thrown. You can call `retryUntil` - * with a second parameter to change this number. - */ + /** Create a generator that calls this generator repeatedly until the given condition is fulfilled. The generated + * value is then returned. Make sure that the provided test property is side-effect free (it should not use external + * vars). + * + * If the generator fails more than 10000 times, a RetryUntilException will be thrown. You can call `retryUntil` with + * a second parameter to change this number. + */ def retryUntil(p: T => Boolean): Gen[T] = retryUntil(p, 10000) def sample: Option[T] = doApply(Gen.Parameters.default, Seed.random()).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. */ + /** 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 = Prop { prms => // test equality using a random seed val seed = Seed.random() @@ -408,13 +387,13 @@ object Gen extends GenArities with GenVersionSpecific { def retrieve: Option[T] = result - @deprecated(message="Please use withLabels, withResult, or withSeed instead.", since="1.18.0") + @deprecated(message = "Please use withLabels, withResult, or withSeed instead.", since = "1.18.0") def copy[U >: T]( - l: Set[String] = this.labels, - // s is no longer used but preserved for binary compatibility - s: U => Boolean = this.sieve, - r: Option[U] = this.result, - sd: Seed = this.seed + l: Set[String] = this.labels, + // s is no longer used but preserved for binary compatibility + s: U => Boolean = this.sieve, + r: Option[U] = this.result, + sd: Seed = this.seed ): R[U] = withLabels(l).withSeed(sd).withResult(r) final def withLabels(l: Set[String]): R[T] = new R[T] { @@ -472,18 +451,16 @@ object Gen extends GenArities with GenVersionSpecific { sb.toString } - /** - * 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]]. - */ + /** 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 private[this] def cpy( - size0: Int = outer.size, - initialSeed0: Option[Seed] = outer.initialSeed, - useLegacyShrinking0: Boolean = outer.useLegacyShrinking + size0: Int = outer.size, + initialSeed0: Option[Seed] = outer.initialSeed, + useLegacyShrinking0: Boolean = outer.useLegacyShrinking ): Parameters = new Parameters { val size: Int = size0 @@ -491,16 +468,12 @@ object Gen extends GenArities with GenVersionSpecific { override val useLegacyShrinking: Boolean = useLegacyShrinking0 } - /** - * Create a copy of this [[Gen.Parameters]] instance with - * [[Gen.Parameters.size]] set to the specified value. - */ + /** Create a copy of this [[Gen.Parameters]] instance with [[Gen.Parameters.size]] set to the specified value. + */ def withSize(size: Int): Parameters = cpy(size0 = size) - /** - * - */ + /** */ val initialSeed: Option[Seed] def withInitialSeed(o: Option[Seed]): Parameters = @@ -539,6 +512,7 @@ object Gen extends GenArities with GenVersionSpecific { /** Provides methods for creating [[org.scalacheck.Gen.Parameters]] values */ object Parameters { + /** Default generator parameters instance. */ val default: Parameters = new Parameters { val size: Int = 100 @@ -548,6 +522,7 @@ object Gen extends GenArities with GenVersionSpecific { /** A wrapper type for range types */ trait Choose[T] extends Serializable { + /** Creates a generator that returns a value in the given inclusive range */ def choose(min: T, max: T): Gen[T] } @@ -558,10 +533,8 @@ object Gen extends GenArities with GenVersionSpecific { class IllegalBoundsError[A](low: A, high: A) extends IllegalArgumentException(s"invalid bounds: low=$low, high=$high") - /** - * This method gets a ton of use -- so we want it to be as fast as - * possible for many of our common cases. - */ + /** This method gets a ton of use -- so we want it to be as fast as possible for many of our common cases. + */ private def chLng(l: Long, h: Long)(p: P, seed: Seed): R[Long] = { if (h < l) { throw new IllegalBoundsError(l, h) @@ -612,27 +585,22 @@ object Gen extends GenArities with GenVersionSpecific { r(Some(l), seed) } else { val (n, s) = seed.double - r(Some(n * (h-l) + l), s) + r(Some(n * (h - l) + l), s) } } - /** - * Generate a random BigInt within [lower, lower + span). - * - * Note that unlike the choose method, whose bounds are inclusive, - * this method's upper bound is exclusive. We determine how many - * random bits we need (bitLen), and then round up to the nearest - * number of bytes (byteLen). We generate the bytes, possibly - * truncating the most significant byte (bytes(0)) if bitLen is - * not evenly-divisible by 8. - * - * Finally, we check to see if the BigInt we ended up with is in - * our range. If it is not, we restart this method. The likelihood - * of needing to restart depends on span. In the worst case we - * have almost a 50% chance of this (which occurs when span is a - * power of 2 + 1) and in the best case we never restart (which - * occurs when span is a power of 2). - */ + /** Generate a random BigInt within [lower, lower + span). + * + * Note that unlike the choose method, whose bounds are inclusive, this method's upper bound is exclusive. We + * determine how many random bits we need (bitLen), and then round up to the nearest number of bytes (byteLen). We + * generate the bytes, possibly truncating the most significant byte (bytes(0)) if bitLen is not evenly-divisible + * by 8. + * + * Finally, we check to see if the BigInt we ended up with is in our range. If it is not, we restart this method. + * The likelihood of needing to restart depends on span. In the worst case we have almost a 50% chance of this + * (which occurs when span is a power of 2 + 1) and in the best case we never restart (which occurs when span is a + * power of 2). + */ private def chBigInteger(lower: BigInteger, span: BigInteger, seed0: Seed): R[BigInteger] = { val bitLen = span.bitLength val byteLen = (bitLen + 7) / 8 @@ -679,7 +647,7 @@ object Gen extends GenArities with GenVersionSpecific { new Choose[Long] { def choose(low: Long, high: Long): Gen[Long] = if (low > high) throw new IllegalBoundsError(low, high) - else gen(chLng(low,high)) + else gen(chLng(low, high)) } implicit val chooseInt: Choose[Int] = @@ -698,12 +666,10 @@ object Gen extends GenArities with GenVersionSpecific { def choose(low: Double, high: Double) = if (low > high) throw new IllegalBoundsError(low, high) else if (low == Double.NegativeInfinity) - frequency(1 -> const(Double.NegativeInfinity), - 9 -> choose(Double.MinValue, high)) + frequency(1 -> const(Double.NegativeInfinity), 9 -> choose(Double.MinValue, high)) else if (high == Double.PositiveInfinity) - frequency(1 -> const(Double.PositiveInfinity), - 9 -> choose(low, Double.MaxValue)) - else gen(chDbl(low,high)) + frequency(1 -> const(Double.PositiveInfinity), 9 -> choose(low, Double.MaxValue)) + else gen(chDbl(low, high)) } implicit val chooseFloat: Choose[Float] = @@ -730,35 +696,30 @@ object Gen extends GenArities with GenVersionSpecific { } } - /** - * Choose a BigDecimal number between two given numbers. - * - * The minimum scale used will be 34. That means that the - * fractional part will have at least 34 digits (more if one of - * the given numbers has a scale larger than 34). - * - * The minimum scale was chosen based on Scala's default scale for - * expanding infinite fractions: - * - * BigDecimal(1) / 3 // 0.3333333333333333333333333333333333 - * - * See chooseBigDecimalScale for more information about scale. - */ + /** Choose a BigDecimal number between two given numbers. + * + * The minimum scale used will be 34. That means that the fractional part will have at least 34 digits (more if one + * of the given numbers has a scale larger than 34). + * + * The minimum scale was chosen based on Scala's default scale for expanding infinite fractions: + * + * BigDecimal(1) / 3 // 0.3333333333333333333333333333333333 + * + * See chooseBigDecimalScale for more information about scale. + */ implicit val chooseBigDecimal: Choose[BigDecimal] = chooseBigDecimalScale(minScale = 34) - /** - * The "scale" of a decimal number refers to the number of digits - * in the fractional part. For example, 3.0000 has a scale of 4. - * - * We can generate an arbitrary number of digits in the decimal - * expansion of a number, so if a user calls choose(0, 1) we need - * to decide "how much" work to do. The minScale ensures that we - * do "enough" work to generate interesting numbers. - * - * The implicit instance fixes this value, but since users may - * want to use other scales we expose this method as well. - */ + /** The "scale" of a decimal number refers to the number of digits in the fractional part. For example, 3.0000 has a + * scale of 4. + * + * We can generate an arbitrary number of digits in the decimal expansion of a number, so if a user calls choose(0, + * 1) we need to decide "how much" work to do. The minScale ensures that we do "enough" work to generate + * interesting numbers. + * + * The implicit instance fixes this value, but since users may want to use other scales we expose this method as + * well. + */ private[this] def chooseBigDecimalScale(minScale: Int): Choose[BigDecimal] = new Choose[BigDecimal] { private val c = chooseJavaBigDecimalScale(minScale) @@ -766,36 +727,34 @@ object Gen extends GenArities with GenVersionSpecific { c.choose(low.bigDecimal, high.bigDecimal).map(BigDecimal(_)) } - /** - * Choose a java.math.BigDecimal number between two given numbers. - * - * See chooseBigDecimal and chooseBigDecimalScale for more comments. - */ + /** Choose a java.math.BigDecimal number between two given numbers. + * + * See chooseBigDecimal and chooseBigDecimalScale for more comments. + */ implicit val chooseJavaBigDecimal: Choose[JavaDecimal] = chooseJavaBigDecimalScale(minScale = 34) - /** - * See chooseBigDecimalScale for comments. - */ + /** See chooseBigDecimalScale for comments. + */ private[this] def chooseJavaBigDecimalScale(minScale: Int): Choose[JavaDecimal] = new Choose[JavaDecimal] { def choose(low: JavaDecimal, high: JavaDecimal): Gen[JavaDecimal] = - (low.compareTo(high)) match { - case n if n > 0 => throw new IllegalBoundsError(low, high) - case 0 => Gen.const(low) - case _ => /* n < 0 */ - val s = (low.scale max high.scale) max minScale - val x = if (low.scale < s) low.setScale(s) else low - val y = if (high.scale < s) high.setScale(s) else high - chooseBigInteger - .choose(x.unscaledValue, y.unscaledValue) - .map(n => new JavaDecimal(n, s)) - } + (low.compareTo(high)) match { + case n if n > 0 => throw new IllegalBoundsError(low, high) + case 0 => Gen.const(low) + case _ => /* n < 0 */ + val s = (low.scale max high.scale) max minScale + val x = if (low.scale < s) low.setScale(s) else low + val y = if (high.scale < s) high.setScale(s) else high + chooseBigInteger + .choose(x.unscaledValue, y.unscaledValue) + .map(n => new JavaDecimal(n, s)) + } } - /** 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) */ + /** 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): Gen[U] = @@ -803,7 +762,6 @@ object Gen extends GenArities with GenVersionSpecific { } } - //// Various Generator Combinators //// /** A generator that always generates the given value */ @@ -812,18 +770,11 @@ object Gen extends GenArities with GenVersionSpecific { /** A generator that never generates a value */ def fail[T]: Gen[T] = gen((_, seed) => failed[T](seed)) - - /** - * A fixed point generator. This is useful for making recursive structures - * e.g. - * - * Gen.recursive[List[Int]] { recurse => - * Gen.choose(0, 10).flatMap { idx => - * if (idx < 5) recurse.map(idx :: _) - * else Gen.const(idx :: Nil) - * } - * } - */ + /** A fixed point generator. This is useful for making recursive structures e.g. + * + * Gen.recursive[List[Int]] { recurse => Gen.choose(0, 10).flatMap { idx => if (idx < 5) recurse.map(idx :: _) else + * Gen.const(idx :: Nil) } } + */ def recursive[A](fn: Gen[A] => Gen[A]): Gen[A] = { lazy val result: Gen[A] = lzy(fn(result)) result @@ -836,18 +787,18 @@ object Gen extends GenArities with GenVersionSpecific { val seed = seed0 } - /** A generator that generates a random value in the given (inclusive) - * range. If the range is invalid, an IllegalBoundsError exception will be - * thrown. */ + /** A generator that generates a random value in the given (inclusive) range. If the range is invalid, an + * IllegalBoundsError exception will be thrown. + */ 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] = { + /** 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] = { val g = gen { (p, seed) => gs.foldLeft(r(Some(Vector.empty[T]), seed)) { - case (rs,g) => + case (rs, g) => val rt = g.doApply(p, rs.seed) rt.flatMap(t => rs.map(_ :+ t)).withSeed(rt.seed) } @@ -855,21 +806,19 @@ object Gen extends GenArities with GenVersionSpecific { g.map(b.fromIterable) } - /** Monadic recursion on Gen - * This is a stack-safe loop that is the same as: - * - * {{{ - * - * fn(a).flatMap { - * case Left(a) => tailRec(a)(fn) - * case Right(b) => Gen.const(b) - * } - * - * }}} - * - * which is useful for doing monadic loops without blowing up the - * stack - */ + /** Monadic recursion on Gen This is a stack-safe loop that is the same as: + * + * {{{ + * + * fn(a).flatMap { + * case Left(a) => tailRec(a)(fn) + * case Right(b) => Gen.const(b) + * } + * + * }}} + * + * which is useful for doing monadic loops without blowing up the stack + */ def tailRecM[A, B](a0: A)(fn: A => Gen[Either[A, B]]): Gen[B] = { @tailrec def tailRecMR(a: A, seed: Seed, labs: Set[String])(fn: (A, Seed) => R[Either[A, B]]): R[B] = { @@ -889,15 +838,17 @@ object Gen extends GenArities with GenVersionSpecific { } } - /** Wraps a generator lazily. The given parameter is only evaluated once, - * and not until the wrapper generator is evaluated. */ + /** 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, seed) => h.doApply(p, seed) } } - /** Wraps a generator for later evaluation. The given parameter is - * evaluated each time the wrapper generator is evaluated. */ + /** Wraps a generator for later evaluation. The given parameter is evaluated each time the wrapper generator is + * evaluated. + */ def delay[T](g: => Gen[T]): Gen[T] = gen { (p, seed) => g.doApply(p, seed) } @@ -925,8 +876,9 @@ object Gen extends GenArities with GenVersionSpecific { } /** Picks a random value from a list. - * @todo Remove this overloaded method in the next major release. See #438. - */ + * @todo + * Remove this overloaded method in the next major release. See #438. + */ def oneOf[T](xs: Seq[T]): Gen[T] = oneOf(xs: Iterable[T]) @@ -968,26 +920,24 @@ object Gen extends GenArities with GenVersionSpecific { } } - /** 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)) - + /** 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 buildableOfN[C,T](n: Int, g: Gen[T])(implicit - evb: Buildable[T,C], evt: C => Traversable[T] + /** 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 buildableOfN[C, T](n: Int, g: Gen[T])(implicit + evb: Buildable[T, C], + evt: C => Traversable[T] ): Gen[C] = { require(n >= 0, s"invalid size given: $n") new Gen[C] { @@ -1014,76 +964,80 @@ object Gen extends GenArities with GenVersionSpecific { } } - /** 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 buildableOf[C,T](g: Gen[T])(implicit - evb: Buildable[T,C], evt: C => Traversable[T] + /** 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 buildableOf[C, T](g: Gen[T])(implicit + evb: Buildable[T, C], + evt: C => Traversable[T] ): Gen[C] = sized(s => choose(0, Integer.max(s, 0))) .flatMap(n => buildableOfN(n, g)(evb, evt)) - /** 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 nonEmptyBuildableOf[C,T](g: Gen[T])(implicit - evb: Buildable[T,C], evt: C => Traversable[T] + /** 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 nonEmptyBuildableOf[C, T](g: Gen[T])(implicit + evb: Buildable[T, C], + evt: C => Traversable[T] ): Gen[C] = sized(s => choose(1, Integer.max(s, 1))) .flatMap(n => buildableOfN(n, g)(evb, evt)) /** A convenience method for calling `buildableOfN[C[T],T](n,g)`. */ - def containerOfN[C[_],T](n: Int, g: Gen[T])(implicit - evb: Buildable[T,C[T]], evt: C[T] => Traversable[T] + def containerOfN[C[_], T](n: Int, g: Gen[T])(implicit + evb: Buildable[T, C[T]], + evt: C[T] => Traversable[T] ): Gen[C[T]] = buildableOfN[C[T], T](n, g)(evb, evt) /** A convenience method for calling `buildableOf[C[T],T](g)`. */ - def containerOf[C[_],T](g: Gen[T])(implicit - evb: Buildable[T,C[T]], evt: C[T] => Traversable[T] + def containerOf[C[_], T](g: Gen[T])(implicit + evb: Buildable[T, C[T]], + evt: C[T] => Traversable[T] ): Gen[C[T]] = buildableOf[C[T], T](g)(evb, evt) /** A convenience method for calling `nonEmptyBuildableOf[C[T],T](g)`. */ - def nonEmptyContainerOf[C[_],T](g: Gen[T])(implicit - evb: Buildable[T,C[T]], evt: C[T] => Traversable[T] + def nonEmptyContainerOf[C[_], T](g: Gen[T])(implicit + evb: Buildable[T, C[T]], + evt: C[T] => Traversable[T] ): Gen[C[T]] = nonEmptyBuildableOf[C[T], T](g)(evb, evt) - /** Generates a list of random length. The maximum length depends on the - * size parameter. This method is equal to calling - * `containerOf[List,T](g)`. */ + /** 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]) = buildableOf[List[T], 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)`. */ + /** 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]) = nonEmptyBuildableOf[List[T], T](g) - /** Generates a list with at most the given number of elements. This method - * is equal to calling `containerOfN[List,T](n,g)`. */ + /** Generates a list with at most the given number of elements. This method is equal to calling + * `containerOfN[List,T](n,g)`. + */ def listOfN[T](n: Int, g: Gen[T]) = buildableOfN[List[T], T](n, g) - /** Generates a map of random length. The maximum length depends on the - * size parameter. This method is equal to calling - * containerOf[Map,(T,U)](g). */ + /** Generates a map of random length. The maximum length depends on the size parameter. This method is equal to + * calling containerOf[Map,(T,U)](g). + */ def mapOf[T, U](g: => Gen[(T, U)]) = buildableOf[Map[T, U], (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 - * nonEmptyContainerOf[Map,(T,U)](g). */ - def nonEmptyMap[T,U](g: => Gen[(T,U)]) = nonEmptyBuildableOf[Map[T, U],(T, U)](g) - - /** Generates a map with at most the given number of elements. This method - * is equal to calling containerOfN[Map,(T,U)](n,g). */ - def mapOfN[T,U](n: Int, g: Gen[(T, U)]) = buildableOfN[Map[T, U],(T, U)](n, g) - - /** - * Generates an infinite stream. - * - * Failures in the underlying generator may terminate the stream. - * Otherwise it will continue forever. - */ + /** Generates a non-empty map of random length. The maximum length depends on the size parameter. This method is equal + * to calling nonEmptyContainerOf[Map,(T,U)](g). + */ + def nonEmptyMap[T, U](g: => Gen[(T, U)]) = nonEmptyBuildableOf[Map[T, U], (T, U)](g) + + /** Generates a map with at most the given number of elements. This method is equal to calling + * containerOfN[Map,(T,U)](n,g). + */ + def mapOfN[T, U](n: Int, g: Gen[(T, U)]) = buildableOfN[Map[T, U], (T, U)](n, g) + + /** Generates an infinite stream. + * + * Failures in the underlying generator may terminate the stream. Otherwise it will continue forever. + */ def infiniteStream[T](g: => Gen[T]): Gen[Stream[T]] = { val attemptsPerItem = 10 def unfold(p: P, seed: Seed, attemptsLeft: Int): Stream[T] = @@ -1104,26 +1058,26 @@ object Gen extends GenArities with GenVersionSpecific { /** 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)) + 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: _*)) + choose(0, gs.length + 2).flatMap(pick(_, g1, g2, gs: _*)) /** A generator that picks at least one element from a list */ def atLeastOne[T](l: Iterable[T]) = { require(l.size > 0, "There has to be at least one option to choose from") - choose(1,l.size).flatMap(pick(_,l)) + choose(1, l.size).flatMap(pick(_, l)) } /** A generator that picks at least one element from a list */ def atLeastOne[T](g1: Gen[T], g2: Gen[T], gs: Gen[T]*) = - choose(1, gs.length+2).flatMap(pick(_, g1, g2, gs: _*)) + choose(1, gs.length + 2).flatMap(pick(_, g1, g2, gs: _*)) /** A generator that randomly picks a given number of elements from a list - * - * The elements are not guaranteed to be permuted in random order. - */ + * + * The elements are not guaranteed to be permuted in random order. + */ def pick[T](n: Int, l: Iterable[T]): Gen[collection.Seq[T]] = { if (n > l.size || n < 0) throw new IllegalArgumentException(s"invalid choice: $n") else if (n == 0) Gen.const(Nil) @@ -1149,23 +1103,22 @@ object Gen extends GenArities with GenVersionSpecific { } /** A generator that randomly picks a given number of elements from a list - * - * The elements are not guaranteed to be permuted in random order. - */ + * + * The elements are not guaranteed to be permuted in random order. + */ def pick[T](n: Int, g1: Gen[T], g2: Gen[T], gn: Gen[T]*): Gen[Seq[T]] = pick(n, g1 +: g2 +: gn).flatMap(sequence[Seq[T], T](_)) - /** 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,R0](f: T => R0)(implicit a: Arbitrary[T]): Gen[R0] = + /** 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, R0](f: T => R0)(implicit a: Arbitrary[T]): Gen[R0] = arbitrary[T].map(f) /** Creates a Function0 generator. */ def function0[A](g: Gen[A]): Gen[() => A] = g.map(a => () => a) - //// Character Generators //// private def charSample(cs: Array[Char]): Gen[Char] = @@ -1206,8 +1159,8 @@ object Gen extends GenArities with GenVersionSpecific { val asciiPrintableChar: Gen[Char] = charSample((32.toChar to 126.toChar).toArray) - /** Generates a character that can represent a valid hexadecimal digit. This - * includes both upper and lower case values. + /** Generates a character that can represent a valid hexadecimal digit. This includes both upper and lower case + * values. */ val hexChar: Gen[Char] = charSample("0123456789abcdef0123456789ABCDEF".toArray) @@ -1251,8 +1204,8 @@ object Gen extends GenArities with GenVersionSpecific { sized(s => choose(1, Integer.max(s, 1))) .flatMap(n => stringOfN(n, gc)) - /** Generates a string that starts with a lower-case alpha character, - * and only contains alphanumerical characters */ + /** Generates a string that starts with a lower-case alpha character, and only contains alphanumerical characters + */ val identifier: Gen[String] = gen { (p, seed0) => val (n, seed1) = Gen.mkSize(p, seed0) @@ -1290,46 +1243,40 @@ object Gen extends GenArities with GenVersionSpecific { val asciiPrintableStr: Gen[String] = stringOf(asciiPrintableChar) - /** Generates a string that can represent a valid hexadecimal digit. This - * includes both upper and lower case values. + /** Generates a string that can represent a valid hexadecimal digit. This includes both upper and lower case values. */ val hexStr: Gen[String] = stringOf(hexChar) //// Number Generators //// - /** - * Generate a uniformly-distributed Long. - * - * This method has an equally likely method of generating every - * possible Long value. - */ + /** Generate a uniformly-distributed Long. + * + * This method has an equally likely method of generating every possible Long value. + */ val long: Gen[Long] = gen { (_, s0) => val (n, s1) = s0.long r(Some(n), s1) } - /** - * Generate a Double uniformly-distributed in [0, 1). - * - * This method will generate one of 2^53 distinct Double values in - * the unit interval. - */ + /** Generate a Double uniformly-distributed in [0, 1). + * + * This method will generate one of 2^53 distinct Double values in the unit interval. + */ val double: Gen[Double] = gen { (_, s0) => val (x, s1) = s0.double r(Some(x), s1) } - /** - * Generates a Boolean which has the given chance to be true. - * - * - prob(1.0) is always true - * - prob(0.5) is true 50% of the time - * - prob(0.1) is true 10% of the time - * - prob(0.0) is never true - */ + /** Generates a Boolean which has the given chance to be true. + * + * - prob(1.0) is always true + * - prob(0.5) is true 50% of the time + * - prob(0.1) is true 10% of the time + * - prob(0.0) is never true + */ def prob(chance: Double): Gen[Boolean] = if (chance <= 0.0) Gen.const(false) else if (chance >= 1.0) Gen.const(true) @@ -1338,15 +1285,13 @@ object Gen extends GenArities with GenVersionSpecific { r(Some(x < chance), s1) } - /** - * Generates Double values according to the given gaussian - * distribution, specified by its mean and standard deviation. - * - * Gaussian distributions are also called normal distributions. - * - * The range of values is theoretically (-∞, ∞) but 99.7% of all - * values will be contained within (mean ± 3 * stdDev). - */ + /** Generates Double values according to the given gaussian distribution, specified by its mean and standard + * deviation. + * + * Gaussian distributions are also called normal distributions. + * + * The range of values is theoretically (-∞, ∞) but 99.7% of all values will be contained within (mean ± 3 * stdDev). + */ def gaussian(mean: Double, stdDev: Double): Gen[Double] = { def loop(s0: Seed): R[Double] = { val (x0, s1) = s0.double @@ -1365,14 +1310,12 @@ object Gen extends GenArities with GenVersionSpecific { gen((_, seed) => loop(seed)) } - /** - * Generates Double values according to the given exponential - * distribution, specified by its rate parameter. - * - * The mean and standard deviation are both equal to 1/rate. - * - * The range of values is [0, ∞). - */ + /** Generates Double values according to the given exponential distribution, specified by its rate parameter. + * + * The mean and standard deviation are both equal to 1/rate. + * + * The range of values is [0, ∞). + */ def exponential(rate: Double): Gen[Double] = { require(rate > 0.0, s"rate must be positive (got: $rate)") val mean = 1.0 / rate @@ -1382,17 +1325,14 @@ object Gen extends GenArities with GenVersionSpecific { } } - /** - * Generates Int values according to the given geometric - * distribution, specified by its mean. - * - * This distribution represents the expected number of failures - * before a successful test, where the probability of a successful - * test is p = 1 / (mean + 1). - * - * The ideal range of values is [0, ∞), although the largest value - * that can be produced here is 2147483647 (Int.MaxValue). - */ + /** Generates Int values according to the given geometric distribution, specified by its mean. + * + * This distribution represents the expected number of failures before a successful test, where the probability of a + * successful test is p = 1 / (mean + 1). + * + * The ideal range of values is [0, ∞), although the largest value that can be produced here is 2147483647 + * (Int.MaxValue). + */ def geometric(mean: Double): Gen[Int] = { require(mean > 0.0, s"mean must be positive (got: $mean)") val p = 1.0 / (mean + 1.0) @@ -1403,16 +1343,13 @@ object Gen extends GenArities with GenVersionSpecific { } } - /** - * Generates Int values according to the given Poisson distribution, - * specified by its rate parameters. - * - * The mean equals the rate; the standard deviation is sqrt(rate). - * - * In principle any positive value is a valid rate parameter. - * However, our method of generating values cannot handle large - * rates, so we require rate <= 745. - */ + /** Generates Int values according to the given Poisson distribution, specified by its rate parameters. + * + * The mean equals the rate; the standard deviation is sqrt(rate). + * + * In principle any positive value is a valid rate parameter. However, our method of generating values cannot handle + * large rates, so we require rate <= 745. + */ def poisson(rate: Double): Gen[Int] = { require(0 < rate && rate <= 745.0, s"rate must be between 0 and 745 (got $rate)") val L = Math.exp(-rate) @@ -1427,16 +1364,13 @@ object Gen extends GenArities with GenVersionSpecific { gen((_, s) => loop(s, 0, 1.0)) } - /** - * Generates Int values according to the given binomial - * distribution, specified by the number of trials to conduct, and - * the probability of a true test. - * - * This distribution counts the number of trials which were - * successful according to a given test probability. - * - * The range of values is [0, trials]. - */ + /** Generates Int values according to the given binomial distribution, specified by the number of trials to conduct, + * and the probability of a true test. + * + * This distribution counts the number of trials which were successful according to a given test probability. + * + * The range of values is [0, trials]. + */ def binomial(test: Gen[Boolean], trials: Int): Gen[Int] = { def loop(ps: Gen.Parameters, s: Seed, i: Int, n: Int): R[Int] = if (i >= trials) { @@ -1449,9 +1383,8 @@ object Gen extends GenArities with GenVersionSpecific { gen((ps, s) => loop(ps, s, 0, 0)) } - - /** Generates positive numbers of uniform distribution, with an - * upper bound of the generation size parameter. */ + /** 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._ num match { @@ -1460,16 +1393,18 @@ object Gen extends GenArities with GenVersionSpecific { } } - /** Generates negative numbers of uniform distribution, with an - * lower bound of the negated generation size parameter. */ + /** 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] = posNum.map(num.negate(_)) - /** 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. */ + /** 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] + implicit + num: Numeric[T], + c: Choose[T] ): Gen[T] = { import num._ val basics = List(minT, maxT, zero, one, -one) @@ -1481,17 +1416,17 @@ object Gen extends GenArities with GenVersionSpecific { frequency(allGens: _*) } - //// Misc Generators //// /** Generates a version 4 (random) UUID. */ - lazy val uuid: Gen[UUID] = for { // FIXME: Remove lazy - l1 <- Gen.choose(Long.MinValue, Long.MaxValue) - l2 <- Gen.choose(Long.MinValue, Long.MaxValue) - y <- Gen.oneOf('8', '9', 'a', 'b') - } yield UUID.fromString( - new UUID(l1,l2).toString.updated(14, '4').updated(19, y) - ) + lazy val uuid: Gen[UUID] = + for { // FIXME: Remove lazy + l1 <- Gen.choose(Long.MinValue, Long.MaxValue) + l2 <- Gen.choose(Long.MinValue, Long.MaxValue) + y <- Gen.oneOf('8', '9', 'a', 'b') + } yield UUID.fromString( + new UUID(l1, l2).toString.updated(14, '4').updated(19, y) + ) lazy val calendar: Gen[Calendar] = { // FIXME: Remove lazy import Calendar._ @@ -1526,20 +1461,22 @@ object Gen extends GenArities with GenVersionSpecific { } val beginningOfDayGen: Gen[Calendar] = - calendar.map(c => adjust(c) { c => - c.set(HOUR_OF_DAY, 0) - c.set(MINUTE, 0) - c.set(SECOND, 0) - c.set(MILLISECOND, 0) - }) + calendar.map(c => + adjust(c) { c => + c.set(HOUR_OF_DAY, 0) + c.set(MINUTE, 0) + c.set(SECOND, 0) + c.set(MILLISECOND, 0) + }) val endOfDayGen: Gen[Calendar] = - calendar.map(c => adjust(c) { c => - c.set(HOUR_OF_DAY, 23) - c.set(MINUTE, 59) - c.set(SECOND, 59) - c.set(MILLISECOND, 999) - }) + calendar.map(c => + adjust(c) { c => + c.set(HOUR_OF_DAY, 23) + c.set(MINUTE, 59) + c.set(SECOND, 59) + c.set(MILLISECOND, 999) + }) val firstDayOfYearGen: Gen[Calendar] = for { c <- calendar; y <- yearGen(c) } yield adjust(c)(_.set(y, JANUARY, 1)) @@ -1564,7 +1501,8 @@ object Gen extends GenArities with GenVersionSpecific { (1, endOfDayGen), (1, firstDayOfMonthGen), (1, lastDayOfMonthGen), - (7, calendar)) + (7, calendar) + ) } val finiteDuration: Gen[FiniteDuration] = @@ -1572,12 +1510,11 @@ object Gen extends GenArities with GenVersionSpecific { // duration that cannot be negated. chooseNum(Long.MinValue + 1, Long.MaxValue).map(Duration.fromNanos) - /** - * Generates instance of Duration. - * - * In addition to `FiniteDuration` values, this can generate `Duration.Inf`, - * `Duration.MinusInf`, and `Duration.Undefined`. - */ + /** Generates instance of Duration. + * + * In addition to `FiniteDuration` values, this can generate `Duration.Inf`, `Duration.MinusInf`, and + * `Duration.Undefined`. + */ val duration: Gen[Duration] = frequency( 1 -> const(Duration.Inf), 1 -> const(Duration.MinusInf), diff --git a/core/shared/src/main/scala/org/scalacheck/Prop.scala b/core/shared/src/main/scala/org/scalacheck/Prop.scala index 08cc3b0d..dedb1ec8 100644 --- a/core/shared/src/main/scala/org/scalacheck/Prop.scala +++ b/core/shared/src/main/scala/org/scalacheck/Prop.scala @@ -9,12 +9,13 @@ package org.scalacheck +import scala.annotation.tailrec + import rng.Seed import util.{Pretty, ConsoleReporter} -import scala.annotation.tailrec -/** Helper class to satisfy ScalaJS compilation. Do not use this directly, - * use `Prop.apply` instead. */ +/** Helper class to satisfy ScalaJS compilation. Do not use this directly, use `Prop.apply` instead. + */ sealed class PropFromFun(f: Gen.Parameters => Prop.Result) extends Prop { def apply(prms: Gen.Parameters) = f(prms) } @@ -40,7 +41,7 @@ sealed abstract class Prop extends Serializable { self => res } - @deprecated(message="Please use useSeed which only takes a seed. name is, and has been, unused.", since="1.18.0") + @deprecated(message = "Please use useSeed which only takes a seed. name is, and has been, unused.", since = "1.18.0") def useSeed(name: String, seed: Seed): Prop = useSeed(seed) @@ -60,50 +61,46 @@ sealed abstract class Prop extends Serializable { self => } def combine(p: => Prop)(f: (Result, Result) => Result) = - for(r1 <- this; r2 <- p) yield f(r1,r2) + 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. Should only be used when running - * tests interactively within the Scala REPL.*/ + /** Convenience method that checks this property with the given parameters and reports the result on the console. + * Should only be used when running tests interactively within the Scala REPL. + */ def check(prms: Test.Parameters): Unit = Test.check_( - if(prms.testCallback.isInstanceOf[ConsoleReporter]) prms + 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. Should only be used when running - * tests interactively within the Scala REPL. - * - * The default test parameters - * ([[Test.Parameters.default]]) are used for the check. */ + /** Convenience method that checks this property and reports the result on the console. Should only be used when + * running tests interactively within the Scala REPL. + * + * 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. Should only be used when running - * tests interactively within the Scala REPL. - * - * 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) - * } - * }}} - */ + /** Convenience method that checks this property and reports the result on the console. Should only be used when + * running tests interactively within the Scala REPL. + * + * 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 makes it possible to use this property - * as an application that checks itself on execution. Calls `System.exit` - * with a non-zero exit code if the property check fails. */ + /** Convenience method that makes it possible to use this property as an application that checks itself on execution. + * Calls `System.exit` with a non-zero exit code if the property check fails. + */ def main(args: Array[String]): Unit = { val ret = Test.CmdLineParser.parseParams(args) match { case (applyCmdParams, Nil) => @@ -118,36 +115,34 @@ sealed abstract class Prop extends Serializable { self => if (ret != 0) System.exit(ret) } - /** 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. */ + /** 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(p)(_ && _) - /** Returns a new property that holds if either this - * or the given property (or both) hold. */ + /** Returns a new property that holds if either this or the given property (or both) hold. + */ def ||(p: => Prop) = combine(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. */ + /** 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(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)) } + 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. */ + /** 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) + mergeRes(r1, r2, if (r1.status == r2.status) True else False) } } @@ -178,12 +173,12 @@ object Prop { /** A property argument */ case class Arg[+T]( - label: String, - arg: T, - shrinks: Int, - origArg: T, - prettyArg: Pretty, - prettyOrigArg: Pretty + label: String, + arg: T, + shrinks: Int, + origArg: T, + prettyArg: Pretty, + prettyOrigArg: Pretty ) private[scalacheck] def mergeRes(x: Result, y: Result, st: Status) = @@ -196,10 +191,10 @@ object Prop { /** 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 + status: Status, + args: List[Arg[Any]] = Nil, + collected: Set[Any] = Set.empty, + labels: Set[String] = Set.empty ) { def success = status match { case True => true @@ -215,48 +210,48 @@ object Prop { def proved = status == Proof - def addArg(a: Arg[Any]) = copy(args = a::args) + def addArg(a: Arg[Any]) = copy(args = a :: args) - def collect(x: Any) = copy(collected = collected+x) + def collect(x: Any) = copy(collected = collected + x) - def label(l: String) = copy(labels = labels+l) + def label(l: String) = copy(labels = labels + l) def &&(r: Result) = (this.status, r.status) match { - case (Exception(_),_) => this - case (_,Exception(_)) => r + case (Exception(_), _) => this + case (_, Exception(_)) => r - case (False,_) => this - case (_,False) => r + case (False, _) => this + case (_, False) => r - case (Undecided,_) => this - case (_,Undecided) => r + case (Undecided, _) => this + case (_, Undecided) => r - case (_,Proof) => mergeRes(this, r, this.status) - case (Proof,_) => mergeRes(this, r, r.status) + case (_, Proof) => mergeRes(this, r, this.status) + case (Proof, _) => mergeRes(this, r, r.status) - case (True,True) => mergeRes(this, r, True) + case (True, True) => mergeRes(this, r, True) } def ||(r: Result) = (this.status, r.status) match { - case (Exception(_),_) => this - case (_,Exception(_)) => r + case (Exception(_), _) => this + case (_, Exception(_)) => r - case (False,False) => mergeRes(this, r, False) - case (False,_) => r - case (_,False) => this + case (False, False) => mergeRes(this, r, False) + case (False, _) => r + case (_, False) => this - case (Proof,_) => this - case (_,Proof) => r + case (Proof, _) => this + case (_, Proof) => r - case (True,_) => this - case (_,True) => r + case (True, _) => this + case (_, True) => r - case (Undecided,Undecided) => mergeRes(this, r, Undecided) + case (Undecided, Undecided) => mergeRes(this, r, Undecided) } def ++(r: Result) = (this.status, r.status) match { - case (Exception(_),_) => this - case (_,Exception(_)) => r + case (Exception(_), _) => this + case (_, Exception(_)) => r case (_, Undecided) => this case (Undecided, _) => r @@ -271,15 +266,15 @@ object Prop { } def ==>(r: Result) = (this.status, r.status) match { - case (Exception(_),_) => this - case (_,Exception(_)) => r + case (Exception(_), _) => this + case (_, Exception(_)) => r - case (False,_) => mergeRes(this, r, Undecided) + case (False, _) => mergeRes(this, r, Undecided) - case (Undecided,_) => this + case (Undecided, _) => this - case (Proof,_) => mergeRes(this, r, r.status) - case (True,_) => mergeRes(this, r, r.status) + case (Proof, _) => mergeRes(this, r, r.status) + case (True, _) => mergeRes(this, r, r.status) } } @@ -307,64 +302,71 @@ object Prop { /** Create a new property from the given function. */ def apply(f: Gen.Parameters => Result): Prop = new PropFromFun(prms => - try f(prms) catch { + 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(_ => r) /** Create a property from a boolean value */ - def apply(b: Boolean): Prop = if(b) proved else falsified + 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. */ + /** A collection of property operators on `Any` values. Import [[Prop.AnyOperators]] to make the operators available. + */ class ExtendedAny[T](x: => T)(implicit ev: T => Pretty) { + /** See [[Prop.imply]] */ - def imply(f: PartialFunction[T,Prop]) = Prop.imply(x,f) + def imply(f: PartialFunction[T, Prop]) = Prop.imply(x, f) + /** See [[Prop.iff]] */ - def iff(f: PartialFunction[T,Prop]) = Prop.iff(x,f) + 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.propBoolean]] to make the operators available. - * The availability of this class as an implicit via - * `BooleanOperators` was removed in 1.15.0. */ + /** A collection of property operators on `Boolean` values. Import [[Prop.propBoolean]] to make the operators + * available. The availability of this class as an implicit via `BooleanOperators` was removed in 1.15.0. + */ 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 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](x: => T)(implicit ev: T => Pretty): ExtendedAny[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. */ - @deprecated("Please import Prop.propBoolean instead", since="1.14.1") + /** 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. + */ + @deprecated("Please import Prop.propBoolean instead", since = "1.14.1") def BooleanOperators(b: => Boolean): ExtendedBoolean = 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 { @@ -372,7 +374,6 @@ object Prop { case _ => r } - // Property combinators /** A property that never is proved or falsified */ @@ -393,19 +394,20 @@ object Prop { /** A property that denotes an exception */ lazy val exception: Prop = exception(null) - /** Create a property that compares two values. If the values aren't equal, - * the property will fail and report that first value doesn't match the - * expected (second) value. */ + /** Create a property that compares two 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 :| { + 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 + "Expected " + exp + " but got " + act } - /** Create a property that compares two values. If the values aren't equal, - * the property will fail and report that second value doesn't match the - * expected (first) value. */ + /** Create a property that compares two 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 */ @@ -417,49 +419,51 @@ object Prop { } /** Implication with several conditions */ - def imply[T](x: T, f: PartialFunction[T,Prop]): Prop = secure { - if(f.isDefinedAt(x)) f(x) else undecided + 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 + /** 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 */ + /** 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 */ + /** 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 */ + /** A property that holds if at least one of the given generators fails generating a value + */ def someFailing[T](gs: Seq[Gen[T]]): Prop = - atLeastOne(gs.map(_ == Gen.fail):_*) + atLeastOne(gs.map(_ == Gen.fail): _*) - /** A property that holds iff none of the given generators - * fails generating a value */ + /** A property that holds iff none of the given generators fails generating a value + */ def noneFailing[T](gs: Seq[Gen[T]]): Prop = - all(gs.map(_ !== Gen.fail):_*) + all(gs.map(_ !== Gen.fail): _*) - /** Returns true if the given statement throws an exception - * of the specified type */ + /** 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 } + try { x; false } + catch { case e if c.isInstance(e) => true } /** Collect data for presentation in test report */ @deprecated("Use Prop.forAll(t => Prop.collect(t)(...)) instead of Prop.forAll(Prop.collect(t => ...))", "1.15.0") - def collect[T, P](f: T => P)(implicit ev: P => Prop): T => Prop = t => Prop { prms => - val prop = ev(f(t)) - prop(prms).collect(t) - } + def collect[T, P](f: T => P)(implicit ev: P => Prop): T => Prop = t => + Prop { prms => + val prop = ev(f(t)) + prop(prms).collect(t) + } /** Collect data for presentation in test report */ def collect[T](t: T)(prop: Prop) = Prop { prms => @@ -468,66 +472,60 @@ object Prop { /** Collect data for presentation in test report */ def classify(c: => Boolean, ifTrue: Any)(prop: Prop): Prop = - if(c) collect(ifTrue)(prop) else collect(())(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) + if (c) collect(ifTrue)(prop) else collect(ifFalse)(prop) - /** Wraps and protects a property, turning exceptions thrown - * by the property into test failures. */ + /** Wraps and protects a property, turning exceptions thrown by the property into test failures. + */ def secure[P](p: => P)(implicit ev: P => Prop): Prop = - try ev(p) catch { case e: Throwable => exception(e) } + try ev(p) + catch { case e: Throwable => exception(e) } - /** Wraps a property to delay its evaluation. The given parameter is - * evaluated each time the wrapper property is evaluated. */ + /** Wraps a property to delay its evaluation. The given parameter is evaluated each time the wrapper property is + * evaluated. + */ def delay(p: => Prop): Prop = Prop(params => p(params)) - /** Wraps a property lazily. The given parameter is only evaluated once, - * and not until the wrapper property is evaluated. */ + /** Wraps a property lazily. The given parameter is only evaluated once, and not until the wrapper property is + * evaluated. + */ def lzy(p: => Prop): Prop = { lazy val q = p Prop(params => q(params)) } - /** Wraps and protects a property, delaying its evaluation - * and turning exceptions into test failures. */ + /** Wraps and protects a property, delaying its evaluation and turning exceptions into test failures. + */ def protect(p: => Prop): Prop = delay(secure(p)) /** Existential quantifier for an explicit generator. */ - def exists[A,P](f: A => P)(implicit - pv: P => Prop, - pp: A => Pretty, - aa: Arbitrary[A] + def exists[A, P](f: A => P)(implicit + pv: P => Prop, + pp: A => Pretty, + aa: Arbitrary[A] ): Prop = exists(aa.arbitrary)(f) - /** - * This handles situations where we have a starting seed in our - * parameters. - * - * If we do, then we remove it from parameters and return it. If - * not, we create a new random seed. The new parameters from this - * method should be used with all the generation that this prop - * needs itself. - * - * Note that if this Prop needs to evaluate other Props (e.g. in - * forAll), you should make sure *not* to use the parameters - * returned from this method. We need for all Props evaluated by - * this one to behave deterministically if this Prop was given a - * seed. In that case you should use `slideSeed` to update the - * parameters. - */ + /** This handles situations where we have a starting seed in our parameters. + * + * If we do, then we remove it from parameters and return it. If not, we create a new random seed. The new parameters + * from this method should be used with all the generation that this prop needs itself. + * + * Note that if this Prop needs to evaluate other Props (e.g. in forAll), you should make sure *not* to use the + * parameters returned from this method. We need for all Props evaluated by this one to behave deterministically if + * this Prop was given a seed. In that case you should use `slideSeed` to update the parameters. + */ def startSeed(prms: Gen.Parameters): (Gen.Parameters, Seed) = prms.initialSeed match { case Some(seed) => (prms.withNoInitialSeed, seed) case None => (prms, Seed.random()) } - /** - * - */ + /** */ def slideSeed(prms: Gen.Parameters): Gen.Parameters = prms.initialSeed match { case Some(seed) => prms.withInitialSeed(seed.slide) @@ -535,9 +533,9 @@ object Prop { } /** Existential quantifier for an explicit generator. */ - def exists[A,P](g: Gen[A])(f: A => P)(implicit - pv: P => Prop, - pp: A => Pretty + def exists[A, P](g: Gen[A])(f: A => P)(implicit + pv: P => Prop, + pp: A => Pretty ): Prop = Prop { prms0 => val (prms, seed) = startSeed(prms0) val gr = g.doApply(prms, seed) @@ -546,7 +544,7 @@ object Prop { case Some(x) => val p = secure(f(x)) val labels = gr.labels.mkString(",") - val r = p(slideSeed(prms0)).addArg(Arg(labels,x,0,x,pp(x),pp(x))) + val r = p(slideSeed(prms0)).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) @@ -555,13 +553,15 @@ object Prop { } } - /** 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 + /** 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 { prms0 => val (prms, seed) = startSeed(prms0) val gr = g1.doApply(prms, seed) @@ -570,445 +570,714 @@ object Prop { case Some(x) => val p = secure(f(x)) val labels = gr.labels.mkString(",") - provedToTrue(p(slideSeed(prms0))).addArg(Arg(labels,x,0,x,pp1(x),pp1(x))) + provedToTrue(p(slideSeed(prms0))).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))) + /** 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 + 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 + 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 + 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 + 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 + 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 + 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 + 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], + 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 + 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) + 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 { prms0 => + /** 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 { prms0 => + val (prms, seed) = startSeed(prms0) + val gr = g.doApply(prms, seed) + val labels = gr.labels.mkString(",") - val (prms, seed) = startSeed(prms0) - val gr = g.doApply(prms, seed) - val labels = gr.labels.mkString(",") + def result(x: T) = { + val p = secure(pv(f(x))) + provedToTrue(p(slideSeed(prms0))) + } - def result(x: T) = { - val p = secure(pv(f(x))) - provedToTrue(p(slideSeed(prms0))) - } + /* + * Returns the first failed result in Left or success in Right. + */ + def getFirstFailure( + xs: Stream[T], + exceptionFilter: Option[Class[_ <: Throwable]] + ): Either[(T, Result), (T, Result)] = { + assert(!xs.isEmpty, "Stream cannot be empty") + val results = xs.map(x => (x, result(x))) + results.dropWhile { + case (_, Result(Exception(e), _, _, _)) => !exceptionFilter.contains(e.getClass) + case (_, r) => !r.failure + }.headOption match { + case None => Right(results.head) + case Some(xr) => Left(xr) + } + } - /* - * Returns the first failed result in Left or success in Right. - */ - def getFirstFailure(xs: Stream[T], exceptionFilter: Option[Class[_ <: Throwable]]): Either[(T,Result),(T,Result)] = { - assert(!xs.isEmpty, "Stream cannot be empty") - val results = xs.map(x => (x, result(x))) - results.dropWhile { - case (_, Result(Exception(e), _, _, _)) => !exceptionFilter.contains(e.getClass) - case (_, r) => !r.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) + val res = r.addArg(Arg(labels, x, shrinks, orig, pp(x), pp(orig))) + val originalException = Some(r.status).collect { case Prop.Exception(e) => e.getClass } + if (xs.isEmpty) res + else getFirstFailure(xs, originalException) match { + case Right(_) => res + case Left((x2, r2)) => shrinker(x2, replOrig(r, r2), shrinks + 1, orig) + } } - } - def shrinker(x: T, r: Result, shrinks: Int, orig: T): Result = { - val xs = shrink(x) - val res = r.addArg(Arg(labels,x,shrinks,orig,pp(x),pp(orig))) - val originalException = Some(r.status).collect { case Prop.Exception(e) => e.getClass } - if(xs.isEmpty) res else getFirstFailure(xs, originalException) match { - case Right(_) => 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 } - } - 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 && prms.useLegacyShrinking) shrinker(x, r, 0, x) + else r.addArg(Arg(labels, x, 0, x, pp(x), pp(x))) + } - gr.retrieve match { - case None => undecided(prms) - case Some(x) => - val r = result(x) - if (r.failure && prms.useLegacyShrinking) shrinker(x,r,0,x) - else r.addArg(Arg(labels,x,0,x,pp(x),pp(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, s1.shrink)(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))) + /** 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, s1.shrink)(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 + def forAll[A1, P]( + f: A1 => P + )(implicit + p: P => Prop, + a1: Arbitrary[A1], + s1: Shrink[A1], + pp1: A1 => Pretty ): Prop = forAllShrink(arbitrary[A1], s1.shrink)(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))) + 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))) + 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))) + 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))) + 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))) + 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))) + 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 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 = { @tailrec def attempt(prms: Gen.Parameters, endTime: Long): Result = { val result = wrappedProp.apply(prms) if (System.currentTimeMillis > endTime) { - (if(result.failure) result else Result(status = False)).label("Timeout") + (if (result.failure) result else Result(status = False)).label("Timeout") } else { if (result.success) result else attempt(prms, endTime) diff --git a/core/shared/src/main/scala/org/scalacheck/Properties.scala b/core/shared/src/main/scala/org/scalacheck/Properties.scala index 7ed17cb4..9de4de29 100644 --- a/core/shared/src/main/scala/org/scalacheck/Properties.scala +++ b/core/shared/src/main/scala/org/scalacheck/Properties.scala @@ -13,63 +13,55 @@ import org.scalacheck.rng.Seed import util.ConsoleReporter -/** Represents a collection of properties, with convenient methods - * for checking all properties at once. - *

Properties are added in the following way:

- * - * {{{ - * object MyProps extends Properties("MyProps") { - * property("myProp1") = forAll { (n:Int, m:Int) => - * n+m == m+n - * } - * } - * }}} - */ +/** Represents a collection of properties, with convenient methods for checking all properties at once.

Properties + * are added in the following way:

+ * + * {{{ + * object MyProps extends Properties("MyProps") { + * property("myProp1") = forAll { (n:Int, m:Int) => + * n+m == m+n + * } + * } + * }}} + */ @Platform.EnableReflectiveInstantiation class Properties(val name: String) { - private val props = new scala.collection.mutable.ListBuffer[(String,Prop)] + private val props = new scala.collection.mutable.ListBuffer[(String, Prop)] private var frozen = false - /** - * Customize the parameters specific to this class. - * - * After the command-line (either [[main]] above or sbt) modifies - * the default parameters, this method is called with the current - * state of the parameters. This method must then return - * parameters. The default implementation returns the parameters - * unchanged. However, a user can override this method in a - * properties subclass. Their method can modify the parameters. - * Those parameters will take precedence when the properties are - * executed. - */ + /** Customize the parameters specific to this class. + * + * After the command-line (either [[main]] above or sbt) modifies the default parameters, this method is called with + * the current state of the parameters. This method must then return parameters. The default implementation returns + * the parameters unchanged. However, a user can override this method in a properties subclass. Their method can + * modify the parameters. Those parameters will take precedence when the properties are executed. + */ def overrideParameters(p: Test.Parameters): Test.Parameters = p - /** Returns all properties of this collection in a list of name/property - * pairs. */ - def properties: collection.Seq[(String,Prop)] = { + /** Returns all properties of this collection in a list of name/property pairs. + */ + def properties: collection.Seq[(String, Prop)] = { frozen = true // once the properties have been exposed, they must be frozen props } - /** Convenience method that checks the properties with the given parameters - * (or default parameters, if not specified) - * and reports the result on the console. Should only be used when running - * tests interactively within the Scala REPL. - * - * If you need to get the results - * from the test use the `check` methods in [[org.scalacheck.Test]] - * instead. */ + /** Convenience method that checks the properties with the given parameters (or default parameters, if not specified) + * and reports the result on the console. Should only be used when running tests interactively within the Scala REPL. + * + * If you need to get the results from the test use the `check` methods in [[org.scalacheck.Test]] instead. + */ def check(prms: Test.Parameters = Test.Parameters.default): Unit = { val params = overrideParameters(prms) Test.checkProperties_( - params.withTestCallback(ConsoleReporter(1).chain(params.testCallback)), this + params.withTestCallback(ConsoleReporter(1).chain(params.testCallback)), + this ) } - /** Convenience method that makes it possible to use this property collection - * as an application that checks itself on execution. Calls `System.exit` - * with the exit code set to the number of failed properties. */ + /** Convenience method that makes it possible to use this property collection as an application that checks itself on + * execution. Calls `System.exit` with the exit code set to the number of failed properties. + */ def main(args: Array[String]): Unit = Test.CmdLineParser.parseParams(args) match { case (applyCmdParams, Nil) => @@ -92,16 +84,17 @@ class Properties(val name: String) { def include(ps: Properties): Unit = include(ps, prefix = "") - /** Adds all properties from another property collection to this one - * with a prefix this is prepended to each included property's name. */ + /** Adds all properties from another property collection to this one with a prefix this is prepended to each included + * property's name. + */ def include(ps: Properties, prefix: String): Unit = - for((n,p) <- ps.properties) property(prefix + n) = p + for ((n, p) <- ps.properties) property(prefix + n) = p /** Used for specifying properties. Usage: - * {{{ - * property("myProp") = ... - * }}} - */ + * {{{ + * property("myProp") = ... + * }}} + */ sealed class PropertySpecifier() { def update(propName: String, p: => Prop) = { if (frozen) throw new IllegalStateException("cannot nest properties or create properties during execution") diff --git a/core/shared/src/main/scala/org/scalacheck/ScalaCheckFramework.scala b/core/shared/src/main/scala/org/scalacheck/ScalaCheckFramework.scala index 9f19ae57..4b456937 100644 --- a/core/shared/src/main/scala/org/scalacheck/ScalaCheckFramework.scala +++ b/core/shared/src/main/scala/org/scalacheck/ScalaCheckFramework.scala @@ -9,11 +9,11 @@ package org.scalacheck -import sbt.testing._ -import java.util.concurrent.atomic.AtomicInteger - import org.scalacheck.Test.Parameters import org.scalacheck.Test.matchPropFilter +import sbt.testing._ + +import java.util.concurrent.atomic.AtomicInteger private abstract class ScalaCheckRunner extends Runner { @@ -29,7 +29,7 @@ private abstract class ScalaCheckRunner extends Runner { def deserializeTask(task: String, deserializer: String => TaskDef): BaseTask = { val taskDef = deserializer(task) val countTestSelectors = taskDef.selectors().toSeq.count { - case _:TestSelector => true + case _: TestSelector => true case _ => false } if (countTestSelectors == 0) rootTask(taskDef) @@ -52,8 +52,8 @@ private abstract class ScalaCheckRunner extends Runner { val loaded: Either[Prop, Properties] = { val fp = taskDef.fingerprint().asInstanceOf[SubclassFingerprint] - val obj = if (fp.isModule()) Platform.loadModule(taskDef.fullyQualifiedName(),loader) - else Platform.newInstance(taskDef.fullyQualifiedName(), loader, Seq())(Seq()) + val obj = if (fp.isModule()) Platform.loadModule(taskDef.fullyQualifiedName(), loader) + else Platform.newInstance(taskDef.fullyQualifiedName(), loader, Seq())(Seq()) obj match { case props: Properties => Right(props) case prop: Prop => Left(prop) @@ -80,22 +80,25 @@ private abstract class ScalaCheckRunner extends Runner { def log(loggers: Array[Logger], ok: Boolean, msg: String) = loggers foreach { l => val logstr = - if(!l.ansiCodesSupported()) msg + if (!l.ansiCodesSupported()) msg else s"${if (ok) Console.GREEN else Console.RED}$msg${Console.RESET}" l.info(logstr) } - def execute(handler: EventHandler, loggers: Array[Logger], - continuation: Array[Task] => Unit - ): Unit = continuation(execute(handler,loggers)) + def execute(handler: EventHandler, loggers: Array[Logger], continuation: Array[Task] => Unit): Unit = + continuation(execute(handler, loggers)) } def rootTask(td: TaskDef): BaseTask = new BaseTask(td) { def execute(handler: EventHandler, loggers: Array[Logger]): Array[Task] = props.map(_._1).toSet.toArray map { name => - checkPropTask(new TaskDef(td.fullyQualifiedName(), td.fingerprint(), - td.explicitlySpecified(), Array(new TestSelector(name))) - , single = true) + checkPropTask( + new TaskDef( + td.fullyQualifiedName(), + td.fingerprint(), + td.explicitlySpecified(), + Array(new TestSelector(name))), + single = true) } } @@ -122,7 +125,13 @@ private abstract class ScalaCheckRunner extends Runner { Array.empty[Task] } - def executeInternal(prop: Prop, name: String, handler: EventHandler, loggers: Array[Logger], propertyFilter: Option[scala.util.matching.Regex]): Unit = { + def executeInternal( + prop: Prop, + name: String, + handler: EventHandler, + loggers: Array[Logger], + propertyFilter: Option[scala.util.matching.Regex] + ): Unit = { if (propertyFilter.isEmpty || propertyFilter.exists(matchPropFilter(name, _))) { import util.Pretty.{pretty, Params} @@ -139,8 +148,8 @@ private abstract class ScalaCheckRunner extends Runner { val throwable = result.status match { case Test.PropException(_, e, _) => new OptionalThrowable(e) case _: Test.Failed => new OptionalThrowable( - new Exception(pretty(result, Params(0))) - ) + new Exception(pretty(result, Params(0))) + ) case _ => new OptionalThrowable() } val fullyQualifiedName = self.taskDef.fullyQualifiedName() @@ -192,44 +201,47 @@ final class ScalaCheckFramework extends Framework { mkFP(true, "org.scalacheck.Prop") ) - override def runner(_args: Array[String], _remoteArgs: Array[String], - _loader: ClassLoader - ): Runner = new ScalaCheckRunner { + override def runner(_args: Array[String], _remoteArgs: Array[String], _loader: ClassLoader): Runner = + new ScalaCheckRunner { + + val args = _args + val remoteArgs = _remoteArgs + val loader = _loader + val (prms, unknownArgs) = Test.CmdLineParser.parseParams(args) + val applyCmdParams = prms.andThen(sbtSetup(loader)) + + def receiveMessage(msg: String): Option[String] = msg(0) match { + case 'd' => + val Array(t, s, f, e) = msg.tail.split(',') + testCount.addAndGet(t.toInt) + successCount.addAndGet(s.toInt) + failureCount.addAndGet(f.toInt) + errorCount.addAndGet(e.toInt) + None + } - val args = _args - val remoteArgs = _remoteArgs - val loader = _loader - val (prms,unknownArgs) = Test.CmdLineParser.parseParams(args) - val applyCmdParams = prms.andThen(sbtSetup(loader)) + override def done() = if (testCount.get > 0) { + val heading = if (testCount.get == successCount.get) "Passed" else "Failed" + s"$heading: Total $testCount, " + + s"Failed $failureCount, Errors $errorCount, Passed $successCount" + + (if (unknownArgs.isEmpty) "" + else + s"\nWarning: Unknown ScalaCheck args provided: ${unknownArgs.mkString(" ")}") + } else "" - def receiveMessage(msg: String): Option[String] = msg(0) match { - case 'd' => - val Array(t,s,f,e) = msg.tail.split(',') - testCount.addAndGet(t.toInt) - successCount.addAndGet(s.toInt) - failureCount.addAndGet(f.toInt) - errorCount.addAndGet(e.toInt) - None } - override def done() = if (testCount.get > 0) { - val heading = if (testCount.get == successCount.get) "Passed" else "Failed" - s"$heading: Total $testCount, " + - s"Failed $failureCount, Errors $errorCount, Passed $successCount" + - (if(unknownArgs.isEmpty) "" else - s"\nWarning: Unknown ScalaCheck args provided: ${unknownArgs.mkString(" ")}") - } else "" - - } - - def slaveRunner(_args: Array[String], _remoteArgs: Array[String], - _loader: ClassLoader, send: String => Unit + def slaveRunner( + _args: Array[String], + _remoteArgs: Array[String], + _loader: ClassLoader, + send: String => Unit ): _root_.sbt.testing.Runner = new ScalaCheckRunner { val args = _args val remoteArgs = _remoteArgs val loader = _loader - val (prms,unknownArgs) = Test.CmdLineParser.parseParams(args) + val (prms, unknownArgs) = Test.CmdLineParser.parseParams(args) if (unknownArgs.nonEmpty) { println(s"Warning: Unknown ScalaCheck args provided: ${unknownArgs.mkString(" ")}") diff --git a/core/shared/src/main/scala/org/scalacheck/Shrink.scala b/core/shared/src/main/scala/org/scalacheck/Shrink.scala index 4bf86b25..1eae3d18 100644 --- a/core/shared/src/main/scala/org/scalacheck/Shrink.scala +++ b/core/shared/src/main/scala/org/scalacheck/Shrink.scala @@ -9,20 +9,22 @@ package org.scalacheck +import scala.concurrent.duration.Duration +import scala.concurrent.duration.FiniteDuration + import util.Buildable import util.SerializableCanBuildFroms._ -import scala.concurrent.duration.{Duration, FiniteDuration} sealed abstract class Shrink[T] extends Serializable { def shrink(x: T): Stream[T] - /** Create a new shrink that only produces values satisfying the given - * condition. - */ + /** Create a new shrink that only produces values satisfying the given condition. + */ def suchThat(f: T => Boolean): Shrink[T] = Shrink(v => this.shrink(v).filter(f)) } trait ShrinkLowPriority { + /** Default shrink instance */ implicit def shrinkAny[T]: Shrink[T] = Shrink(_ => Stream.empty) } @@ -34,8 +36,8 @@ object Shrink extends ShrinkLowPriority with ShrinkVersionSpecific with time.Jav /** Interleaves two streams */ private def interleave[T](xs: Stream[T], ys: Stream[T]): Stream[T] = - if(xs.isEmpty) ys - else if(ys.isEmpty) xs + if (xs.isEmpty) ys + else if (ys.isEmpty) xs else cons(xs.head, cons(ys.head, interleave(xs.tail, ys.tail))) /** Shrink instance factory */ @@ -46,27 +48,31 @@ object Shrink extends ShrinkLowPriority with ShrinkVersionSpecific with time.Jav /** Shrink a value */ def shrink[T](x: T)(implicit s: Shrink[T]): Stream[T] = s.shrink(x) - /** Shrink a value, but also return the original value as the first element in - * the resulting stream */ + /** Shrink a value, but also return the original value as the first element in the resulting stream + */ def shrinkWithOrig[T](x: T)(implicit s: Shrink[T]): Stream[T] = cons(x, s.shrink(x)) /** Shrink instance of container */ - implicit def shrinkContainer[C[_],T](implicit v: C[T] => Traversable[T], s: Shrink[T], - b: Buildable[T,C[T]] + implicit def shrinkContainer[C[_], T](implicit + v: C[T] => Traversable[T], + s: Shrink[T], + b: Buildable[T, C[T]] ): 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) + 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: Buildable[(T,U),C[T,U]] - ): Shrink[C[T,U]] = Shrink { (xs: C[T,U]) => + implicit def shrinkContainer2[C[_, _], T, U](implicit + v: C[T, U] => Traversable[(T, U)], + s: Shrink[(T, U)], + b: Buildable[(T, U), C[T, U]] + ): 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) + removeChunks(ys.size, zs).append(shrinkOne(zs)).map(b.fromIterable) } private def removeChunks[T](n: Int, xs: Stream[T]): Stream[Stream[T]] = @@ -85,12 +91,12 @@ object Shrink extends ShrinkLowPriority with ShrinkVersionSpecific with time.Jav cons(xs1, cons(xs2, interleave(xs3, xs4))) } - private def shrinkOne[T : Shrink](zs: Stream[T]): Stream[Stream[T]] = + 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(x).map(cons(_, xs)).append(shrinkOne(xs).map(cons(x, _))) } /** Shrink instances for numeric data types */ @@ -103,118 +109,152 @@ object Shrink extends ShrinkLowPriority with ShrinkVersionSpecific with time.Jav /** Shrink instance of String */ implicit lazy val shrinkString: Shrink[String] = Shrink { s => - shrinkContainer[List,Char].shrink(s.toList).map(_.mkString) + shrinkContainer[List, Char].shrink(s.toList).map(_.mkString) } /** Shrink instance of Option */ - implicit def shrinkOption[T : Shrink]: Shrink[Option[T]] = Shrink { + implicit def shrinkOption[T: Shrink]: Shrink[Option[T]] = Shrink { case None => empty - case Some(x) => cons(None, for(y <- shrink(x)) yield Some(y)) + 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,_)) + 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) => + 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(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) => + 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(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) => + 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(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) => + 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(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) => + 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(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) => + 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(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) => + 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, _)) + 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, _)) } - implicit def shrinkEither[T1:Shrink, T2:Shrink]: Shrink[Either[T1, T2]] = + implicit def shrinkEither[T1: Shrink, T2: Shrink]: Shrink[Either[T1, T2]] = Shrink { x => x.fold(shrink(_).map(Left(_)), shrink(_).map(Right(_))) } @@ -227,16 +267,16 @@ object Shrink extends ShrinkLowPriority with ShrinkVersionSpecific with time.Jav case _ => Stream.empty } - /** 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) */ + /** 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) } } final class ShrinkIntegral[T](implicit ev: Integral[T]) extends Shrink[T] { - import ev.{ fromInt, gteq, quot, negate, equiv, zero, one } + import ev.{fromInt, gteq, quot, negate, equiv, zero, one} val two = fromInt(2) @@ -259,7 +299,7 @@ final class ShrinkIntegral[T](implicit ev: Integral[T]) extends Shrink[T] { } final class ShrinkFractional[T](implicit ev: Fractional[T]) extends Shrink[T] { - import ev.{ fromInt, abs, zero, one, div, lteq, negate, lt } + import ev.{fromInt, abs, zero, one, div, lteq, negate, lt} val two = fromInt(2) diff --git a/core/shared/src/main/scala/org/scalacheck/Test.scala b/core/shared/src/main/scala/org/scalacheck/Test.scala index dd8c3c07..3562bd5f 100644 --- a/core/shared/src/main/scala/org/scalacheck/Test.scala +++ b/core/shared/src/main/scala/org/scalacheck/Test.scala @@ -9,85 +9,94 @@ package org.scalacheck -import Prop.Arg +import org.scalacheck.util.CmdLineParser +import org.scalacheck.util.ConsoleReporter +import org.scalacheck.util.FreqMap + import java.lang.Math -import org.scalacheck.util.{FreqMap, CmdLineParser, ConsoleReporter} -import scala.util.{Success, Failure} +import scala.util.Failure +import scala.util.Success import scala.util.matching.Regex -object Test { +import Prop.Arg +object Test { - /** Test parameters used by the check methods. Default - * parameters are defined by [[Test.Parameters.default]]. */ + /** Test parameters used by the check methods. Default parameters are defined by [[Test.Parameters.default]]. + */ sealed abstract class Parameters { outer => - /** The minimum number of tests that must succeed for ScalaCheck to - * consider a property passed. */ + + /** 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. */ + /** Create a copy of this [[Test.Parameters]] instance with [[Test.Parameters.minSuccessfulTests]] set to the + * specified value. + */ def withMinSuccessfulTests(minSuccessfulTests: Int): Parameters = cpy(minSuccessfulTests0 = 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. */ + /** Create a copy of this [[Test.Parameters]] instance with [[Test.Parameters.minSize]] set to the specified value. + */ def withMinSize(minSize: Int): Parameters = cpy(minSize0 = 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. */ + /** Create a copy of this [[Test.Parameters]] instance with [[Test.Parameters.maxSize]] set to the specified value. + */ def withMaxSize(maxSize: Int): Parameters = cpy(maxSize0 = maxSize) /** 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. */ + /** Create a copy of this [[Test.Parameters]] instance with [[Test.Parameters.workers]] set to the specified value. + */ def withWorkers(workers: Int): Parameters = cpy(workers0 = 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. */ + /** Create a copy of this [[Test.Parameters]] instance with [[Test.Parameters.testCallback]] set to the specified + * value. + */ def withTestCallback(testCallback: TestCallback): Parameters = cpy(testCallback0 = testCallback) - /** The maximum ratio between discarded and passed tests allowed before - * ScalaCheck gives up and discards the whole property (with status - * [[Test.Exhausted]]). Additionally, ScalaCheck will always allow - * at least `minSuccessfulTests * maxDiscardRatio` discarded tests, so the - * resulting discard ratio might be higher than `maxDiscardRatio`. */ + /** The maximum ratio between discarded and passed tests allowed before ScalaCheck gives up and discards the whole + * property (with status [[Test.Exhausted]]). Additionally, ScalaCheck will always allow at least + * `minSuccessfulTests * maxDiscardRatio` discarded tests, so the resulting discard ratio might be higher than + * `maxDiscardRatio`. + */ val maxDiscardRatio: Float - /** Create a copy of this [[Test.Parameters]] instance with - * [[Test.Parameters.maxDiscardRatio]] set to the specified value. */ + /** Create a copy of this [[Test.Parameters]] instance with [[Test.Parameters.maxDiscardRatio]] set to the specified + * value. + */ def withMaxDiscardRatio(maxDiscardRatio: Float): Parameters = cpy(maxDiscardRatio0 = 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. */ + /** Create a copy of this [[Test.Parameters]] instance with [[Test.Parameters.customClassLoader]] set to the + * specified value. + */ def withCustomClassLoader(customClassLoader: Option[ClassLoader]): Parameters = cpy(customClassLoader0 = customClassLoader) /** An optional regular expression to filter properties on. */ val propFilter: Option[String] - /** Create a copy of this [[Test.Parameters]] instance with - * [[Test.Parameters.propFilter]] set to the specified regular expression - * filter. */ + /** Create a copy of this [[Test.Parameters]] instance with [[Test.Parameters.propFilter]] set to the specified + * regular expression filter. + */ def withPropFilter(propFilter: Option[String]): Parameters = cpy(propFilter0 = propFilter) @@ -125,11 +134,10 @@ object Test { def withLegacyShrinking(b: Boolean): Parameters = cpy(useLegacyShrinking0 = b) - /** Maximum number of spins of the RNG to perform between checks. - * Greater values will reduce reuse of values (with dimimishing returns) - * for a given number of arguments to Prop.forAll tests. Greater values - * will also generally lead to slower tests, so be careful. - */ + /** Maximum number of spins of the RNG to perform between checks. Greater values will reduce reuse of values (with + * dimimishing returns) for a given number of arguments to Prop.forAll tests. Greater values will also generally + * lead to slower tests, so be careful. + */ val maxRNGSpins: Int = 1 /** Set maximum RNG spins between checks */ @@ -155,17 +163,17 @@ object Test { /** Copy constructor with named default arguments */ private[this] def cpy( - minSuccessfulTests0: Int = outer.minSuccessfulTests, - minSize0: Int = outer.minSize, - maxSize0: Int = outer.maxSize, - workers0: Int = outer.workers, - testCallback0: TestCallback = outer.testCallback, - maxDiscardRatio0: Float = outer.maxDiscardRatio, - customClassLoader0: Option[ClassLoader] = outer.customClassLoader, - propFilter0: Option[String] = outer.propFilter, - initialSeed0: Option[rng.Seed] = outer.initialSeed, - useLegacyShrinking0: Boolean = outer.useLegacyShrinking, - maxRNGSpins0: Int = outer.maxRNGSpins + minSuccessfulTests0: Int = outer.minSuccessfulTests, + minSize0: Int = outer.minSize, + maxSize0: Int = outer.maxSize, + workers0: Int = outer.workers, + testCallback0: TestCallback = outer.testCallback, + maxDiscardRatio0: Float = outer.maxDiscardRatio, + customClassLoader0: Option[ClassLoader] = outer.customClassLoader, + propFilter0: Option[String] = outer.propFilter, + initialSeed0: Option[rng.Seed] = outer.initialSeed, + useLegacyShrinking0: Boolean = outer.useLegacyShrinking, + maxRNGSpins0: Int = outer.maxRNGSpins ): Parameters = new Parameters { val minSuccessfulTests: Int = minSuccessfulTests0 @@ -184,29 +192,30 @@ object Test { // no longer used, but preserved for binary compatibility @deprecated("cp is deprecated. use cpy.", "1.14.1") private case class cp( - minSuccessfulTests: Int = minSuccessfulTests, - minSize: Int = minSize, - maxSize: Int = maxSize, - workers: Int = workers, - testCallback: TestCallback = testCallback, - maxDiscardRatio: Float = maxDiscardRatio, - customClassLoader: Option[ClassLoader] = customClassLoader, - propFilter: Option[String] = propFilter, - initialSeed: Option[rng.Seed] = initialSeed + minSuccessfulTests: Int = minSuccessfulTests, + minSize: Int = minSize, + maxSize: Int = maxSize, + workers: Int = workers, + testCallback: TestCallback = testCallback, + maxDiscardRatio: Float = maxDiscardRatio, + customClassLoader: Option[ClassLoader] = customClassLoader, + propFilter: Option[String] = propFilter, + initialSeed: Option[rng.Seed] = initialSeed ) extends Parameters } - /** Test parameters used by the check methods. Default - * parameters are defined by [[Test.Parameters.default]]. */ + /** Test parameters used by the check methods. Default parameters are defined by [[Test.Parameters.default]]. + */ object Parameters { - /** Default test parameters. Can be overridden if you need to - * tweak the parameters: - * - * {{{ - * val myParams = Parameters.default - * .withMinSuccessfulTests(600) - * .withMaxDiscardRatio(8) - * }}} */ + + /** Default test parameters. Can be overridden if you need to tweak the parameters: + * + * {{{ + * val myParams = Parameters.default + * .withMinSuccessfulTests(600) + * .withMaxDiscardRatio(8) + * }}} + */ val default: Parameters = new Parameters { val minSuccessfulTests: Int = 100 val minSize: Int = 0 @@ -225,11 +234,11 @@ object Test { /** Test statistics */ final case class Result( - status: Status, - succeeded: Int, - discarded: Int, - freqMap: FreqMap[Set[Any]], - time: Long = 0 + status: Status, + succeeded: Int, + discarded: Int, + freqMap: FreqMap[Set[Any]], + time: Long = 0 ) { def passed = status match { case Passed => true @@ -241,46 +250,44 @@ object Test { /** 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). */ + /** 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. */ + /** 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. */ + /** 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 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 trait TestCallback { self => + /** Called each time a property is evaluated */ - def onPropEval(name: String, threadIdx: Int, succeeded: Int, - discarded: Int): Unit = () + 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): 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 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) + self.onTestResult(name, result) + testCallback.onTestResult(name, result) } } } @@ -314,8 +321,8 @@ object Test { val names = Set("maxDiscardRatio", "r") val help = "The maximum ratio between discarded and succeeded tests " + - "allowed before ScalaCheck stops testing a property. At " + - "least minSuccessfulTests will always be tested, though." + "allowed before ScalaCheck stops testing a property. At " + + "least minSuccessfulTests will always be tested, though." } object OptMinSize extends IntOpt { val default = Parameters.default.minSize @@ -363,9 +370,15 @@ object Test { } val opts = Set[Opt[_]]( - OptMinSuccess, OptMaxDiscardRatio, OptMinSize, - OptMaxSize, OptWorkers, OptVerbosity, - OptPropFilter, OptInitialSeed, OptDisableLegacyShrinking, + OptMinSuccess, + OptMaxDiscardRatio, + OptMinSize, + OptMaxSize, + OptWorkers, + OptVerbosity, + OptPropFilter, + OptInitialSeed, + OptDisableLegacyShrinking, OptMaxRNGSpins ) @@ -407,22 +420,21 @@ object Test { } } - /** 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) - * } - * }}} - */ + /** 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. */ + /** Tests a property with the given testing parameters, and returns the test results. + */ def check(params: Parameters, p: Prop): Result = { assertParams(params) @@ -432,8 +444,8 @@ object Test { var stop = false def workerFun(workerIdx: Int): Result = { - var n = 0 // passed tests - var d = 0 // discarded tests + var n = 0 // passed tests + var d = 0 // discarded tests var res: Result = null var fm = FreqMap.empty[Set[Any]] @@ -445,8 +457,8 @@ object Test { } val spinner: () => Unit = - if (maxSpinsBetween > 1) { - () => { + if (maxSpinsBetween > 1) { () => + { var slides = 1 + ((n + d) % maxSpinsBetween) while (slides > 0) { @@ -454,13 +466,13 @@ object Test { slides -= 1 } } - } else { - () => { + } else { () => + { seed = seed.slide } } - while(!stop && res == null && n < iterations) { + while (!stop && res == null && n < iterations) { val count = workerIdx + (params.workers * (n + d)) val size = params.minSize.toDouble + (sizeStep * count) @@ -489,10 +501,10 @@ object Test { res = Result(Proved(propRes.args), n, d, fm) stop = true case Prop.False => - res = Result(Failed(propRes.args,propRes.labels), n, d, fm) + 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) + res = Result(PropException(propRes.args, e, propRes.labels), n, d, fm) stop = true } } @@ -510,23 +522,23 @@ object Test { timedRes } - /** As `check`, but discards the result. Useful for when you just want to - * read the console output. + /** As `check`, but discards the result. Useful for when you just want to read the console output. */ - def check_(params: Parameters, p: Prop): Unit = - {check(params, p); ()} + def check_(params: Parameters, p: Prop): Unit = { check(params, p); () } - /** As `check`, but discards the result. Useful for when you just want to - * read the console output. + /** As `check`, but discards the result. Useful for when you just want to read the console output. */ def check_(p: Prop)(f: Parameters => Parameters): Unit = check_(f(Parameters.default), p) /** Returns the result of filtering a property name by a supplied regular expression. * - * @param propertyName The name of the property to be filtered. - * @param regex The regular expression to filter the property name by. - * @return true if the regular expression matches the property name, false if not. + * @param propertyName + * The name of the property to be filtered. + * @param regex + * The regular expression to filter the property name by. + * @return + * true if the regular expression matches the property name, false if not. */ def matchPropFilter(propertyName: String, regex: Regex): Boolean = { regex.findFirstIn(propertyName).isDefined @@ -561,8 +573,8 @@ object Test { } } - /** As `checkProperties`, but discards the result. Useful for when you just - * want to observe the results on the console. + /** As `checkProperties`, but discards the result. Useful for when you just want to observe the results on the + * console. */ - def checkProperties_(prms: Parameters, ps: Properties): Unit = {checkProperties(prms, ps); ()} + def checkProperties_(prms: Parameters, ps: Properties): Unit = { checkProperties(prms, ps); () } } diff --git a/core/shared/src/main/scala/org/scalacheck/commands/Commands.scala b/core/shared/src/main/scala/org/scalacheck/commands/Commands.scala index 8ef55766..4891dd8f 100644 --- a/core/shared/src/main/scala/org/scalacheck/commands/Commands.scala +++ b/core/shared/src/main/scala/org/scalacheck/commands/Commands.scala @@ -10,126 +10,115 @@ package org.scalacheck.commands import org.scalacheck._ -import scala.util.{Try, Success, Failure} + +import scala.util.Failure +import scala.util.Success +import scala.util.Try /** An API for stateful testing in ScalaCheck. - * - * For an implementation overview, see the examples in ScalaCheck's source tree. - * - * @since 1.12.0 - */ + * + * For an implementation overview, see the examples in ScalaCheck's source tree. + * + * @since 1.12.0 + */ trait Commands { - /** The abstract state type. Must be immutable. - * The [[State]] type should model the state of the system under - * test (SUT). It should only contain details needed for specifying - * our pre- and post-conditions, and for creating [[Sut]] - * instances. */ + /** The abstract state type. Must be immutable. The [[State]] type should model the state of the system under test + * (SUT). It should only contain details needed for specifying our pre- and post-conditions, and for creating [[Sut]] + * instances. + */ type State - /** A type representing one instance of the system under test (SUT). - * The [[Sut]] type should be a proxy to the actual system under - * test and is therefore, by definition, a mutable type. - * It is used by the [[Command.run]] method to execute commands in the - * system under test. It should be possible to have any - * number of co-existing instances of the [[Sut]] type, as long as - * [[canCreateNewSut]] isn't violated, and each [[Sut]] - * instance should be a proxy to a distinct SUT instance. There should be no - * dependencies between the [[Sut]] instances, as they might be used - * in parallel by ScalaCheck. [[Sut]] instances are created by - * [[newSut]] and destroyed by - * [[destroySut]]. [[newSut]] and - * [[destroySut]] might be called at any time by - * ScalaCheck, as long as [[canCreateNewSut]] isn't violated. */ + /** A type representing one instance of the system under test (SUT). The [[Sut]] type should be a proxy to the actual + * system under test and is therefore, by definition, a mutable type. It is used by the [[Command.run]] method to + * execute commands in the system under test. It should be possible to have any number of co-existing instances of + * the [[Sut]] type, as long as [[canCreateNewSut]] isn't violated, and each [[Sut]] instance should be a proxy to a + * distinct SUT instance. There should be no dependencies between the [[Sut]] instances, as they might be used in + * parallel by ScalaCheck. [[Sut]] instances are created by [[newSut]] and destroyed by [[destroySut]]. [[newSut]] + * and [[destroySut]] might be called at any time by ScalaCheck, as long as [[canCreateNewSut]] isn't violated. + */ type Sut - /** Decides if [[newSut]] should be allowed to be called - * with the specified state instance. This can be used to limit the number - * of co-existing [[Sut]] instances. The list of existing states represents - * the initial states (not the current states) for all [[Sut]] instances - * that are active for the moment. If this method is implemented - * incorrectly, for example if it returns false even if the list of - * existing states is empty, ScalaCheck might hang. - * - * If you want to allow only one [[Sut]] instance to exist at any given time - * (a singleton [[Sut]]), implement this method the following way: - * - * {{{ - * def canCreateNewSut(newState: State, initSuts: Traversable[State] - * runningSuts: Traversable[Sut] - * ) = { - * initSuts.isEmpty && runningSuts.isEmpty - * } - * }}} - */ - def canCreateNewSut(newState: State, initSuts: Traversable[State], - runningSuts: Traversable[Sut]): Boolean - - /** Create a new [[Sut]] instance with an internal state that - * corresponds to the provided abstract state instance. The provided state - * is guaranteed to fulfill [[initialPreCondition]], and - * [[newSut]] will never be called if - * [[canCreateNewSut]] is not true for the given state. */ + /** Decides if [[newSut]] should be allowed to be called with the specified state instance. This can be used to limit + * the number of co-existing [[Sut]] instances. The list of existing states represents the initial states (not the + * current states) for all [[Sut]] instances that are active for the moment. If this method is implemented + * incorrectly, for example if it returns false even if the list of existing states is empty, ScalaCheck might hang. + * + * If you want to allow only one [[Sut]] instance to exist at any given time (a singleton [[Sut]]), implement this + * method the following way: + * + * {{{ + * def canCreateNewSut(newState: State, initSuts: Traversable[State] + * runningSuts: Traversable[Sut] + * ) = { + * initSuts.isEmpty && runningSuts.isEmpty + * } + * }}} + */ + def canCreateNewSut(newState: State, initSuts: Traversable[State], runningSuts: Traversable[Sut]): Boolean + + /** Create a new [[Sut]] instance with an internal state that corresponds to the provided abstract state instance. The + * provided state is guaranteed to fulfill [[initialPreCondition]], and [[newSut]] will never be called if + * [[canCreateNewSut]] is not true for the given state. + */ def newSut(state: State): Sut - /** Destroy the system represented by the given [[Sut]] - * instance, and release any resources related to it. */ + /** Destroy the system represented by the given [[Sut]] instance, and release any resources related to it. + */ def destroySut(sut: Sut): Unit - /** The precondition for the initial state, when no commands yet have - * run. This is used by ScalaCheck when command sequences are shrunk - * and the first state might differ from what is returned from - * [[genInitialState]]. */ + /** The precondition for the initial state, when no commands yet have run. This is used by ScalaCheck when command + * sequences are shrunk and the first state might differ from what is returned from [[genInitialState]]. + */ def initialPreCondition(state: State): Boolean - /** A generator that should produce an initial [[State]] instance that is - * usable by [[newSut]] to create a new system under test. - * The state returned by this generator is always checked with the - * [[initialPreCondition]] method before it is used. */ + /** A generator that should produce an initial [[State]] instance that is usable by [[newSut]] to create a new system + * under test. The state returned by this generator is always checked with the [[initialPreCondition]] method before + * it is used. + */ def genInitialState: Gen[State] - /** A generator that, given the current abstract state, should produce - * a suitable Command instance. */ + /** A generator that, given the current abstract state, should produce a suitable Command instance. + */ def genCommand(state: State): Gen[Command] - /** A type representing the commands that can run in the system under test. - * This type should be immutable and implement the equality operator - * properly. */ + /** A type representing the commands that can run in the system under test. This type should be immutable and + * implement the equality operator properly. + */ trait Command { - /** An abstract representation of the result of running this command in - * the system under test. The [[Result]] type should be immutable - * and it should encode everything about the command run that is necessary - * to know in order to correctly implement the - * [[[Command!.postCondition* postCondition]]] method. */ + + /** An abstract representation of the result of running this command in the system under test. The [[Result]] type + * should be immutable and it should encode everything about the command run that is necessary to know in order to + * correctly implement the [[[Command!.postCondition* postCondition]]] method. + */ type Result - /** Executes the command in the system under test, and returns a - * representation of the result of the command run. The result value - * is later used for verifying that the command behaved according - * to the specification, by the [[Command!.postCondition* postCondition]] - * method. */ + /** Executes the command in the system under test, and returns a representation of the result of the command run. + * The result value is later used for verifying that the command behaved according to the specification, by the + * [[Command!.postCondition* postCondition]] method. + */ def run(sut: Sut): Result - /** Returns a new [[State]] instance that represents the - * state of the system after this command has run, given the system - * was in the provided state before the run. */ + /** Returns a new [[State]] instance that represents the state of the system after this command has run, given the + * system was in the provided state before the run. + */ def nextState(state: State): State - /** Precondition that decides if this command is allowed to run - * when the system under test is in the provided state. */ + /** Precondition that decides if this command is allowed to run when the system under test is in the provided state. + */ def preCondition(state: State): Boolean - /** Postcondition that decides if this command produced the correct result - * or not, given the system was in the provided state before the command - * ran. */ + /** Postcondition that decides if this command produced the correct result or not, given the system was in the + * provided state before the command ran. + */ def postCondition(state: State, result: Try[Result]): Prop - /** Wraps the run and postCondition methods in order not to leak the - * dependent Result type. */ + /** Wraps the run and postCondition methods in order not to leak the dependent Result type. + */ private[Commands] def runPC(sut: Sut): (Try[String], State => Prop) = { import Prop.propBoolean val r = Try(run(sut)) - (r.map(_.toString), s => preCondition(s) ==> postCondition(s,r)) + (r.map(_.toString), s => preCondition(s) ==> postCondition(s, r)) } } @@ -160,18 +149,17 @@ trait Commands { def postCondition(state: State, result: Try[Null]) = true } - /** A command that runs a sequence of other commands. - * All commands (and their post conditions) are executed even if some - * command fails. Note that you probably can't use this method if you're - * testing in parallel (`threadCount` larger than 1). This is because - * ScalaCheck regards each command as atomic, even if the command - * is a sequence of other commands. */ + /** A command that runs a sequence of other commands. All commands (and their post conditions) are executed even if + * some command fails. Note that you probably can't use this method if you're testing in parallel (`threadCount` + * larger than 1). This is because ScalaCheck regards each command as atomic, even if the command is a sequence of + * other commands. + */ def commandSequence(head: Command, snd: Command, rest: Command*): Command = new CommandSequence(head, snd, rest: _*) /** A command that runs a sequence of other commands */ private final class CommandSequence(val head: Command, snd: Command, rest: Command*) - extends SuccessCommand { + extends SuccessCommand { /* The tail of the command sequence */ val tail: Command = if (rest.isEmpty) snd else new CommandSequence(snd, rest.head, rest.tail: _*) @@ -187,38 +175,31 @@ trait Commands { def postCondition(state: State, result: Result): Prop = head.postCondition(state, result._1) && - tail.postCondition(head.nextState(state), result._2) + tail.postCondition(head.nextState(state), result._2) } /** A property that can be used to test this [[Commands]] specification. - * - * The parameter `threadCount` specifies the number of commands that might - * be executed in parallel. Defaults to one, which means the commands will - * only be run serially for the same [[Sut]] instance. Distinct [[Sut]] - * instances might still receive commands in parallel, if the - * [[Test.Parameters.workers]] parameter is larger than one. Setting - * `threadCount` higher than one enables ScalaCheck to reveal - * thread-related issues in your system under test. - * - * When setting `threadCount` larger than one, ScalaCheck must evaluate - * all possible command interleavings (and the end [[State]] instances - * they produce), since parallel command execution is non-deterministic. - * ScalaCheck tries out all possible end states with the - * [[Command.postCondition]] function of the very last command executed - * (there is always exactly one command executed after all parallel command - * executions). If it fails to find an end state that satisfies the - * postcondition, the test fails. - * However, the number of possible end states grows rapidly with increasing - * values of `threadCount`. Therefore, the lengths of the parallel command - * sequences are limited so that the number of possible end states don't - * exceed `maxParComb`. The default value of `maxParComb` is 1000000. */ + * + * The parameter `threadCount` specifies the number of commands that might be executed in parallel. Defaults to one, + * which means the commands will only be run serially for the same [[Sut]] instance. Distinct [[Sut]] instances might + * still receive commands in parallel, if the [[Test.Parameters.workers]] parameter is larger than one. Setting + * `threadCount` higher than one enables ScalaCheck to reveal thread-related issues in your system under test. + * + * When setting `threadCount` larger than one, ScalaCheck must evaluate all possible command interleavings (and the + * end [[State]] instances they produce), since parallel command execution is non-deterministic. ScalaCheck tries out + * all possible end states with the [[Command.postCondition]] function of the very last command executed (there is + * always exactly one command executed after all parallel command executions). If it fails to find an end state that + * satisfies the postcondition, the test fails. However, the number of possible end states grows rapidly with + * increasing values of `threadCount`. Therefore, the lengths of the parallel command sequences are limited so that + * the number of possible end states don't exceed `maxParComb`. The default value of `maxParComb` is 1000000. + */ final def property(threadCount: Int = 1, maxParComb: Int = 1000000): Prop = { - val suts = collection.mutable.Map.empty[AnyRef,(State,Option[Sut])] + val suts = collection.mutable.Map.empty[AnyRef, (State, Option[Sut])] Prop.forAll(actions(threadCount, maxParComb)) { as => try { val sutId = suts.synchronized { - val initSuts = suts.values.collect { case (state,None) => state } + val initSuts = suts.values.collect { case (state, None) => state } val runningSuts = suts.values.collect { case (_, Some(sut)) => sut } if (canCreateNewSut(as.s, initSuts, runningSuts)) { val sutId = new AnyRef @@ -229,7 +210,7 @@ trait Commands { sutId match { case Some(id) => val sut = newSut(as.s) - def removeSut():Unit = { + def removeSut(): Unit = { suts.synchronized { suts -= id destroySut(sut) @@ -241,7 +222,7 @@ trait Commands { true } else false } - if (doRun) runActions(sut,as, removeSut()) + if (doRun) runActions(sut, as, removeSut()) else { removeSut() Prop.undecided @@ -251,28 +232,32 @@ trait Commands { println("NOT IMPL") Prop.undecided } - } catch { case e: Throwable => - suts.synchronized { suts.clear() } - throw e + } catch { + case e: Throwable => + suts.synchronized { suts.clear() } + throw e } } } - /** Override this to provide a custom Shrinker for your internal - * [[State]]. By default no shrinking is done for [[State]]. */ + /** Override this to provide a custom Shrinker for your internal [[State]]. By default no shrinking is done for + * [[State]]. + */ def shrinkState: Shrink[State] = implicitly // Private methods // private type Commands = List[Command] private case class Actions( - s: State, seqCmds: Commands, parCmds: List[Commands] + s: State, + seqCmds: Commands, + parCmds: List[Commands] ) private implicit val shrinkActions: Shrink[Actions] = Shrink[Actions] { as => val shrinkedCmds: Stream[Actions] = Shrink.shrink(as.seqCmds).map(cs => as.copy(seqCmds = cs)) append - Shrink.shrink(as.parCmds).map(cs => as.copy(parCmds = cs)) + Shrink.shrink(as.parCmds).map(cs => as.copy(parCmds = cs)) Shrink.shrinkWithOrig[State](as.s)(shrinkState) flatMap { state => shrinkedCmds.map(_.copy(s = state)) @@ -307,49 +292,47 @@ trait Commands { } } - private def runSeqCmds(sut: Sut, s0: State, cs: Commands - ): (Prop, State, List[Try[String]]) = - cs.foldLeft((Prop.proved,s0,List[Try[String]]())) { case ((p,s,rs),c) => - val (r,pf) = c.runPC(sut) + private def runSeqCmds(sut: Sut, s0: State, cs: Commands): (Prop, State, List[Try[String]]) = + cs.foldLeft((Prop.proved, s0, List[Try[String]]())) { case ((p, s, rs), c) => + val (r, pf) = c.runPC(sut) (p && pf(s), c.nextState(s), rs :+ r) } - private def runParCmds(sut: Sut, s: State, pcmds: List[Commands] - ): (Prop, List[List[(Command,Try[String])]]) = { + private def runParCmds(sut: Sut, s: State, pcmds: List[Commands]): (Prop, List[List[(Command, Try[String])]]) = { import concurrent._ val tp = java.util.concurrent.Executors.newFixedThreadPool(pcmds.size) implicit val ec: ExecutionContextExecutor = ExecutionContext.fromExecutor(tp) - val memo = collection.mutable.Map.empty[(State,List[Commands]), List[State]] + val memo = collection.mutable.Map.empty[(State, List[Commands]), List[State]] def endStates(scss: (State, List[Commands])): List[State] = { - val (s,css) = (scss._1, scss._2.filter(_.nonEmpty)) - (memo.get((s,css)),css) match { - case (Some(states),_) => states - case (_,Nil) => List(s) - case (_,cs::Nil) => - List(cs.init.foldLeft(s) { case (s0,c) => c.nextState(s0) }) + val (s, css) = (scss._1, scss._2.filter(_.nonEmpty)) + (memo.get((s, css)), css) match { + case (Some(states), _) => states + case (_, Nil) => List(s) + case (_, cs :: Nil) => + List(cs.init.foldLeft(s) { case (s0, c) => c.nextState(s0) }) case _ => - val inits = scan(css) { case (cs,x) => - (cs.head.nextState(s), cs.tail::x) + val inits = scan(css) { case (cs, x) => + (cs.head.nextState(s), cs.tail :: x) } val states = inits.distinct.flatMap(endStates).distinct - memo += (s,css) -> states + memo += (s, css) -> states states } } - def run(endStates: List[State], cs: Commands - ): Future[(Prop,List[(Command,Try[String])])] = Future { - if(cs.isEmpty) (Prop.proved, Nil) else blocking { + def run(endStates: List[State], cs: Commands): Future[(Prop, List[(Command, Try[String])])] = Future { + if (cs.isEmpty) (Prop.proved, Nil) + else blocking { val rs = cs.init.map(_.runPC(sut)._1) - val (r,pf) = cs.last.runPC(sut) + val (r, pf) = cs.last.runPC(sut) (Prop.atLeastOne(endStates.map(pf): _*), cs.zip(rs :+ r)) } } try { val res = Future.traverse(pcmds)(run(endStates(s -> pcmds), _)) map { l => - val (ps,rs) = l.unzip + val (ps, rs) = l.unzip (Prop.atLeastOne(ps: _*), rs) } Await.result(res, concurrent.duration.Duration.Inf) @@ -357,15 +340,17 @@ trait Commands { } /** Formats a list of commands with corresponding results */ - private def prettyCmdsRes(rs: List[(Command,Try[String])], maxLength: Int) = { + private def prettyCmdsRes(rs: List[(Command, Try[String])], maxLength: Int) = { val maxNumberWidth = "%d".format(maxLength).length val lineLayout = " %%%dd. %%s".format(maxNumberWidth) val cs = rs.zipWithIndex.map { - case (r, i) => lineLayout.format(i + 1, r match { - case (c, Success("()")) => c.toString - case (c, Success(r)) => s"$c => $r" - case (c, r) => s"$c => $r" - }) + case (r, i) => lineLayout.format( + i + 1, + r match { + case (c, Success("()")) => c.toString + case (c, Success(r)) => s"$c => $r" + case (c, r) => s"$c => $r" + }) } if (cs.isEmpty) " " @@ -374,50 +359,50 @@ trait Commands { } /** A property that runs the given actions in the given SUT */ - private def runActions(sut: Sut, as: Actions, finalize : =>Unit): Prop = { + private def runActions(sut: Sut, as: Actions, finalize: => Unit): Prop = { val maxLength = as.parCmds.map(_.length).foldLeft(as.seqCmds.length)(_.max(_)) - try{ - val (p1, s, rs1) = runSeqCmds(sut, as.s, as.seqCmds) - val l1 = s"Initial State:\n ${as.s}\nSequential Commands:\n${prettyCmdsRes(as.seqCmds zip rs1, maxLength)}" - if(as.parCmds.isEmpty) p1 :| l1 - else propAnd(p1.flatMap{r => if(!r.success) finalize; Prop(_ => r)} :| l1, { - try{ - val (p2, rs2) = runParCmds(sut, s, as.parCmds) - val l2 = rs2.map(prettyCmdsRes(_, maxLength)).mkString("\n\n") - p2 :| l1 :| s"Parallel Commands (starting in state = ${s})\n$l2" - } - finally finalize - }) - } - finally if(as.parCmds.isEmpty) finalize + try { + val (p1, s, rs1) = runSeqCmds(sut, as.s, as.seqCmds) + val l1 = s"Initial State:\n ${as.s}\nSequential Commands:\n${prettyCmdsRes(as.seqCmds zip rs1, maxLength)}" + if (as.parCmds.isEmpty) p1 :| l1 + else propAnd( + p1.flatMap { r => if (!r.success) finalize; Prop(_ => r) } :| l1, { + try { + val (p2, rs2) = runParCmds(sut, s, as.parCmds) + val l2 = rs2.map(prettyCmdsRes(_, maxLength)).mkString("\n\n") + p2 :| l1 :| s"Parallel Commands (starting in state = ${s})\n$l2" + } finally finalize + } + ) + } finally if (as.parCmds.isEmpty) finalize } /** [[Actions]] generator */ private def actions(threadCount: Int, maxParComb: Int): Gen[Actions] = { import Gen.{const, listOfN, sized} - def sizedCmds(s: State)(sz: Int): Gen[(State,Commands)] = { + def sizedCmds(s: State)(sz: Int): Gen[(State, Commands)] = { val l: List[Unit] = List.fill(sz)(()) - l.foldLeft(const((s,Nil:Commands))) { case (g,()) => + l.foldLeft(const((s, Nil: Commands))) { case (g, ()) => for { - (s0,cs) <- g + (s0, cs) <- g c <- genCommand(s0).suchThat(_.preCondition(s0)) } yield (c.nextState(s0), cs :+ c) } } - def cmdsPrecond(s: State, cmds: Commands): (State,Boolean) = cmds match { - case Nil => (s,true) - case c::cs if c.preCondition(s) => cmdsPrecond(c.nextState(s), cs) - case _ => (s,false) + def cmdsPrecond(s: State, cmds: Commands): (State, Boolean) = cmds match { + case Nil => (s, true) + case c :: cs if c.preCondition(s) => cmdsPrecond(c.nextState(s), cs) + case _ => (s, false) } def actionsPrecond(as: Actions) = as.parCmds.length != 1 && as.parCmds.forall(_.nonEmpty) && - initialPreCondition(as.s) && (cmdsPrecond(as.s, as.seqCmds) match { - case (s,true) => as.parCmds.forall(cmdsPrecond(s,_)._2) - case _ => false - }) + initialPreCondition(as.s) && (cmdsPrecond(as.s, as.seqCmds) match { + case (s, true) => as.parCmds.forall(cmdsPrecond(s, _)._2) + case _ => false + }) // Number of sequences to test (n = threadCount, m = parSz): // 2^m * 3^m * ... * n^m @@ -436,9 +421,10 @@ trait Commands { val parSz = { // Nbr of combinations def seqs(n: Long, m: Long): Long = - if(n == 1) 1 else math.round(math.pow(n.toDouble, m.toDouble)) * seqs(n-1,m) + if (n == 1) 1 else math.round(math.pow(n.toDouble, m.toDouble)) * seqs(n - 1, m) - if (threadCount < 2) 0 else { + if (threadCount < 2) 0 + else { var parSz = 1 while (seqs(threadCount.toLong, parSz.toLong) < maxParComb) parSz += 1 parSz @@ -447,23 +433,24 @@ trait Commands { val g = for { s0 <- genInitialState - (s1,seqCmds) <- sized(sizedCmds(s0)) - parCmds <- if(parSz <= 0) const(Nil) else - listOfN(threadCount, sizedCmds(s1)(parSz).map(_._2)) + (s1, seqCmds) <- sized(sizedCmds(s0)) + parCmds <- if (parSz <= 0) const(Nil) + else + listOfN(threadCount, sizedCmds(s1)(parSz).map(_._2)) } yield Actions(s0, seqCmds, parCmds) g.suchThat(actionsPrecond) } /** [1,2,3] -- [f(1,[2,3]), f(2,[1,3]), f(3,[1,2])] */ - private def scan[T,U](xs: List[T])(f: (T,List[T]) => U): List[U] = xs match { + private def scan[T, U](xs: List[T])(f: (T, List[T]) => U): List[U] = xs match { case Nil => Nil - case y::ys => f(y,ys) :: scan(ys) { case (x,xs) => f(x,y::xs) } + case y :: ys => f(y, ys) :: scan(ys) { case (x, xs) => f(x, y :: xs) } } /** Short-circuit property AND operator. (Should maybe be in Prop module) */ private def propAnd(p1: => Prop, p2: => Prop) = p1.flatMap { r => - if(r.success) Prop.secure(p2) else Prop(_ => r) + if (r.success) Prop.secure(p2) else Prop(_ => r) } } diff --git a/core/shared/src/main/scala/org/scalacheck/rng/Seed.scala b/core/shared/src/main/scala/org/scalacheck/rng/Seed.scala index 8632fd9f..af7f7dd5 100644 --- a/core/shared/src/main/scala/org/scalacheck/rng/Seed.scala +++ b/core/shared/src/main/scala/org/scalacheck/rng/Seed.scala @@ -13,29 +13,24 @@ package rng import scala.annotation.tailrec import scala.util.Try -/** - * Simple RNG by Bob Jenkins: - * - * http://burtleburtle.net/bob/rand/smallprng.html - */ +/** Simple RNG by Bob Jenkins: + * + * http://burtleburtle.net/bob/rand/smallprng.html + */ sealed abstract class Seed extends Serializable { protected val a: Long protected val b: Long protected val c: Long protected val d: Long - /** - * Generate a Base-64 representation of this seed. - * - * Given a seed, this method will return a String with 44 - * characters, according to the web-safe Base-64 specification - * (i.e. using minus (-) and underscore (_) in addition to - * alphanumeric characters). - * - * The 256-bit seed is serialized as a little-endian array of 64-bit - * Long values. Strings produced by this method are guaranteed to be - * parseable by the Seed.fromBase64 method. - */ + /** Generate a Base-64 representation of this seed. + * + * Given a seed, this method will return a String with 44 characters, according to the web-safe Base-64 specification + * (i.e. using minus (-) and underscore (_) in addition to alphanumeric characters). + * + * The 256-bit seed is serialized as a little-endian array of 64-bit Long values. Strings produced by this method are + * guaranteed to be parseable by the Seed.fromBase64 method. + */ def toBase64: String = { def enc(x: Long): Char = Seed.Alphabet((x & 0x3f).toInt) val chars = new Array[Char](44) @@ -73,35 +68,31 @@ sealed abstract class Seed extends Serializable { val n1 = (n & 0xffffffff) var i = 0 var seed: Seed = Seed.apply(a ^ n0, b ^ n1, c, d) - while(i < 16) { seed = seed.next; i += 1 } + while (i < 16) { seed = seed.next; i += 1 } seed } - /** - * This is a quick way of deterministically sliding this RNG to a - * different part of the PRNG sequence. - * - * We use this as an easy way to "split" the RNG off into a new part - * of the sequence. We want to do this in situations where we've - * already called .next several times, and we want to avoid - * repeating those numbers while preserving determinism. - */ + /** This is a quick way of deterministically sliding this RNG to a different part of the PRNG sequence. + * + * We use this as an easy way to "split" the RNG off into a new part of the sequence. We want to do this in + * situations where we've already called .next several times, and we want to avoid repeating those numbers while + * preserving determinism. + */ def slide: Seed = { val (n, s) = long s.reseed(n) } - /** - * Generates a Long value. - * - * The values will be uniformly distributed. */ + /** Generates a Long value. + * + * The values will be uniformly distributed. + */ def long: (Long, Seed) = (d, next) - /** - * Generates a Double value. - * - * The values will be uniformly distributed, and will be contained - * in the interval [0.0, 1.0). */ + /** Generates a Double value. + * + * The values will be uniformly distributed, and will be contained in the interval [0.0, 1.0). + */ def double: (Double, Seed) = ((d >>> 11) * 1.1102230246251565e-16, next) } @@ -119,14 +110,11 @@ object Seed { seed } - /** - * Generate a seed directly from four Long values. - * - * Warning: unlike Seed.apply(Long), this method just directly - * constructs a seed from the four Long values. Prefer using - * `Seed(Long)` if you aren't sure whether these will be good seed - * values. - */ + /** Generate a seed directly from four Long values. + * + * Warning: unlike Seed.apply(Long), this method just directly constructs a seed from the four Long values. Prefer + * using `Seed(Long)` if you aren't sure whether these will be good seed values. + */ def fromLongs(a: Long, b: Long, c: Long, d: Long): Seed = { if (a == 0 && b == 0 && c == 0 && d == 0) { throw new IllegalArgumentException("illegal Seed.fromLongs(0, 0, 0, 0)") @@ -134,35 +122,29 @@ object Seed { apply(a, b, c, d) } - /** - * Alphabet of characters used by the `toBase64` method. - * - * Since we're using the web-safe Base-64 specification, we are - * using minus (-) and underscore(_) in addition to the alphanumeric - * characters. - */ + /** Alphabet of characters used by the `toBase64` method. + * + * Since we're using the web-safe Base-64 specification, we are using minus (-) and underscore(_) in addition to the + * alphanumeric characters. + */ private[scalacheck] final val Alphabet: Array[Char] = ((0 until 26).map(i => ('A' + i).toChar) ++ (0 until 26).map(i => ('a' + i).toChar) ++ (0 until 10).map(i => ('0' + i).toChar) ++ Vector('-', '_')).toArray - /** - * Parse a Base-64 encoded seed, returning a Seed value. - * - * This method requires the exact format produced by `toBase64` - * (i.e. a 44-character string using the web-safe Base-64 - * alphabet). Other encodings must produce precisely the same - * outputs to be supported. - * - * This method will throw an IllegalArgumentException if parsing - * fails. - */ + /** Parse a Base-64 encoded seed, returning a Seed value. + * + * This method requires the exact format produced by `toBase64` (i.e. a 44-character string using the web-safe + * Base-64 alphabet). Other encodings must produce precisely the same outputs to be supported. + * + * This method will throw an IllegalArgumentException if parsing fails. + */ def fromBase64(s: String): Try[Seed] = { def fail(s: String): Nothing = throw new IllegalArgumentException(s) def dec(c: Char): Long = - if ('A' <= c && c <= 'Z') (c - 'A').toLong + if ('A' <= c && c <= 'Z') (c - 'A').toLong else if ('a' <= c && c <= 'z') ((c - 'a') + 26).toLong else if ('0' <= c && c <= '9') ((c - '0') + 52).toLong else if (c == '-') 62L diff --git a/core/shared/src/main/scala/org/scalacheck/time/JavaTimeArbitrary.scala b/core/shared/src/main/scala/org/scalacheck/time/JavaTimeArbitrary.scala index d6493e86..57d3d427 100644 --- a/core/shared/src/main/scala/org/scalacheck/time/JavaTimeArbitrary.scala +++ b/core/shared/src/main/scala/org/scalacheck/time/JavaTimeArbitrary.scala @@ -10,12 +10,14 @@ package org.scalacheck.time import org.scalacheck._ + import java.time._ /** [[Arbitrary]] instances for `java.time` types. * - * @note [[Arbitrary]] instances for `java.time` types which are Java enum - * types are provided by ScalaCheck's general Java enum support. + * @note + * [[Arbitrary]] instances for `java.time` types which are Java enum types are provided by ScalaCheck's general Java + * enum support. */ private[scalacheck] trait JavaTimeArbitrary { @@ -73,11 +75,9 @@ private[scalacheck] trait JavaTimeArbitrary { // ZoneId - /** ''Technically'' the available zone ids can change at runtime, so we store - * an immutable snapshot in time here. We avoid going through the - * scala/java collection converters to avoid having to deal with the scala - * 2.13 changes and adding a dependency on the collection compatibility - * library. + /** ''Technically'' the available zone ids can change at runtime, so we store an immutable snapshot in time here. We + * avoid going through the scala/java collection converters to avoid having to deal with the scala 2.13 changes and + * adding a dependency on the collection compatibility library. */ private final lazy val availableZoneIds: Set[ZoneId] = ZoneId.getAvailableZoneIds.toArray(Array.empty[String]).toSet.map((value: String) => ZoneId.of(value)) @@ -120,5 +120,7 @@ private[scalacheck] trait JavaTimeArbitrary { // The ZoneOffset's here look flipped but they are // not. ZonedDateTime.of(LocalDateTime.MIN, ZoneOffset.MAX) is _older_ // than ZonedDateTime.of(LocalDateTime, ZoneOffset.MIN). - Arbitrary(Gen.choose(ZonedDateTime.of(LocalDateTime.MIN, ZoneOffset.MAX), ZonedDateTime.of(LocalDateTime.MAX, ZoneOffset.MIN))) + Arbitrary(Gen.choose( + ZonedDateTime.of(LocalDateTime.MIN, ZoneOffset.MAX), + ZonedDateTime.of(LocalDateTime.MAX, ZoneOffset.MIN))) } diff --git a/core/shared/src/main/scala/org/scalacheck/time/JavaTimeChoose.scala b/core/shared/src/main/scala/org/scalacheck/time/JavaTimeChoose.scala index 8b2afc47..6df64fa0 100644 --- a/core/shared/src/main/scala/org/scalacheck/time/JavaTimeChoose.scala +++ b/core/shared/src/main/scala/org/scalacheck/time/JavaTimeChoose.scala @@ -9,14 +9,16 @@ package org.scalacheck.time +import org.scalacheck.Gen.Choose import org.scalacheck._ + import java.time._ -import org.scalacheck.Gen.Choose /** [[Gen#Choose]] instances for `java.time` types. * - * @note [[Gen#Choose]] instances for `java.time` types which are Java enum - * types are provided by ScalaCheck's general Java enum support. + * @note + * [[Gen#Choose]] instances for `java.time` types which are Java enum types are provided by ScalaCheck's general Java + * enum support. */ private[scalacheck] trait JavaTimeChoose { @@ -31,9 +33,9 @@ private[scalacheck] trait JavaTimeChoose { case _ => val minSeconds: Long = min.getSeconds val maxSeconds: Long = max.getSeconds - Gen.choose(minSeconds, maxSeconds).flatMap{seconds => + Gen.choose(minSeconds, maxSeconds).flatMap { seconds => val minNanos: Int = - if(seconds == minSeconds) { + if (seconds == minSeconds) { min.getNano } else { 0 @@ -45,8 +47,7 @@ private[scalacheck] trait JavaTimeChoose { 999999999 } Gen.choose(minNanos, maxNanos).map(nanos => - Duration.ofSeconds(seconds, nanos.toLong) - ) + Duration.ofSeconds(seconds, nanos.toLong)) } } } @@ -61,7 +62,7 @@ private[scalacheck] trait JavaTimeChoose { case 0 => Gen.const(min) case result if result > 0 => Gen.fail case _ => - Gen.choose(min.getEpochSecond, max.getEpochSecond).flatMap{epochSecond => + Gen.choose(min.getEpochSecond, max.getEpochSecond).flatMap { epochSecond => val minNano: Int = if (epochSecond == min.getEpochSecond) { min.getNano @@ -75,8 +76,7 @@ private[scalacheck] trait JavaTimeChoose { 999999999 } Gen.choose(minNano, maxNano).map(nanos => - Instant.ofEpochSecond(epochSecond, nanos.toLong) - ) + Instant.ofEpochSecond(epochSecond, nanos.toLong)) } } } @@ -111,7 +111,7 @@ private[scalacheck] trait JavaTimeChoose { case 0 => Gen.const(min) case result if result > 0 => Gen.fail case _ => - Gen.choose(min.getYear, max.getYear).flatMap{year => + Gen.choose(min.getYear, max.getYear).flatMap { year => val minMonth: Month = if (year == min.getYear) { min.getMonth @@ -124,7 +124,7 @@ private[scalacheck] trait JavaTimeChoose { } else { Month.DECEMBER } - Gen.choose(minMonth, maxMonth).flatMap{month => + Gen.choose(minMonth, maxMonth).flatMap { month => val minDay: Int = if (year == min.getYear && month == minMonth) { min.getDayOfMonth @@ -140,8 +140,7 @@ private[scalacheck] trait JavaTimeChoose { month.length(Year.isLeap(year.toLong)) } Gen.choose(minDay, maxDay).map(day => - LocalDate.of(year, month, day) - ) + LocalDate.of(year, month, day)) } } } @@ -153,8 +152,7 @@ private[scalacheck] trait JavaTimeChoose { new Choose[LocalTime] { override def choose(min: LocalTime, max: LocalTime): Gen[LocalTime] = Gen.choose(min.toNanoOfDay, max.toNanoOfDay).map(nano => - LocalTime.ofNanoOfDay(nano) - ) + LocalTime.ofNanoOfDay(nano)) } // LocalDateTime @@ -170,7 +168,7 @@ private[scalacheck] trait JavaTimeChoose { min.toLocalDate val maxLocalDate: LocalDate = max.toLocalDate - Gen.choose(minLocalDate, maxLocalDate).flatMap{localDate => + Gen.choose(minLocalDate, maxLocalDate).flatMap { localDate => val minLocalTime: LocalTime = if (localDate == minLocalDate) { min.toLocalTime @@ -184,8 +182,7 @@ private[scalacheck] trait JavaTimeChoose { LocalTime.MAX } Gen.choose(minLocalTime, maxLocalTime).map(localTime => - LocalDateTime.of(localDate, localTime) - ) + LocalDateTime.of(localDate, localTime)) } } } @@ -202,7 +199,7 @@ private[scalacheck] trait JavaTimeChoose { case _ => val minMonth: Month = min.getMonth val maxMonth: Month = max.getMonth - Gen.choose(minMonth, maxMonth).flatMap{month => + Gen.choose(minMonth, maxMonth).flatMap { month => val minDayOfMonth: Int = if (month == minMonth) { min.getDayOfMonth @@ -216,25 +213,21 @@ private[scalacheck] trait JavaTimeChoose { month.maxLength } Gen.choose(minDayOfMonth, maxDayOfMonth).map(dayOfMonth => - MonthDay.of(month, dayOfMonth) - ) + MonthDay.of(month, dayOfMonth)) } } } // ZoneOffset - /** ZoneOffset values have some unusual semantics when it comes to - * ordering. The short explanation is that `(ZoneOffset.MAX < - * ZoneOffset.MIN) == true`. This is because for any given `LocalDateTime`, - * that time applied to `ZoneOffset.MAX` will be an older moment in time - * than that same `LocalDateTime` applied to `ZoneOffset.MIN`. + /** ZoneOffset values have some unusual semantics when it comes to ordering. The short explanation is that + * `(ZoneOffset.MAX < ZoneOffset.MIN) == true`. This is because for any given `LocalDateTime`, that time applied to + * `ZoneOffset.MAX` will be an older moment in time than that same `LocalDateTime` applied to `ZoneOffset.MIN`. * * From the JavaDoc, * - * "The offsets are compared in the order that they occur for the same time - * of day around the world. Thus, an offset of +10:00 comes before an - * offset of +09:00 and so on down to -18:00." + * "The offsets are compared in the order that they occur for the same time of day around the world. Thus, an offset + * of +10:00 comes before an offset of +09:00 and so on down to -18:00." * * This has the following implication, * @@ -251,7 +244,8 @@ private[scalacheck] trait JavaTimeChoose { * * This implementation is consistent with that comparison. * - * @see [[https://docs.oracle.com/javase/8/docs/api/java/time/ZoneOffset.html#compareTo-java.time.ZoneOffset-]] + * @see + * [[https://docs.oracle.com/javase/8/docs/api/java/time/ZoneOffset.html#compareTo-java.time.ZoneOffset-]] */ implicit final lazy val chooseZoneOffset: Choose[ZoneOffset] = new Choose[ZoneOffset] { @@ -291,7 +285,7 @@ private[scalacheck] trait JavaTimeChoose { } else { rolloverSeconds } - Gen.choose(0, lub).flatMap{offsetShift => + Gen.choose(0, lub).flatMap { offsetShift => val shifted: OffsetTime = shiftForwardByOffset(min, offsetShift) val localShiftMin: Duration = { val durationFromMin: Duration = Duration.between(shifted, min) @@ -300,7 +294,7 @@ private[scalacheck] trait JavaTimeChoose { // e.g. Duration.ofHours(-1).compareTo(Duration.ofHours(-2)) > 0. For // this calculation we want the Duration with the smallest absolute // value, e.g. the one which compares larger. - if(durationFromMin.compareTo(durationAfterMidnight) > 0) { + if (durationFromMin.compareTo(durationAfterMidnight) > 0) { durationFromMin } else { durationAfterMidnight @@ -316,8 +310,7 @@ private[scalacheck] trait JavaTimeChoose { } } Gen.choose(localShiftMin, localShiftMax).map(localShift => - shifted.plus(localShift) - ) + shifted.plus(localShift)) } } @@ -328,7 +321,7 @@ private[scalacheck] trait JavaTimeChoose { case 0 => Gen.const(min) case result if result > 0 => Gen.fail case _ => - Gen.choose(Duration.ZERO, Duration.between(min, max)).flatMap{duration => + Gen.choose(Duration.ZERO, Duration.between(min, max)).flatMap { duration => genShiftOffsetTimeForward(min, max, duration) } } @@ -345,9 +338,7 @@ private[scalacheck] trait JavaTimeChoose { case _ => Gen.choose(min.getOffset, max.getOffset).flatMap(offset => Gen.choose(min.toInstant, max.toInstant).map(instant => - OffsetDateTime.ofInstant(instant, offset) - ) - ) + OffsetDateTime.ofInstant(instant, offset))) } } @@ -362,7 +353,7 @@ private[scalacheck] trait JavaTimeChoose { case _ => val minYear: Year = Year.of(min.getYear) val maxYear: Year = Year.of(max.getYear) - Gen.choose(minYear, maxYear).flatMap{year => + Gen.choose(minYear, maxYear).flatMap { year => val minMonth: Month = if (minYear == year) { min.getMonth @@ -376,8 +367,7 @@ private[scalacheck] trait JavaTimeChoose { Month.DECEMBER } Gen.choose(minMonth, maxMonth).map(month => - YearMonth.of(year.getValue, month) - ) + YearMonth.of(year.getValue, month)) } } } @@ -393,9 +383,7 @@ private[scalacheck] trait JavaTimeChoose { case _ => Gen.choose(min.getOffset, max.getOffset).flatMap(offset => Gen.choose(min.toInstant, max.toInstant).map(instant => - ZonedDateTime.ofInstant(instant, offset) - ) - ) + ZonedDateTime.ofInstant(instant, offset))) } } } diff --git a/core/shared/src/main/scala/org/scalacheck/time/JavaTimeCogen.scala b/core/shared/src/main/scala/org/scalacheck/time/JavaTimeCogen.scala index e8e38c99..ef73d7e9 100644 --- a/core/shared/src/main/scala/org/scalacheck/time/JavaTimeCogen.scala +++ b/core/shared/src/main/scala/org/scalacheck/time/JavaTimeCogen.scala @@ -10,6 +10,7 @@ package org.scalacheck.time import org.scalacheck._ + import java.time._ import java.time.temporal._ @@ -69,10 +70,11 @@ private[scalacheck] trait JavaTimeCogen { // ZoneId implicit final lazy val cogenZoneId: Cogen[ZoneId] = - Cogen[String].contramap(_.toString) // This may seem contrived, and in a - // way it is, but ZoneId values - // _without_ offsets are basically - // just newtypes of String. + // This may seem contrived, and in a + // way it is, but ZoneId values + // _without_ offsets are basically + // just newtypes of String. + Cogen[String].contramap(_.toString) // OffsetTime diff --git a/core/shared/src/main/scala/org/scalacheck/time/JavaTimeShrink.scala b/core/shared/src/main/scala/org/scalacheck/time/JavaTimeShrink.scala index 0b20555e..0c894a79 100644 --- a/core/shared/src/main/scala/org/scalacheck/time/JavaTimeShrink.scala +++ b/core/shared/src/main/scala/org/scalacheck/time/JavaTimeShrink.scala @@ -10,6 +10,7 @@ package org.scalacheck.time import org.scalacheck._ + import java.time._ /** [[Shrink]] instances for `java.time` types. */ @@ -18,7 +19,7 @@ private[scalacheck] trait JavaTimeShrink { // Duration implicit final lazy val shrinkJavaDuration: Shrink[Duration] = - Shrink[Duration]{value => + Shrink[Duration] { value => val q: Duration = value.dividedBy(2) if (q == Duration.ZERO) { Stream(Duration.ZERO) diff --git a/core/shared/src/main/scala/org/scalacheck/util/Buildable.scala b/core/shared/src/main/scala/org/scalacheck/util/Buildable.scala index bcb4cb86..e78b7ed7 100644 --- a/core/shared/src/main/scala/org/scalacheck/util/Buildable.scala +++ b/core/shared/src/main/scala/org/scalacheck/util/Buildable.scala @@ -9,10 +9,11 @@ package org.scalacheck.util -import scala.collection.{mutable, Map => _, _} +import scala.collection.mutable +import scala.collection.{Map => _, _} -trait Buildable[T,C] extends Serializable { - def builder: mutable.Builder[T,C] +trait Buildable[T, C] extends Serializable { + def builder: mutable.Builder[T, C] def fromIterable(it: Traversable[T]): C = { val b = builder b ++= it diff --git a/core/shared/src/main/scala/org/scalacheck/util/CmdLineParser.scala b/core/shared/src/main/scala/org/scalacheck/util/CmdLineParser.scala index d6309db1..a6a03491 100644 --- a/core/shared/src/main/scala/org/scalacheck/util/CmdLineParser.scala +++ b/core/shared/src/main/scala/org/scalacheck/util/CmdLineParser.scala @@ -24,7 +24,7 @@ private[scalacheck] trait CmdLineParser { trait StrOpt extends Opt[String] trait OpStrOpt extends Opt[Option[String]] - class OptMap(private val opts: Map[Opt[_],Any] = Map.empty) { + class OptMap(private val opts: Map[Opt[_], Any] = Map.empty) { def apply(flag: Flag): Boolean = opts.contains(flag) def apply[T](opt: Opt[T]): T = opts.get(opt) match { case None => opt.default @@ -36,7 +36,7 @@ private[scalacheck] trait CmdLineParser { val opts: Set[Opt[_]] private def getOpt(s: String) = { - if(s == null || s.length == 0 || s.charAt(0) != '-') None + if (s == null || s.length == 0 || s.charAt(0) != '-') None else opts.find(_.names.contains(s.drop(1))) } @@ -53,38 +53,40 @@ private[scalacheck] trait CmdLineParser { def printHelp(): Unit = { Console.out.println("Available options:") opts.foreach { opt => - Console.out.println(" " + opt.names.map("-"+_).mkString(", ") + ": " + opt.help) + Console.out.println(" " + opt.names.map("-" + _).mkString(", ") + ": " + opt.help) } } - /** Parses a command line and returns a tuple of the parsed options, - * and any unrecognized strings */ + /** Parses a command line and returns a tuple of the parsed options, and any unrecognized strings + */ def parseArgs[T](args: Array[String]): (OptMap, List[String]) = { def parse( - as: List[String], om: OptMap, us: List[String] + as: List[String], + om: OptMap, + us: List[String] ): (OptMap, List[String]) = as match { case Nil => (om, us) - case a::Nil => + case a :: Nil => getOpt(a) match { case Some(o: Flag) => parse(Nil, om.set((o, ())), us) case _ => (om, us :+ a) } - case a1::a2::as => getOpt(a1) match { - case Some(o: Flag) => - parse(a2 :: as, om.set((o, ())), us) - case otherwise => - (otherwise match { - case Some(o: IntOpt) => getInt(a2).map(v => parse(as, om.set(o -> v), us)) - case Some(o: FloatOpt) => getFloat(a2).map(v => parse(as, om.set(o -> v), us)) - case Some(o: StrOpt) => getStr(a2).map(v => parse(as, om.set(o -> v), us)) - case Some(o: OpStrOpt) => getStr(a2).map(v => parse(as, om.set(o -> Option(v)), us)) - case _ => None - }).getOrElse(parse(a2::as, om, us :+ a1)) - } + case a1 :: a2 :: as => getOpt(a1) match { + case Some(o: Flag) => + parse(a2 :: as, om.set((o, ())), us) + case otherwise => + (otherwise match { + case Some(o: IntOpt) => getInt(a2).map(v => parse(as, om.set(o -> v), us)) + case Some(o: FloatOpt) => getFloat(a2).map(v => parse(as, om.set(o -> v), us)) + case Some(o: StrOpt) => getStr(a2).map(v => parse(as, om.set(o -> v), us)) + case Some(o: OpStrOpt) => getStr(a2).map(v => parse(as, om.set(o -> Option(v)), us)) + case _ => None + }).getOrElse(parse(a2 :: as, om, us :+ a1)) + } } parse(args.toList, new OptMap(), Nil) diff --git a/core/shared/src/main/scala/org/scalacheck/util/ConsoleReporter.scala b/core/shared/src/main/scala/org/scalacheck/util/ConsoleReporter.scala index a2b582a4..5cf30e3c 100644 --- a/core/shared/src/main/scala/org/scalacheck/util/ConsoleReporter.scala +++ b/core/shared/src/main/scala/org/scalacheck/util/ConsoleReporter.scala @@ -9,26 +9,25 @@ package org.scalacheck.util -import Pretty.{Params, pretty, format} import org.scalacheck.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()`. - */ +import Pretty.{Params, pretty, format} + +/** 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()`. + */ class ConsoleReporter(val verbosity: Int, val columnWidth: Int) - extends Test.TestCallback { + extends Test.TestCallback { private val prettyPrms = Params(verbosity) override def onTestResult(name: String, res: Test.Result): Unit = { - if(verbosity > 0) { - if(name == "") { - val s = (if(res.passed) "+ " else "! ") + pretty(res, prettyPrms) + if (verbosity > 0) { + if (name == "") { + val s = (if (res.passed) "+ " else "! ") + pretty(res, prettyPrms) println(format(s, "", "", columnWidth)) } else { - val s = (if(res.passed) "+ " else "! ") + name + ": " + + val s = (if (res.passed) "+ " else "! ") + name + ": " + pretty(res, prettyPrms) println(format(s, "", "", columnWidth)) } @@ -39,9 +38,9 @@ class ConsoleReporter(val verbosity: Int, val columnWidth: Int) object ConsoleReporter { - /** Factory method, creates a ConsoleReporter with the - * the given verbosity and wraps output at the given column width - * (use 0 for unlimited width). */ + /** Factory method, creates a ConsoleReporter with the the given verbosity and wraps output at the given column width + * (use 0 for unlimited width). + */ def apply(verbosity: Int = 0, columnWidth: Int = 75) = new ConsoleReporter(verbosity, columnWidth) diff --git a/core/shared/src/main/scala/org/scalacheck/util/FreqMap.scala b/core/shared/src/main/scala/org/scalacheck/util/FreqMap.scala index 4f697544..479af055 100644 --- a/core/shared/src/main/scala/org/scalacheck/util/FreqMap.scala +++ b/core/shared/src/main/scala/org/scalacheck/util/FreqMap.scala @@ -12,13 +12,13 @@ package org.scalacheck.util import org.scalacheck.ScalaVersionSpecific._ sealed trait FreqMap[T] extends Serializable { - protected val underlying: scala.collection.immutable.Map[T,Int] + protected val underlying: scala.collection.immutable.Map[T, Int] def total: Int def +(t: T): FreqMap[T] = new FreqMap[T] { private val n = FreqMap.this.underlying.get(t) match { case None => 1 - case Some(n) => n+1 + case Some(n) => n + 1 } val underlying = FreqMap.this.underlying + (t -> n) val total = FreqMap.this.total + 1 @@ -27,7 +27,7 @@ sealed trait FreqMap[T] extends Serializable { def -(t: T): FreqMap[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)) + case Some(n) => FreqMap.this.underlying + (t -> (n - 1)) } val total = FreqMap.this.total + 1 } @@ -43,25 +43,25 @@ sealed trait FreqMap[T] extends Serializable { def --(fm: FreqMap[T]): FreqMap[T] = new FreqMap[T] { val underlying = FreqMap.this.underlying transform { - case (x,n) => n - fm.getCount(x).getOrElse(0) + case (x, n) => n - fm.getCount(x).getOrElse(0) } lazy val total = underlying.valuesIterator.foldLeft(0)(_ + _) } def getCount(t: T) = underlying.get(t) - def getCounts: List[(T,Int)] = underlying.toList.sortBy(-_._2) + def getCounts: List[(T, Int)] = underlying.toList.sortBy(-_._2) - def getRatio(t: T) = for(c <- getCount(t)) yield c.toFloat/total + def getRatio(t: T) = for (c <- getCount(t)) yield c.toFloat / total - def getRatios = for((t,c) <- getCounts) yield (t, c.toFloat/total) + def getRatios = for ((t, c) <- getCounts) yield (t, c.toFloat / total) override def toString = underlying.toString } object FreqMap { def empty[T]: FreqMap[T] = new FreqMap[T] { - val underlying = scala.collection.immutable.Map.empty[T,Int] + val underlying = scala.collection.immutable.Map.empty[T, Int] val total = 0 } } diff --git a/core/shared/src/main/scala/org/scalacheck/util/Pretty.scala b/core/shared/src/main/scala/org/scalacheck/util/Pretty.scala index c679bc2d..9dd110e1 100644 --- a/core/shared/src/main/scala/org/scalacheck/util/Pretty.scala +++ b/core/shared/src/main/scala/org/scalacheck/util/Pretty.scala @@ -11,6 +11,7 @@ package org.scalacheck.util import org.scalacheck.Prop.Arg import org.scalacheck.Test + import scala.annotation.tailrec import scala.math.round @@ -41,26 +42,22 @@ object Pretty { def pretty[T](t: T)(implicit ev: T => Pretty): String = pretty(t, defaultParams) private[this] implicit class StrBreak(val s1: String) extends AnyVal { - def /(s2: String) = if(s2 == "") s1 else s1+"\n"+s2 + 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 - - /** - * Break a long string across lines. - * - * This method will wrap the given string at `length` characters, - * inserting newlines and an optional prefix (`lead`) on every line - * other than the first. - * - * All lines in the resulting string are guaranteed to be `length` - * or shorter. - * - * We require `lead.length < length`; otherwise it would be - * impossible to legally wrap lines. - */ + if (s.length >= length) s + else s + List.fill(length - s.length)(c).mkString + + /** Break a long string across lines. + * + * This method will wrap the given string at `length` characters, inserting newlines and an optional prefix (`lead`) + * on every line other than the first. + * + * All lines in the resulting string are guaranteed to be `length` or shorter. + * + * We require `lead.length < length`; otherwise it would be impossible to legally wrap lines. + */ def break(s: String, lead: String, length: Int): String = { require(lead.length < length, s"lead ($lead) should be shorter than length ($length)") val step = length - lead.length @@ -82,7 +79,7 @@ object Pretty { def format(s: String, lead: String, trail: String, width: Int) = // was just `s.lines....`, but on JDK 11 we hit scala/bug#11125 - Predef.augmentString(s).lines.map(l => break(lead+l+trail, " ", width)).mkString("\n") + Predef.augmentString(s).lines.map(l => break(lead + l + trail, " ", width)).mkString("\n") private def toStrOrNull(s: Any) = if (s == null) "null" else s.toString @@ -90,11 +87,11 @@ object Pretty { val builder = new StringBuilder @annotation.tailrec def loop(i: Int): Unit = { - if(i < s.length){ + if (i < s.length) { val c = s.codePointAt(i) - if(Character.isISOControl(c)){ + if (Character.isISOControl(c)) { builder.append("\\u%04x".format(c)) - }else{ + } else { builder.append(s.charAt(i)) } loop(i + 1) @@ -106,78 +103,79 @@ object Pretty { implicit def prettyAny(t: Any): Pretty = Pretty { _ => toStrOrNull(t) } - implicit def prettyString(t: String): Pretty = Pretty { _ => "\""++escapeControlChars(t)++"\"" } + implicit def prettyString(t: String): Pretty = Pretty { _ => "\"" ++ escapeControlChars(t) ++ "\"" } implicit def prettyList(l: List[Any]): Pretty = Pretty { _ => - l.map("\""+_+"\"").mkString("List(", ", ", ")") + l.map("\"" + _ + "\"").mkString("List(", ", ", ")") } implicit def prettyThrowable(e: Throwable): Pretty = Pretty { prms => val strs = e.getStackTrace.toList.map { st => import st._ - getClassName+"."+getMethodName + "("+getFileName+":"+getLineNumber+")" + getClassName + "." + getMethodName + "(" + getFileName + ":" + getLineNumber + ")" } val strs2 = - if(prms.verbosity <= 0) List[String]() - else if(prms.verbosity <= 1) strs.take(5) + if (prms.verbosity <= 0) List[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 { - val labeledValues = for((a,i) <- args.zipWithIndex) yield { - val l = "> "+(if(a.label == "") "ARG_"+i else a.label) + if (args.isEmpty) "" + else { + val labeledValues = for ((a, i) <- args.zipWithIndex) yield { + val l = "> " + (if (a.label == "") "ARG_" + i else a.label) val s = - if(a.shrinks == 0) None - else Some(l+"_ORIGINAL: "+a.prettyOrigArg(prms)) - (l+": "+a.prettyArg(prms), s) + if (a.shrinks == 0) None + else Some(l + "_ORIGINAL: " + a.prettyOrigArg(prms)) + (l + ": " + a.prettyArg(prms), s) } labeledValues.map(_._1) ++ - labeledValues.map(_._2).collect { case Some(s) => s } + labeledValues.map(_._2).collect { case Some(s) => s } }.mkString("\n") } implicit def prettyFreqMap(fm: FreqMap[Set[Any]]): Pretty = Pretty { _ => - if(fm.total == 0) "" + if (fm.total == 0) "" else { "> Collected test data: " / { for { - (xs,r) <- fm.getRatios + (xs, r) <- fm.getRatios ys = xs - (()) if !ys.isEmpty - } yield round(r*100).toString + "% " + ys.mkString(", ") + } yield round(r * 100).toString + "% " + ys.mkString(", ") }.mkString("\n") } } implicit def prettyTestRes(res: Test.Result): Pretty = Pretty { prms => def labels(ls: collection.immutable.Set[String]) = - if(ls.isEmpty) "" + if (ls.isEmpty) "" else "> Labels of failing property: " / ls.mkString("\n") val s = res.status match { - case Test.Proved(_) if(prms.verbosity <= 1) => "OK, proved property." - case Test.Proved(args) => "OK, proved property."/prettyArgs(args)(prms) - case Test.Passed => "OK, passed "+res.succeeded+" tests." + case Test.Proved(_) if (prms.verbosity <= 1) => "OK, proved property." + 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) + "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) + "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) } - val t = if(prms.verbosity <= 1) "" else "Elapsed time: "+prettyTime(res.time) - s/t/pretty(res.freqMap,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) + 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/core/shared/src/test/scala-2.12-/org/scalacheck/time/OrderingVersionSpecific.scala b/core/shared/src/test/scala-2.12-/org/scalacheck/time/OrderingVersionSpecific.scala index 7f867b1a..9e1c2933 100644 --- a/core/shared/src/test/scala-2.12-/org/scalacheck/time/OrderingVersionSpecific.scala +++ b/core/shared/src/test/scala-2.12-/org/scalacheck/time/OrderingVersionSpecific.scala @@ -12,8 +12,7 @@ package org.scalacheck.time import java.time._ import java.time.chrono._ -/** On Scala <= 2.12 it is used to help the compiler figure out some `Ordering` - * instances needed for testing. +/** On Scala <= 2.12 it is used to help the compiler figure out some `Ordering` instances needed for testing. */ trait OrderingVersionSpecific { diff --git a/core/shared/src/test/scala-2.13+/org/scalacheck/time/OrderingVersionSpecific.scala b/core/shared/src/test/scala-2.13+/org/scalacheck/time/OrderingVersionSpecific.scala index 78fbfc96..a41aa2c4 100644 --- a/core/shared/src/test/scala-2.13+/org/scalacheck/time/OrderingVersionSpecific.scala +++ b/core/shared/src/test/scala-2.13+/org/scalacheck/time/OrderingVersionSpecific.scala @@ -9,9 +9,8 @@ package org.scalacheck.time -/** This is unused on Scala >= 2.13. +/** This is unused on Scala >= 2.13. * - * On Scala <= 2.12 it is used to help the compiler figure out some `Ordering` - * instances needed for testing. + * On Scala <= 2.12 it is used to help the compiler figure out some `Ordering` instances needed for testing. */ trait OrderingVersionSpecific {} diff --git a/core/shared/src/test/scala/org/scalacheck/NoPropertyNestingSpecification.scala b/core/shared/src/test/scala/org/scalacheck/NoPropertyNestingSpecification.scala index 2dc73df6..327aa854 100644 --- a/core/shared/src/test/scala/org/scalacheck/NoPropertyNestingSpecification.scala +++ b/core/shared/src/test/scala/org/scalacheck/NoPropertyNestingSpecification.scala @@ -23,11 +23,11 @@ object NoPropertyNestingSpecification extends Properties("Properties.no nesting" val results = for ((name, prop) <- p.properties) yield prop(Gen.Parameters.default) results match { case collection.Seq(res) => res.status match { - case Prop.Exception(e: IllegalStateException) => - if (e.getMessage.contains("nest")) thrown = true - else throw new Exception("exception message did not reference nesting") - case _ => throw new Exception("did not get IllegalStateException") - } + case Prop.Exception(e: IllegalStateException) => + if (e.getMessage.contains("nest")) thrown = true + else throw new Exception("exception message did not reference nesting") + case _ => throw new Exception("did not get IllegalStateException") + } case _ => throw new Exception("more than one property, somehow") } diff --git a/core/shared/src/test/scala/org/scalacheck/PropSpecification.scala b/core/shared/src/test/scala/org/scalacheck/PropSpecification.scala index 06f7b852..ce62b731 100644 --- a/core/shared/src/test/scala/org/scalacheck/PropSpecification.scala +++ b/core/shared/src/test/scala/org/scalacheck/PropSpecification.scala @@ -10,11 +10,30 @@ package org.scalacheck import Prop.{ - forAll, falsified, undecided, exception, passed, proved, all, - atLeastOne, sizedProp, someFailing, noneFailing, Undecided, False, True, - Exception, Proof, throws, propBoolean, secure, delay, lzy, collect + forAll, + falsified, + undecided, + exception, + passed, + proved, + all, + atLeastOne, + sizedProp, + someFailing, + noneFailing, + Undecided, + False, + True, + Exception, + Proof, + throws, + propBoolean, + secure, + delay, + lzy, + collect } -import Gen.{ const, fail, oneOf, listOf, Parameters } +import Gen.{const, fail, oneOf, listOf, Parameters} object PropSpecification extends Properties("Prop") { @@ -23,7 +42,7 @@ object PropSpecification extends Properties("Prop") { } property("Prop.==> undecided") = forAll { (p1: Prop) => - val g = oneOf(falsified,undecided) + val g = oneOf(falsified, undecided) forAll(g) { p2 => val p3 = (p2 ==> p1) p3 == undecided || (p3 == exception && p1 == exception) @@ -31,9 +50,9 @@ object PropSpecification extends Properties("Prop") { } property("Prop.==> true") = { - val g1 = oneOf(proved,falsified,undecided,exception) - val g2 = oneOf(passed,proved) - forAll(g1, g2) { case (p1,p2) => + val g1 = oneOf(proved, falsified, undecided, exception) + val g2 = oneOf(passed, proved) + forAll(g1, g2) { case (p1, p2) => val p = p2 ==> p1 (p == p1) || (p2 == passed && p1 == proved && p == passed) } @@ -55,8 +74,8 @@ object PropSpecification extends Properties("Prop") { } property("Prop.&& Commutativity") = { - val g = oneOf(proved,passed,falsified,undecided,exception) - forAll(g,g) { case (p1,p2) => (p1 && p2) == (p2 && p1) } + val g = oneOf(proved, passed, falsified, undecided, exception) + forAll(g, g) { case (p1, p2) => (p1 && p2) == (p2 && p1) } } property("Prop.&& Exception") = forAll { (p: Prop) => (p && propException()) == exception @@ -65,7 +84,7 @@ object PropSpecification extends Properties("Prop") { (passed && propException()) == exception } property("Prop.&& Identity") = { - val g = oneOf(proved,passed,falsified,undecided,exception) + val g = oneOf(proved, passed, falsified, undecided, exception) forAll(g)(p => (p && proved) == p) } property("Prop.&& False") = forAll { (p: Prop) => @@ -73,7 +92,7 @@ object PropSpecification extends Properties("Prop") { q == falsified || (q == exception && p == exception) } property("Prop.&& Undecided") = { - val g = oneOf(proved,passed,undecided) + val g = oneOf(proved, passed, undecided) forAll(g)(p => (p && undecided) == undecided) } property("Prop.&& Right prio") = forAll { (_: Int, prms: Parameters) => @@ -82,42 +101,42 @@ object PropSpecification extends Properties("Prop") { } property("Prop.|| Commutativity") = { - val g = oneOf(proved,passed,falsified,undecided,exception) - forAll(g,g) { case (p1,p2) => (p1 || p2) == (p2 || p1) } + val g = oneOf(proved, passed, falsified, undecided, exception) + forAll(g, g) { case (p1, p2) => (p1 || p2) == (p2 || p1) } } property("Prop.|| Exception") = forAll { (p: Prop) => (p || propException()) == exception } property("Prop.|| Identity") = { - val g = oneOf(proved,passed,falsified,undecided,exception) + val g = oneOf(proved, passed, falsified, undecided, exception) forAll(g)(p => (p || falsified) == p) } property("Prop.|| True") = { - val g = oneOf(proved,passed,falsified,undecided) + val g = oneOf(proved, passed, falsified, undecided) forAll(g)(p => (p || proved) == proved) } property("Prop.|| Undecided") = { - val g = oneOf(falsified,undecided) + val g = oneOf(falsified, undecided) forAll(g)(p => (p || undecided) == undecided) } property("Prop.++ Commutativity") = { - val g = oneOf(proved,passed,falsified,undecided,exception) - forAll(g,g) { case (p1,p2) => (p1 ++ p2) == (p2 ++ p1) } + val g = oneOf(proved, passed, falsified, undecided, exception) + forAll(g, g) { case (p1, p2) => (p1 ++ p2) == (p2 ++ p1) } } property("Prop.++ Exception") = forAll { (p: Prop) => (p ++ propException()) == exception } property("Prop.++ Identity 1") = { - val g = oneOf(falsified,passed,proved,exception) + val g = oneOf(falsified, passed, proved, exception) forAll(g)(p => (p ++ proved) == p) } property("Prop.++ Identity 2") = { - val g = oneOf(proved,passed,falsified,undecided,exception) + val g = oneOf(proved, passed, falsified, undecided, exception) forAll(g)(p => (p ++ undecided) == p) } property("Prop.++ False") = { - val g = oneOf(falsified,passed,proved,undecided) + val g = oneOf(falsified, passed, proved, undecided) forAll(g)(p => (p ++ falsified) == falsified) } @@ -153,7 +172,7 @@ object PropSpecification extends Properties("Prop") { } property("sizedProp") = { - val g = oneOf(passed,falsified,undecided,exception) + val g = oneOf(passed, falsified, undecided, exception) forAll(g) { p => p == sizedProp(_ => p) } } @@ -253,7 +272,7 @@ object PropSpecification extends Properties("Prop") { class ExpectedException extends RuntimeException("expected exception") class UnexpectedException extends RuntimeException("unexpected exception") def throwOn42(n: Int): Int = { - if(n == 42) + if (n == 42) throw new ExpectedException else throw new UnexpectedException @@ -275,7 +294,7 @@ object PropSpecification extends Properties("Prop") { def split(s: String): Stream[String] = { if (s.length == 1) Stream.empty else { - s.take(s.length / 2) #:: s.drop(s.length / 2) #:: Stream.empty + s.take(s.length / 2) #:: s.drop(s.length / 2) #:: Stream.empty } } split @@ -296,5 +315,5 @@ object PropSpecification extends Properties("Prop") { // make sure the two forAlls are seeing independent values property("regression #530: failure to slide seed") = forAll((x: Int) => (x >= 0) ==> true) && - forAll((x: Int) => (x < 0) ==> true) + forAll((x: Int) => (x < 0) ==> true) } diff --git a/core/shared/src/test/scala/org/scalacheck/ShrinkSpecification.scala b/core/shared/src/test/scala/org/scalacheck/ShrinkSpecification.scala index cd222c41..0f79ef21 100644 --- a/core/shared/src/test/scala/org/scalacheck/ShrinkSpecification.scala +++ b/core/shared/src/test/scala/org/scalacheck/ShrinkSpecification.scala @@ -9,16 +9,17 @@ package org.scalacheck +import scala.concurrent.duration.Duration +import scala.concurrent.duration.FiniteDuration + import Prop.{forAll, forAllNoShrink, propBoolean} import Shrink.shrink -import scala.concurrent.duration.{Duration, FiniteDuration} - object ShrinkSpecification extends Properties("Shrink") { - def shrinkClosure[T : Shrink](x: T): Stream[T] = { + def shrinkClosure[T: Shrink](x: T): Stream[T] = { val xs = shrink[T](x) - if(xs.isEmpty) xs + if (xs.isEmpty) xs else xs.append(xs.take(1).map(shrinkClosure[T]).flatten) } @@ -71,11 +72,11 @@ object ShrinkSpecification extends Properties("Shrink") { } property("shrink[Float] != 0") = forAll { (n: Float) => - (math.abs(n) > 1E-5f) ==> shrinkClosure(n).contains(0) + (math.abs(n) > 1e-5f) ==> shrinkClosure(n).contains(0) } property("shrink[Double] != 0") = forAll { (n: Double) => - (math.abs(n) > 1E-5d) ==> shrinkClosure(n).contains(0) + (math.abs(n) > 1e-5d) ==> shrinkClosure(n).contains(0) } property("shrink[FiniteDuration] != 0") = forAll { (n: FiniteDuration) => @@ -86,7 +87,7 @@ object ShrinkSpecification extends Properties("Shrink") { (n.isFinite && n != Duration.Zero) ==> shrinkClosure(n).contains(Duration.Zero) } - implicit def vectorShrink[A: Shrink]: Shrink[Vector[A]] = Shrink.xmap[List[A],Vector[A]](Vector(_: _*), _.toList) + implicit def vectorShrink[A: Shrink]: Shrink[Vector[A]] = Shrink.xmap[List[A], Vector[A]](Vector(_: _*), _.toList) property("shrink[Either]") = forAll { (e: Either[Int, Long]) => !shrink(e).contains(e) @@ -104,9 +105,9 @@ object ShrinkSpecification extends Properties("Shrink") { property("suchThat") = { implicit def shrinkEvenLength[A]: Shrink[List[A]] = - Shrink.shrinkContainer[List,A].suchThat(evenLength(_)) + Shrink.shrinkContainer[List, A].suchThat(evenLength(_)) val genEvenLengthLists = - Gen.containerOf[List,Int](Arbitrary.arbitrary[Int]).suchThat(evenLength(_)) + Gen.containerOf[List, Int](Arbitrary.arbitrary[Int]).suchThat(evenLength(_)) forAll(genEvenLengthLists) { (l: List[Int]) => evenLength(l) } @@ -114,7 +115,7 @@ object ShrinkSpecification extends Properties("Shrink") { def evenLength(value: List[_]) = value.length % 2 == 0 def shrinkEvenLength[A]: Shrink[List[A]] = - Shrink.shrinkContainer[List,A].suchThat(evenLength(_)) + Shrink.shrinkContainer[List, A].suchThat(evenLength(_)) property("shrink[List[Int].suchThat") = { forAll { (l: List[Int]) => diff --git a/core/shared/src/test/scala/org/scalacheck/examples/Examples.scala b/core/shared/src/test/scala/org/scalacheck/examples/Examples.scala index 06662d45..51a5ec0a 100644 --- a/core/shared/src/test/scala/org/scalacheck/examples/Examples.scala +++ b/core/shared/src/test/scala/org/scalacheck/examples/Examples.scala @@ -9,7 +9,8 @@ package org.scalacheck.examples -import org.scalacheck.{Prop, Properties} +import org.scalacheck.Prop +import org.scalacheck.Properties object Examples extends Properties("Examples") { @@ -25,20 +26,20 @@ object Examples extends Properties("Examples") { } } - case class Person ( - firstName: String, - lastName: String, - age: Int - ) { + case class Person( + firstName: String, + lastName: String, + age: Int + ) { def isTeenager = age >= 13 && age <= 19 - } + } val genPerson = { import org.scalacheck.Gen.{choose, oneOf} for { firstName <- oneOf("Alan", "Ada", "Alonzo") lastName <- oneOf("Lovelace", "Turing", "Church") - age <- choose(1,100) + age <- choose(1, 100) } yield Person(firstName, lastName, age) } diff --git a/core/shared/src/test/scala/org/scalacheck/examples/MathSpec.scala b/core/shared/src/test/scala/org/scalacheck/examples/MathSpec.scala index e021b101..2407c3e6 100644 --- a/core/shared/src/test/scala/org/scalacheck/examples/MathSpec.scala +++ b/core/shared/src/test/scala/org/scalacheck/examples/MathSpec.scala @@ -9,13 +9,14 @@ package org.scalacheck.examples -import org.scalacheck.Prop.{forAll, propBoolean} +import org.scalacheck.Prop.forAll +import org.scalacheck.Prop.propBoolean object MathSpec extends org.scalacheck.Properties("Math") { property("sqrt") = forAll { (n: Int) => (n >= 0) ==> { val m = math.sqrt(n.toDouble) - math.round(m*m) == n - } + math.round(m * m) == n + } } } diff --git a/core/shared/src/test/scala/org/scalacheck/util/BuildableSpecification.scala b/core/shared/src/test/scala/org/scalacheck/util/BuildableSpecification.scala index 7799469a..98a599ff 100644 --- a/core/shared/src/test/scala/org/scalacheck/util/BuildableSpecification.scala +++ b/core/shared/src/test/scala/org/scalacheck/util/BuildableSpecification.scala @@ -11,12 +11,13 @@ package org.scalacheck package util import scala.collection._ + import ScalaVersionSpecific._ object BuildableSpecification { def container[C[_]](implicit - evb: Buildable[String, C[String]], - evt: C[String] => Traversable[String] + evb: Buildable[String, C[String]], + evt: C[String] => Traversable[String] ) = Gen.containerOf[C, String](Gen.alphaStr) implicit val listGen: Gen[List[String]] = container[List] diff --git a/project/codegen.scala b/project/codegen.scala index 63f68003..04d52922 100644 --- a/project/codegen.scala +++ b/project/codegen.scala @@ -12,124 +12,127 @@ case class GeneratedFile(name: String, code: String) object codegen { - + def csv(s: Seq[String]) = s mkString ", " - def typed(s: Seq[(String,String)]) = s map { case (v,t) => s"$v:$t"} - def wrapType(t: String, w:String) = s"$w[$t]" - - def idents(name: String, i: Int) = 1 to i map(i0 => name+i0) - def types(i: Int) = idents("T",i).mkString(",") - + def typed(s: Seq[(String, String)]) = s map { case (v, t) => s"$v:$t" } + def wrapType(t: String, w: String) = s"$w[$t]" + + def idents(name: String, i: Int) = 1 to i map (i0 => name + i0) + def types(i: Int) = idents("T", i).mkString(",") + def valsWithTypes(i: Int) = - idents("t",i) zip - idents("T",i) map - { case (v,t) => s"$v:$t"} mkString "," - - def wrappedArgs(wrapper: String, i: Int) = + idents("t", i) zip + idents("T", i) map { case (v, t) => s"$v:$t" } mkString "," + + def wrappedArgs(wrapper: String, i: Int) = csv(typed( - idents(wrapper.take(1).toLowerCase,i) zip - idents("T",i).map(wrapType(_,wrapper)) + idents(wrapper.take(1).toLowerCase, i) zip + idents("T", i).map(wrapType(_, wrapper)) )) - - def flatMappedGenerators(i: Int, s: Seq[(String,String)]): String = + + def flatMappedGenerators(i: Int, s: Seq[(String, String)]): String = s.init.foldRight(s"${s.last._2}.map { ${s.last._1} => (${vals(i)}) }") { case ((t, g), acc) => val T = t.toUpperCase s"$g.flatMap(($t: $T) => $acc)" } - - def vals(i: Int) = csv(idents("t",i)) - + + def vals(i: Int) = csv(idents("t", i)) + def coImplicits(i: Int) = (1 to i).map(n => s"co$n: Cogen[T$n]").mkString(",") - + def fnArgs(i: Int) = (1 to i).map(n => s"t$n: T$n").mkString(",") - + def nestedPerturbs(i: Int) = (1 to i).foldLeft("seed0") { (s, n) => s"co$n.perturb($s, t$n)" } - + def fntype(i: Int) = s"(${types(i)}) => Z" - - def arbfn(i: Int) = s""" - | /** Arbitrary instance of Function${i} */ - | implicit def arbFunction${i}[${types(i)},Z](implicit g: Arbitrary[Z], ${coImplicits(i)}): Arbitrary[${fntype(i)}] = - | Arbitrary(Gen.function${i}(g.arbitrary)) - |""".stripMargin - - def genfn(i: Int) = s""" - | /** Gen creator for Function${i} */ - | def function${i}[${types(i)},Z](g: Gen[Z])(implicit ${coImplicits(i)}): Gen[${fntype(i)}] = - | Gen.gen { (p, seed0) => - | val f: ${fntype(i)} = - | (${fnArgs(i)}) => g.pureApply(p, ${nestedPerturbs(i)}) - | Gen.r[${fntype(i)}]( - | r = Some(f), - | sd = seed0.next - | ) - | } - |""".stripMargin - + + def arbfn(i: Int) = + s""" + | /** Arbitrary instance of Function${i} */ + | implicit def arbFunction${i}[${types(i)},Z]( + | implicit g: Arbitrary[Z], ${coImplicits(i)} + | ): Arbitrary[${fntype(i)}] = + | Arbitrary(Gen.function${i}(g.arbitrary)) + |""".stripMargin + + def genfn(i: Int) = + s""" + | /** Gen creator for Function${i} */ + | def function${i}[${types(i)},Z](g: Gen[Z])(implicit ${coImplicits(i)}): Gen[${fntype(i)}] = + | Gen.gen { (p, seed0) => + | val f: ${fntype(i)} = + | (${fnArgs(i)}) => g.pureApply(p, ${nestedPerturbs(i)}) + | Gen.r[${fntype(i)}]( + | r = Some(f), + | sd = seed0.next + | ) + | } + |""".stripMargin + def tuple(i: Int) = { - val gens = idents("a",i).map(_+".arbitrary") mkString "," - + val gens = idents("a", i).map(_ + ".arbitrary") mkString "," + if (i == 1) { s""" - | /** Arbitrary instance of ${i}-Tuple */ - | implicit def arbTuple$i[${types(i)}](implicit - | ${wrappedArgs("Arbitrary",i)} - | ): Arbitrary[Tuple$i[${types(i)}]] - | = Arbitrary(${gens}.map(Tuple1(_))) - |""".stripMargin + | /** Arbitrary instance of ${i}-Tuple */ + | implicit def arbTuple$i[${types(i)}](implicit + | ${wrappedArgs("Arbitrary", i)} + | ): Arbitrary[Tuple$i[${types(i)}]] + | = Arbitrary(${gens}.map(Tuple1(_))) + |""".stripMargin } else { s""" - | /** Arbitrary instance of ${i}-Tuple */ - | implicit def arbTuple$i[${types(i)}](implicit - | ${wrappedArgs("Arbitrary",i)} - | ): Arbitrary[Tuple$i[${types(i)}]] - | = Arbitrary(Gen.zip(${gens})) - |""".stripMargin + | /** Arbitrary instance of ${i}-Tuple */ + | implicit def arbTuple$i[${types(i)}](implicit + | ${wrappedArgs("Arbitrary", i)} + | ): Arbitrary[Tuple$i[${types(i)}]] + | = Arbitrary(Gen.zip(${gens})) + |""".stripMargin } } - + def zip(i: Int) = { - val gens = flatMappedGenerators(i, idents("t",i) zip idents("g",i)) + val gens = flatMappedGenerators(i, idents("t", i) zip idents("g", i)) s""" - | /** Combines the given generators into one generator that produces a - | * tuple of their generated values. */ - | def zip[${types(i)}]( - | ${wrappedArgs("Gen",i)} - | ): Gen[(${types(i)})] = - | $gens - |""".stripMargin + | /** Combines the given generators into one generator that produces a + | * tuple of their generated values. */ + | def zip[${types(i)}]( + | ${wrappedArgs("Gen", i)} + | ): Gen[(${types(i)})] = + | $gens + |""".stripMargin } - + def resultOf(i: Int) = { - def delegate = idents("T",i).drop(1).map("_:"+_).mkString(",") + def delegate = idents("T", i).drop(1).map("_:" + _).mkString(",") s""" - | /** Takes a function and returns a generator that generates arbitrary - | * results of that function by feeding it with arbitrarily generated input - | * parameters. */ - | def resultOf[${types(i)},R] - | (f: (${types(i)}) => R) - | (implicit - | ${wrappedArgs("Arbitrary",i)} - | ): Gen[R] = arbitrary[T1] flatMap { - | t => resultOf(f(t,$delegate)) - | } - |""".stripMargin + | /** Takes a function and returns a generator that generates arbitrary + | * results of that function by feeding it with arbitrarily generated input + | * parameters. */ + | def resultOf[${types(i)},R] + | (f: (${types(i)}) => R) + | (implicit + | ${wrappedArgs("Arbitrary", i)} + | ): Gen[R] = arbitrary[T1] flatMap { + | t => resultOf(f(t,$delegate)) + | } + |""".stripMargin } - + def tupleCogen(i: Int) = { s""" - | implicit final def tuple${i}[${types(i)}](implicit ${wrappedArgs("Cogen",i)}): Cogen[Tuple$i[${types(i)}]] = - | Cogen((seed, t) => - | ${idents("c", i).zipWithIndex.foldLeft("seed"){ - case (str, (c, n)) => s"$c.perturb($str, t._${n + 1})" - }} - | ) - |""".stripMargin + | implicit final def tuple${i}[${types(i)}](implicit ${wrappedArgs("Cogen", i)}): Cogen[Tuple$i[${types(i)}]] = + | Cogen((seed, t) => + | ${idents("c", i).zipWithIndex.foldLeft("seed") { + case (str, (c, n)) => s"$c.perturb($str, t._${n + 1})" + }} + | ) + |""".stripMargin } - + /* implicit def cogenFunction2[A: Arbitrary, B: Arbitrary, Z: Cogen]: Cogen[(A, B) => Z] = Cogen { (seed, f) => @@ -138,81 +141,84 @@ object codegen { Cogen[Z].perturb(r1.seed, f(r0.retrieve.get, r1.retrieve.get)) } */ - + def functionCogen(i: Int) = { def stanza(j: Int): String = { - val s = if (j == 1) "seed" else s"r${j-1}.seed" + val s = if (j == 1) "seed" else s"r${j - 1}.seed" s" val r${j} = arbitrary[T$j].doPureApply(params, $s)\n" } - + val ap = (1 to i).map(j => s"r${j}.retrieve.get").mkString("f(", ", ", ")") val fn = s"Function$i[${types(i)}, Z]" - + s""" - | implicit final def function${i}[${types(i)}, Z](implicit ${wrappedArgs("Arbitrary",i)}, z: Cogen[Z]): Cogen[$fn] = - | Cogen { (seed: Seed, f: $fn) => - |${(1 to i).map(stanza).mkString} - | Cogen[Z].perturb(seed, $ap) - | } - |""".stripMargin + | implicit final def function${i}[${types(i)}, Z]( + | implicit ${wrappedArgs("Arbitrary", i)}, z: Cogen[Z] + | ): Cogen[$fn] = + | Cogen { (seed: Seed, f: $fn) => + |${(1 to i).map(stanza).mkString} + | Cogen[Z].perturb(seed, $ap) + | } + |""".stripMargin } - + val genAll: Seq[GeneratedFile] = Seq( GeneratedFile( "ArbitraryArities.scala", s"""/** - |Defines implicit [[org.scalacheck.Arbitrary]] instances for tuples and functions - | - |Auto-generated using project/codegen.scala - |*/ - |package org.scalacheck - | - |private[scalacheck] trait ArbitraryArities{ - | // Functions // - | ${1 to 22 map arbfn mkString ""} - | - | // Tuples // - | ${1 to 22 map tuple mkString ""} - |}""".stripMargin), + |Defines implicit [[org.scalacheck.Arbitrary]] instances for tuples and functions + | + |Auto-generated using project/codegen.scala + |*/ + |package org.scalacheck + | + |private[scalacheck] trait ArbitraryArities{ + | // Functions // + | ${1 to 22 map arbfn mkString ""} + | + | // Tuples // + | ${1 to 22 map tuple mkString ""} + |}""".stripMargin + ), GeneratedFile( "GenArities.scala", s"""/** - |Defines zip and resultOf for all arities - | - |Auto-generated using project/codegen.scala - |*/ - |package org.scalacheck - |private[scalacheck] trait GenArities{ - | - | // genfn // - |${1 to 22 map genfn mkString ""} - | - | // zip // - |${1 to 22 map zip mkString ""} - | - | // resultOf // - | import Arbitrary.arbitrary - | def resultOf[T,R](f: T => R)(implicit a: Arbitrary[T]): Gen[R] - |${2 to 22 map resultOf mkString ""} - |}""".stripMargin + |Defines zip and resultOf for all arities + | + |Auto-generated using project/codegen.scala + |*/ + |package org.scalacheck + |private[scalacheck] trait GenArities{ + | + | // genfn // + |${1 to 22 map genfn mkString ""} + | + | // zip // + |${1 to 22 map zip mkString ""} + | + | // resultOf // + | import Arbitrary.arbitrary + | def resultOf[T,R](f: T => R)(implicit a: Arbitrary[T]): Gen[R] + |${2 to 22 map resultOf mkString ""} + |}""".stripMargin ), GeneratedFile( "CogenArities.scala", s"""/** - |Auto-generated using project/codegen.scala - |*/ - |package org.scalacheck - |private[scalacheck] abstract class CogenArities{ - | - | ${1 to 22 map tupleCogen mkString ""} - | - | import Arbitrary.arbitrary - | import Gen.Parameters.{ default => params } - | import rng.Seed - | - | ${1 to 22 map functionCogen mkString ""} - | - |}""".stripMargin + |Auto-generated using project/codegen.scala + |*/ + |package org.scalacheck + |private[scalacheck] abstract class CogenArities{ + | + | ${1 to 22 map tupleCogen mkString ""} + | + | import Arbitrary.arbitrary + | import Gen.Parameters.{ default => params } + | import rng.Seed + | + | ${1 to 22 map functionCogen mkString ""} + | + |}""".stripMargin ) ) } From 97d1eb17943dd52feee6cd4518fd55b9cdc76e98 Mon Sep 17 00:00:00 2001 From: satorg Date: Thu, 8 Jun 2023 14:34:38 -0700 Subject: [PATCH 3/3] flag the formatting commit --- .git-blame-ignore-revs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index cb49a3d0..3d446918 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,3 +1,7 @@ -# Header whitespace cleanup +# Header organizing (PR: #959, #963) b8564609df3c849b3a258a411e0de645d4e8c7a0 0b26b5e6dbcf3e6beeca806297f848f41dde899b + +# Code formatting (PR: #950) +ccd98e22a078e1282dbb2c1acfb40fe3afee01b6 +