diff --git a/core/shared/src/main/scala/org/scalacheck/Gen.scala b/core/shared/src/main/scala/org/scalacheck/Gen.scala
index a89e7ec2..82e4a9e8 100644
--- a/core/shared/src/main/scala/org/scalacheck/Gen.scala
+++ b/core/shared/src/main/scala/org/scalacheck/Gen.scala
@@ -1001,6 +1001,70 @@ 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 generated container
+ * will continuously grow in size until the `fillCondition` returns true.
+ * If the given generator fails generating a value, the
+ * complete container generator will also fail. */
+ def buildableOfCond[C,T](fillCondition: C => Boolean, g: Gen[T], failureHint: Int= Integer.MAX_VALUE)(implicit
+ evb: Buildable[T,C], evt: C => Traversable[T]
+ ): Gen[C] = {
+ new Gen[C] {
+ def doApply(p: P, seed0: Seed): R[C] = {
+ var seed: Seed = p.initialSeed.getOrElse(seed0)
+ val bldr = evb.builder
+ val allowedFailures = Gen.collectionRetries(failureHint)
+ var failures = 0
+ while (!fillCondition(bldr.result)) {
+ val res = g.doApply(p, seed)
+ res.retrieve match {
+ case Some(t) =>
+ bldr += t
+ case None =>
+ failures += 1
+ if (failures >= allowedFailures) return r(None, res.seed)
+ }
+ seed = res.seed
+ }
+ r(Some(bldr.result), seed)
+ }
+ }
+ }
+
+ /** 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 generated container
+ * will continuously frow in size until the `fillCondition` returns true.
+ * Unlike `buildableOfCond`, this version of the method lets you specify another
+ * collection Gen which helps in speeding up the process of growing the collection.
+ * If the given generator fails generating a value, the
+ * complete container generator will also fail. */
+ def buildableOfCollCond[C <: Traversable[T],T](cond: C => Boolean, g: Gen[C], failureHint: Int= Integer.MAX_VALUE)(implicit
+ evb: Buildable[T,C], evt: C => Traversable[T]
+ ): Gen[C] = {
+ new Gen[C] {
+ def doApply(p: P, seed0: Seed): R[C] = {
+ var seed: Seed = p.initialSeed.getOrElse(seed0)
+ val bldr = evb.builder
+ val allowedFailures = Gen.collectionRetries(failureHint)
+ var failures = 0
+ while (!cond(bldr.result)) {
+ val res = g.doApply(p, seed)
+ res.retrieve match {
+ case Some(t) =>
+ bldr ++= t
+ case None =>
+ failures += 1
+ if (failures >= allowedFailures) return r(None, res.seed)
+ }
+ seed = res.seed
+ }
+ r(Some(bldr.result), seed)
+ }
+ }
+ }
+
/** 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
@@ -1042,6 +1106,18 @@ object Gen extends GenArities with GenVersionSpecific {
* `containerOf[List,T](g)`. */
def listOf[T](g: => Gen[T]) = buildableOf[List[T], T](g)
+ /** Generates a list that continuously grows in size until
+ * `finishCondition` returns true. */
+ def listOfCond[T](finishCondition: List[T] => Boolean, g: => Gen[T], failureHint: Int = Integer.MAX_VALUE) =
+ buildableOfCond[List[T], T](finishCondition, g, failureHint)
+
+ /** Generates a list that continuously grows in size until
+ * `finishCondition` returns true. Unlike `listOfCond` it
+ * accepts a list generator argument which lets you generate
+ * larger lists quicker */
+ def listOfFillCond[T](finishCondition: List[T] => Boolean, g: => Gen[List[T]], failureHint: Int = Integer.MAX_VALUE) =
+ buildableOfCollCond[List[T], T](finishCondition, g, failureHint)
+
/** 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)`. */
@@ -1056,6 +1132,16 @@ object Gen extends GenArities with GenVersionSpecific {
* containerOf[Map,(T,U)](g)
. */
def mapOf[T, U](g: => Gen[(T, U)]) = buildableOf[Map[T, U], (T, U)](g)
+ /** Generates a map that continuously grows in size until
+ * `finishCondition` returns true. */
+ def mapOfCond[T, U](cond: Map[T,U] => Boolean, g: => Gen[(T, U)], failureHint: Int = Integer.MAX_VALUE) = buildableOfCond[Map[T, U],(T, U)](cond, g, failureHint)
+
+ /** Generates a map that continuously grows in size until
+ * `finishCondition` returns true. Unlike `mapOfCond` it
+ * accepts a map generator argument which lets you generate
+ * larger maps quicker */
+ def mapOfFillCond[T, U](cond: Map[T,U] => Boolean, g: => Gen[Map[T, U]], failureHint: Int = Integer.MAX_VALUE) = buildableOfCollCond[Map[T, U],(T, U)](cond, g, failureHint)
+
/** 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)
. */