Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent nesting properties #677

Merged
merged 1 commit into from
Sep 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/main/scala/org/scalacheck/Properties.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import util.ConsoleReporter
class Properties(val name: String) {

private val props = new scala.collection.mutable.ListBuffer[(String,Prop)]
private var frozen = false

/**
* Customize the parameters specific to this class.
Expand All @@ -46,7 +47,10 @@ class Properties(val name: String) {

/** Returns all properties of this collection in a list of name/property
* pairs. */
def properties: collection.Seq[(String,Prop)] = props
def properties: collection.Seq[(String,Prop)] = {
frozen = true // once the properties have been exposed, they must be frozen
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

an alternative would be to add a private[scalacheck] def freeze(): Unit and call it from the task when it gets the properties or right before execution

props
}

/** Convenience method that checks the properties with the given parameters
* (or default parameters, if not specified)
Expand Down Expand Up @@ -100,6 +104,7 @@ class Properties(val name: String) {
*/
sealed class PropertySpecifier() {
def update(propName: String, p: => Prop) = {
if (frozen) throw new IllegalStateException("cannot nest properties or create properties during execution")
val fullName = s"$name.$propName"
props += ((fullName, Prop.delay(p).viewSeed(fullName)))
}
Expand Down
36 changes: 36 additions & 0 deletions src/test/scala/org/scalacheck/NoPropertyNestingSpecification.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*-------------------------------------------------------------------------*\
** ScalaCheck **
** Copyright (c) 2007-2019 Rickard Nilsson. All rights reserved. **
** http://www.scalacheck.org **
** **
** This software is released under the terms of the Revised BSD License. **
** There is NO WARRANTY. See the file LICENSE for the full text. **
\*------------------------------------------------------------------------ */

package org.scalacheck

object NoPropertyNestingSpecification extends Properties("Properties.no nesting") {
property("no nested properties") = {
var thrown = false

val p = new Properties("P") {
property("outer") = {
property("inner") = true // not allowed!
true
}
}

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 _ => throw new Exception("more than one property, somehow")
}

thrown == true
}
}