From 006527d246649a5d72f95200576334e904545271 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Mar 2018 09:08:52 +0100 Subject: [PATCH 1/4] Re-order SlashSyntaxSpec arbitraries --- .../src/test/scala/sbt/SlashSyntaxSpec.scala | 59 ++++++++++--------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala b/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala index a4c802934..ea1bcf2ea 100644 --- a/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala +++ b/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala @@ -57,16 +57,42 @@ object BuildDSLInstances { implicit def arbAttrKey[A: Manifest]: Arbitrary[AttributeKey[_]] = Arbitrary(Gen.identifier map (AttributeKey[A](_))) - def withScope[K <: Scoped.ScopingSetting[K]](keyGen: Gen[K]): Arbitrary[K] = - Arbitrary(Gen.frequency( - 5 -> keyGen, - 1 -> (for (key <- keyGen; scope <- arbitrary[Scope]) yield key in scope) - )) + implicit val arbAttributeMap: Arbitrary[AttributeMap] = Arbitrary { + Gen.frequency( + 20 -> AttributeMap.empty, + 1 -> { + for (name <- Gen.identifier; isModule <- arbitrary[Boolean]) + yield + AttributeMap.empty + .put(AttributeKey[String]("name"), name) + .put(AttributeKey[Boolean]("isModule"), isModule) + } + ) + } + + implicit def arbScopeAxis[A: Arbitrary]: Arbitrary[ScopeAxis[A]] = + Arbitrary(Gen.oneOf[ScopeAxis[A]](This, Zero, arbitrary[A] map (Select(_)))) + + implicit def arbScope: Arbitrary[Scope] = Arbitrary( + for { + r <- arbitrary[ScopeAxis[Reference]] + c <- arbitrary[ScopeAxis[ConfigKey]] + t <- arbitrary[ScopeAxis[AttributeKey[_]]] + e <- arbitrary[ScopeAxis[AttributeMap]] + } yield Scope(r, c, t, e) + ) def genInputKey[A: Manifest]: Gen[InputKey[A]] = Gen.identifier map (InputKey[A](_)) def genSettingKey[A: Manifest]: Gen[SettingKey[A]] = Gen.identifier map (SettingKey[A](_)) def genTaskKey[A: Manifest]: Gen[TaskKey[A]] = Gen.identifier map (TaskKey[A](_)) + def withScope[K <: Scoped.ScopingSetting[K]](keyGen: Gen[K]): Arbitrary[K] = Arbitrary { + Gen.frequency( + 5 -> keyGen, + 1 -> (for (key <- keyGen; scope <- arbitrary[Scope]) yield key in scope) + ) + } + implicit def arbInputKey[A: Manifest]: Arbitrary[InputKey[A]] = withScope(genInputKey[A]) implicit def arbSettingKey[A: Manifest]: Arbitrary[SettingKey[A]] = withScope(genSettingKey[A]) implicit def arbTaskKey[A: Manifest]: Arbitrary[TaskKey[A]] = withScope(genTaskKey[A]) @@ -88,29 +114,6 @@ object BuildDSLInstances { implicit def arbSettingKey[A: Manifest]: Arbitrary[SettingKey[A]] = Arbitrary(genSettingKey[A]) implicit def arbTaskKey[A: Manifest]: Arbitrary[TaskKey[A]] = Arbitrary(genTaskKey[A]) } - - implicit def arbScopeAxis[A: Arbitrary]: Arbitrary[ScopeAxis[A]] = - Arbitrary(Gen.oneOf[ScopeAxis[A]](This, Zero, arbitrary[A] map (Select(_)))) - - implicit val arbAttributeMap: Arbitrary[AttributeMap] = Arbitrary { - Gen.frequency( - 20 -> AttributeMap.empty, - 1 -> (for (name <- Gen.identifier; isModule <- arbitrary[Boolean]) - yield AttributeMap.empty - .put(AttributeKey[String]("name"), name) - .put(AttributeKey[Boolean]("isModule"), isModule) - ) - ) - } - - implicit def arbScope: Arbitrary[Scope] = Arbitrary( - for { - r <- arbitrary[ScopeAxis[Reference]] - c <- arbitrary[ScopeAxis[ConfigKey]] - t <- arbitrary[ScopeAxis[AttributeKey[_]]] - e <- arbitrary[ScopeAxis[AttributeMap]] - } yield Scope(r, c, t, e) - ) } import BuildDSLInstances._ From 51ff72872bdc7de92ace2244d090ef032516c058 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Mar 2018 01:21:38 +0100 Subject: [PATCH 2/4] De-generalise expectValue in SlashSyntaxSpec --- .../src/test/scala/sbt/SlashSyntaxSpec.scala | 32 +++---------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala b/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala index ea1bcf2ea..2c843d989 100644 --- a/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala +++ b/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala @@ -117,33 +117,6 @@ object BuildDSLInstances { } import BuildDSLInstances._ -object CustomEquality { - trait Eq[A] { - def equal(x: A, y: A): Boolean - } - - // Avoid reimplementing equality for other standard classes. - trait EqualLowPriority { - implicit def universal[A] = (x: A, y: A) => x == y - } - - object Eq extends EqualLowPriority { - def apply[A: Eq]: Eq[A] = implicitly - - implicit def eqScoped[A <: Scoped]: Eq[A] = (x, y) => x.scope == y.scope && x.key == y.key - } - - implicit class AnyWith_===[A](private val x: A) extends AnyVal { - def ===(y: A)(implicit z: Eq[A]): Boolean = z.equal(x, y) - def =?(y: A)(implicit z: Eq[A]): Prop = { - if (x === y) proved else falsified :| s"Expected $x but got $y" - } - } - - def expectValue[A: Eq](expected: A)(x: A) = expected =? x -} -import CustomEquality._ - object SlashSyntaxSpec extends Properties("SlashSyntax") with SlashSyntax { type Key[K] = Scoped.ScopingSetting[K] with Scoped @@ -296,4 +269,9 @@ object SlashSyntaxSpec extends Properties("SlashSyntax") with SlashSyntax { expectValue(k in ThisScope.copy(project = r, config = c, task = t))(r / c / t / k)) check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] } + + def expectValue(expected: Scoped)(x: Scoped) = { + val equals = x.scope == expected.scope && x.key == expected.key + if (equals) proved else falsified :| s"Expected $expected but got $x" + } } From 42b61a4f8ebfdcb3344bfc83812da3216f5717f0 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Mar 2018 02:14:33 +0100 Subject: [PATCH 3/4] Dedup keys in SlashSyntaxSpec --- .../src/test/scala/sbt/SlashSyntaxSpec.scala | 145 +++++------------- 1 file changed, 41 insertions(+), 104 deletions(-) diff --git a/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala b/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala index 2c843d989..804031cb3 100644 --- a/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala +++ b/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala @@ -82,6 +82,8 @@ object BuildDSLInstances { } yield Scope(r, c, t, e) ) + type Key = K forSome { type K <: Scoped.ScopingSetting[K] with Scoped } + def genInputKey[A: Manifest]: Gen[InputKey[A]] = Gen.identifier map (InputKey[A](_)) def genSettingKey[A: Manifest]: Gen[SettingKey[A]] = Gen.identifier map (SettingKey[A](_)) def genTaskKey[A: Manifest]: Gen[TaskKey[A]] = Gen.identifier map (TaskKey[A](_)) @@ -97,16 +99,18 @@ object BuildDSLInstances { implicit def arbSettingKey[A: Manifest]: Arbitrary[SettingKey[A]] = withScope(genSettingKey[A]) implicit def arbTaskKey[A: Manifest]: Arbitrary[TaskKey[A]] = withScope(genTaskKey[A]) - implicit def arbScoped[A: Manifest](implicit + implicit def arbKey[A: Manifest]( + implicit arbInputKey: Arbitrary[InputKey[A]], arbSettingKey: Arbitrary[SettingKey[A]], arbTaskKey: Arbitrary[TaskKey[A]], - ): Arbitrary[Scoped] = { - Arbitrary(Gen.frequency( - 15 -> arbitrary[InputKey[A]], // 15,431 - 20 -> arbitrary[SettingKey[A]], // 19,645 - 23 -> arbitrary[TaskKey[A]], // 22,867 - )) + ): Arbitrary[Key] = Arbitrary { + def convert[T](g: Gen[T]) = g.asInstanceOf[Gen[Key]] + Gen.frequency( + 15431 -> convert(arbitrary[InputKey[A]]), + 19645 -> convert(arbitrary[SettingKey[A]]), + 22867 -> convert(arbitrary[TaskKey[A]]), + ) } object WithoutScope { @@ -114,160 +118,93 @@ object BuildDSLInstances { implicit def arbSettingKey[A: Manifest]: Arbitrary[SettingKey[A]] = Arbitrary(genSettingKey[A]) implicit def arbTaskKey[A: Manifest]: Arbitrary[TaskKey[A]] = Arbitrary(genTaskKey[A]) } + + implicit def arbScoped[A: Manifest]: Arbitrary[Scoped] = Arbitrary(arbitrary[Key]) } import BuildDSLInstances._ object SlashSyntaxSpec extends Properties("SlashSyntax") with SlashSyntax { - type Key[K] = Scoped.ScopingSetting[K] with Scoped - property("Global / key == key in Global") = { - def check[K <: Key[K]: Arbitrary] = forAll((k: K) => expectValue(k in Global)(Global / k)) - check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] + forAll((k: Key) => expectValue(k in Global)(Global / k)) } property("Reference / key == key in Reference") = { - def check[K <: Key[K]: Arbitrary] = forAll((r: Reference, k: K) => expectValue(k in r)(r / k)) - check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] + forAll((r: Reference, k: Key) => expectValue(k in r)(r / k)) } property("Reference / Config / key == key in Reference in Config") = { - def check[K <: Key[K]: Arbitrary] = - forAll((r: Reference, c: ConfigKey, k: K) => expectValue(k in r in c)(r / c / k)) - check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] + forAll((r: Reference, c: ConfigKey, k: Key) => expectValue(k in r in c)(r / c / k)) } property("Reference / task.key / key == key in Reference in task") = { - def check[K <: Key[K]: Arbitrary] = - forAll((r: Reference, t: Scoped, k: K) => expectValue(k in (r, t))(r / t.key / k)) - check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] + forAll((r: Reference, t: Scoped, k: Key) => expectValue(k in (r, t))(r / t.key / k)) } property("Reference / task / key ~= key in Reference in task") = { import WithoutScope._ - def check[T <: Key[T]: Arbitrary, K <: Key[K]: Arbitrary] = - forAll((r: Reference, t: T, k: K) => expectValue(k in (r, t))(r / t / k)) - (true - && check[InputKey[String], InputKey[String]] - && check[InputKey[String], SettingKey[String]] - && check[InputKey[String], TaskKey[String]] - && check[SettingKey[String], InputKey[String]] - && check[SettingKey[String], SettingKey[String]] - && check[SettingKey[String], TaskKey[String]] - && check[TaskKey[String], InputKey[String]] - && check[TaskKey[String], SettingKey[String]] - && check[TaskKey[String], TaskKey[String]] - ) + forAll((r: Reference, t: Key, k: Key) => expectValue(k in (r, t))(r / t / k)) } property("Reference / Config / task.key / key == key in Reference in Config in task") = { - def check[K <: Key[K]: Arbitrary] = - forAll((r: Reference, c: ConfigKey, t: Scoped, k: K) => - expectValue(k in (r, c, t))(r / c / t.key / k)) - check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] + forAll { (r: Reference, c: ConfigKey, t: Scoped, k: Key) => + expectValue(k in (r, c, t))(r / c / t.key / k) + } } property("Reference / Config / task / key ~= key in Reference in Config in task") = { import WithoutScope._ - def check[T <: Key[T]: Arbitrary, K <: Key[K]: Arbitrary] = - forAll((r: Reference, c: ConfigKey, t: T, k: K) => expectValue(k in (r, c, t))(r / c / t / k)) - (true - && check[InputKey[String], InputKey[String]] - && check[InputKey[String], SettingKey[String]] - && check[InputKey[String], TaskKey[String]] - && check[SettingKey[String], InputKey[String]] - && check[SettingKey[String], SettingKey[String]] - && check[SettingKey[String], TaskKey[String]] - && check[TaskKey[String], InputKey[String]] - && check[TaskKey[String], SettingKey[String]] - && check[TaskKey[String], TaskKey[String]] - ) + forAll { (r: Reference, c: ConfigKey, t: Key, k: Key) => + expectValue(k in (r, c, t))(r / c / t / k) + } } property("Config / key == key in Config") = { - def check[K <: Key[K]: Arbitrary] = - forAll((c: ConfigKey, k: K) => expectValue(k in c)(c / k)) - check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] + forAll((c: ConfigKey, k: Key) => expectValue(k in c)(c / k)) } property("Config / task.key / key == key in Config in task") = { - def check[K <: Key[K]: Arbitrary] = - forAll((c: ConfigKey, t: Scoped, k: K) => expectValue(k in c in t)(c / t.key / k)) - check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] + forAll((c: ConfigKey, t: Scoped, k: Key) => expectValue(k in c in t)(c / t.key / k)) } property("Config / task / key ~= key in Config in task") = { import WithoutScope._ - def check[T <: Key[T]: Arbitrary, K <: Key[K]: Arbitrary] = - forAll((c: ConfigKey, t: T, k: K) => expectValue(k in c in t)(c / t / k)) - (true - && check[InputKey[String], InputKey[String]] - && check[InputKey[String], SettingKey[String]] - && check[InputKey[String], TaskKey[String]] - && check[SettingKey[String], InputKey[String]] - && check[SettingKey[String], SettingKey[String]] - && check[SettingKey[String], TaskKey[String]] - && check[TaskKey[String], InputKey[String]] - && check[TaskKey[String], SettingKey[String]] - && check[TaskKey[String], TaskKey[String]] - ) + forAll((c: ConfigKey, t: Key, k: Key) => expectValue(k in c in t)(c / t / k)) } property("task.key / key == key in task") = { - def check[K <: Key[K]: Arbitrary] = - forAll((t: Scoped, k: K) => expectValue(k in t)(t.key / k)) - check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] + forAll((t: Scoped, k: Key) => expectValue(k in t)(t.key / k)) } property("task / key ~= key in task") = { import WithoutScope._ - def check[T <: Key[T]: Arbitrary, K <: Key[K]: Arbitrary] = - forAll((t: T, k: K) => expectValue(k in t)(t / k)) - (true - && check[InputKey[String], InputKey[String]] - && check[InputKey[String], SettingKey[String]] - && check[InputKey[String], TaskKey[String]] - && check[SettingKey[String], InputKey[String]] - && check[SettingKey[String], SettingKey[String]] - && check[SettingKey[String], TaskKey[String]] - && check[TaskKey[String], InputKey[String]] - && check[TaskKey[String], SettingKey[String]] - && check[TaskKey[String], TaskKey[String]] - ) + forAll((t: Key, k: Key) => expectValue(k in t)(t / k)) } property("Scope / key == key in Scope") = { - def check[K <: Key[K]: Arbitrary] = forAll((s: Scope, k: K) => expectValue(k in s)(s / k)) - check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] + forAll((s: Scope, k: Key) => expectValue(k in s)(s / k)) } property("Reference? / key == key in ThisScope.copy(..)") = { - def check[K <: Key[K]: Arbitrary] = - forAll((r: ScopeAxis[Reference], k: K) => - expectValue(k in ThisScope.copy(project = r))(r / k)) - check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] + forAll { (r: ScopeAxis[Reference], k: Key) => + expectValue(k in ThisScope.copy(project = r))(r / k) + } } property("Reference? / ConfigKey? / key == key in ThisScope.copy(..)") = { - def check[K <: Key[K]: Arbitrary] = - forAll((r: ScopeAxis[Reference], c: ScopeAxis[ConfigKey], k: K) => - expectValue(k in ThisScope.copy(project = r, config = c))(r / c / k)) - check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] + forAll((r: ScopeAxis[Reference], c: ScopeAxis[ConfigKey], k: Key) => + expectValue(k in ThisScope.copy(project = r, config = c))(r / c / k)) } // property("Reference? / AttributeKey? / key == key in ThisScope.copy(..)") = { -// def check[K <: Key[K]: Arbitrary] = -// forAll( -// (r: ScopeAxis[Reference], t: ScopeAxis[AttributeKey[_]], k: K) => -// expectValue(k in ThisScope.copy(project = r, task = t))(r / t / k)) -// check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] +// forAll((r: ScopeAxis[Reference], t: ScopeAxis[AttributeKey[_]], k: AnyKey) => +// expectValue(k in ThisScope.copy(project = r, task = t))(r / t / k)) // } property("Reference? / ConfigKey? / AttributeKey? / key == key in ThisScope.copy(..)") = { - def check[K <: Key[K]: Arbitrary] = - forAll( - (r: ScopeAxis[Reference], c: ScopeAxis[ConfigKey], t: ScopeAxis[AttributeKey[_]], k: K) => - expectValue(k in ThisScope.copy(project = r, config = c, task = t))(r / c / t / k)) - check[InputKey[String]] && check[SettingKey[String]] && check[TaskKey[String]] + forAll { + (r: ScopeAxis[Reference], c: ScopeAxis[ConfigKey], t: ScopeAxis[AttributeKey[_]], k: Key) => + expectValue(k in ThisScope.copy(project = r, config = c, task = t))(r / c / t / k) + } } def expectValue(expected: Scoped)(x: Scoped) = { From 3c66f39744d054b073dd9755abb111455b372589 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 27 Mar 2018 09:14:55 +0100 Subject: [PATCH 4/4] Allow SlashSyntaxSpec to be Scalafmt formatted Previously: [warn] /d/sbt/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala:44: error: illegal start of simple expression [warn] ) [warn] ^ --- .../src/test/scala/sbt/SlashSyntaxSpec.scala | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala b/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala index 804031cb3..e68d3ba0a 100644 --- a/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala +++ b/main-settings/src/test/scala/sbt/SlashSyntaxSpec.scala @@ -13,7 +13,16 @@ import java.io.File import sbt.io.IO import sbt.SlashSyntax import sbt.{ Scope, ScopeAxis, Scoped, Select, This, Zero }, Scope.{ Global, ThisScope } -import sbt.{ BuildRef, LocalProject, LocalRootProject, ProjectRef, Reference, RootProject, ThisBuild, ThisProject } +import sbt.{ + BuildRef, + LocalProject, + LocalRootProject, + ProjectRef, + Reference, + RootProject, + ThisBuild, + ThisProject +} import sbt.ConfigKey import sbt.librarymanagement.syntax._ import sbt.{ InputKey, SettingKey, TaskKey } @@ -34,13 +43,13 @@ object BuildDSLInstances { implicit val arbReference: Arbitrary[Reference] = Arbitrary { Gen.frequency( - 1 -> arbitrary[BuildRef], // 96 - 100 -> ThisBuild, // 10,271 - 3 -> LocalRootProject, // 325 - 23 -> arbitrary[ProjectRef], // 2,283 - 3 -> ThisProject, // 299 - 4 -> arbitrary[LocalProject], // 436 - 11 -> arbitrary[RootProject], // 1,133 + 96 -> arbitrary[BuildRef], + 10271 -> ThisBuild, + 325 -> LocalRootProject, + 2283 -> arbitrary[ProjectRef], + 299 -> ThisProject, + 436 -> arbitrary[LocalProject], + 1133 -> arbitrary[RootProject], ) }