@@ -1001,6 +1001,70 @@ object Gen extends GenArities with GenVersionSpecific {
10011001 }
10021002 }
10031003
1004+ /** Generates a container of any Traversable type for which there exists an
1005+ * implicit [[org.scalacheck.util.Buildable ]] instance. The elements in the
1006+ * container will be generated by the given generator. The generated container
1007+ * will continuously grow in size until the `fillCondition` returns true.
1008+ * If the given generator fails generating a value, the
1009+ * complete container generator will also fail. */
1010+ def buildableOfCond [C ,T ](fillCondition : C => Boolean , g : Gen [T ], failureHint : Int = Integer .MAX_VALUE )(implicit
1011+ evb : Buildable [T ,C ], evt : C => Traversable [T ]
1012+ ): Gen [C ] = {
1013+ new Gen [C ] {
1014+ def doApply (p : P , seed0 : Seed ): R [C ] = {
1015+ var seed : Seed = p.initialSeed.getOrElse(seed0)
1016+ val bldr = evb.builder
1017+ val allowedFailures = Gen .collectionRetries(failureHint)
1018+ var failures = 0
1019+ while (! fillCondition(bldr.result)) {
1020+ val res = g.doApply(p, seed)
1021+ res.retrieve match {
1022+ case Some (t) =>
1023+ bldr += t
1024+ case None =>
1025+ failures += 1
1026+ if (failures >= allowedFailures) return r(None , res.seed)
1027+ }
1028+ seed = res.seed
1029+ }
1030+ r(Some (bldr.result), seed)
1031+ }
1032+ }
1033+ }
1034+
1035+ /** Generates a container of any Traversable type for which there exists an
1036+ * implicit [[org.scalacheck.util.Buildable ]] instance. The elements in the
1037+ * container will be generated by the given generator. The generated container
1038+ * will continuously frow in size until the `fillCondition` returns true.
1039+ * Unlike `buildableOfCond`, this version of the method lets you specify another
1040+ * collection Gen which helps in speeding up the process of growing the collection.
1041+ * If the given generator fails generating a value, the
1042+ * complete container generator will also fail. */
1043+ def buildableOfCollCond [C <: Traversable [T ],T ](cond : C => Boolean , g : Gen [C ], failureHint : Int = Integer .MAX_VALUE )(implicit
1044+ evb : Buildable [T ,C ], evt : C => Traversable [T ]
1045+ ): Gen [C ] = {
1046+ new Gen [C ] {
1047+ def doApply (p : P , seed0 : Seed ): R [C ] = {
1048+ var seed : Seed = p.initialSeed.getOrElse(seed0)
1049+ val bldr = evb.builder
1050+ val allowedFailures = Gen .collectionRetries(failureHint)
1051+ var failures = 0
1052+ while (! cond(bldr.result)) {
1053+ val res = g.doApply(p, seed)
1054+ res.retrieve match {
1055+ case Some (t) =>
1056+ bldr ++= t
1057+ case None =>
1058+ failures += 1
1059+ if (failures >= allowedFailures) return r(None , res.seed)
1060+ }
1061+ seed = res.seed
1062+ }
1063+ r(Some (bldr.result), seed)
1064+ }
1065+ }
1066+ }
1067+
10041068 /** Generates a container of any Traversable type for which there exists an
10051069 * implicit [[org.scalacheck.util.Buildable ]] instance. The elements in the
10061070 * container will be generated by the given generator. The size of the
@@ -1042,6 +1106,18 @@ object Gen extends GenArities with GenVersionSpecific {
10421106 * `containerOf[List,T](g)`. */
10431107 def listOf [T ](g : => Gen [T ]) = buildableOf[List [T ], T ](g)
10441108
1109+ /** Generates a list that continuously grows in size until
1110+ * `finishCondition` returns true. */
1111+ def listOfCond [T ](finishCondition : List [T ] => Boolean , g : => Gen [T ], failureHint : Int = Integer .MAX_VALUE ) =
1112+ buildableOfCond[List [T ], T ](finishCondition, g, failureHint)
1113+
1114+ /** Generates a list that continuously grows in size until
1115+ * `finishCondition` returns true. Unlike `listOfCond` it
1116+ * accepts a list generator argument which lets you generate
1117+ * larger lists quicker */
1118+ def listOfFillCond [T ](finishCondition : List [T ] => Boolean , g : => Gen [List [T ]], failureHint : Int = Integer .MAX_VALUE ) =
1119+ buildableOfCollCond[List [T ], T ](finishCondition, g, failureHint)
1120+
10451121 /** Generates a non-empty list of random length. The maximum length depends
10461122 * on the size parameter. This method is equal to calling
10471123 * `nonEmptyContainerOf[List,T](g)`. */
@@ -1056,6 +1132,16 @@ object Gen extends GenArities with GenVersionSpecific {
10561132 * <code>containerOf[Map,(T,U)](g)</code>. */
10571133 def mapOf [T , U ](g : => Gen [(T , U )]) = buildableOf[Map [T , U ], (T , U )](g)
10581134
1135+ /** Generates a map that continuously grows in size until
1136+ * `finishCondition` returns true. */
1137+ 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)
1138+
1139+ /** Generates a map that continuously grows in size until
1140+ * `finishCondition` returns true. Unlike `mapOfCond` it
1141+ * accepts a map generator argument which lets you generate
1142+ * larger maps quicker */
1143+ 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)
1144+
10591145 /** Generates a non-empty map of random length. The maximum length depends
10601146 * on the size parameter. This method is equal to calling
10611147 * <code>nonEmptyContainerOf[Map,(T,U)](g)</code>. */
0 commit comments