From 9f9de600ee8b762d2bf2e363b3aded1177eb7e62 Mon Sep 17 00:00:00 2001 From: Josh Suereth Date: Wed, 7 May 2014 11:52:23 -0400 Subject: [PATCH] Scalariforming test code --- cache/src/test/scala/CacheTest.scala | 41 ++- .../src/test/scala/DagSpecification.scala | 78 +++-- util/collection/src/test/scala/KeyTest.scala | 55 ++-- .../src/test/scala/LiteralTest.scala | 8 +- util/collection/src/test/scala/PMapTest.scala | 19 +- .../src/test/scala/SettingsExample.scala | 116 +++---- .../src/test/scala/SettingsTest.scala | 303 +++++++++--------- util/complete/src/test/scala/ParserTest.scala | 250 +++++++-------- .../scala/sbt/complete/FileExamplesTest.scala | 132 ++++---- .../sbt/complete/FixedSetExamplesTest.scala | 32 +- .../sbt/complete/ParserWithExamplesTest.scala | 136 ++++---- util/log/src/test/scala/Escapes.scala | 133 ++++---- util/log/src/test/scala/LogWriterTest.scala | 252 +++++++-------- util/log/src/test/scala/TestLogger.scala | 15 +- .../logic/src/test/scala/sbt/logic/Test.scala | 194 ++++++----- .../src/test/scala/ProcessSpecification.scala | 226 +++++++------ .../src/test/scala/TestedProcess.scala | 91 +++--- .../src/test/scala/RelationTest.scala | 128 ++++---- 18 files changed, 1080 insertions(+), 1129 deletions(-) diff --git a/cache/src/test/scala/CacheTest.scala b/cache/src/test/scala/CacheTest.scala index 481bfb9b6..cbb7319b7 100644 --- a/cache/src/test/scala/CacheTest.scala +++ b/cache/src/test/scala/CacheTest.scala @@ -3,30 +3,29 @@ package sbt import java.io.File import Types.:+: -object CacheTest// extends Properties("Cache test") +object CacheTest // extends Properties("Cache test") { - val lengthCache = new File("/tmp/length-cache") - val cCache = new File("/tmp/c-cache") + val lengthCache = new File("/tmp/length-cache") + val cCache = new File("/tmp/c-cache") - import Cache._ - import FileInfo.hash._ - import Ordering._ - import sbinary.DefaultProtocol.FileFormat - def test - { - lazy val create = new File("test") + import Cache._ + import FileInfo.hash._ + import Ordering._ + import sbinary.DefaultProtocol.FileFormat + def test { + lazy val create = new File("test") - val length = cached(lengthCache) { - (f: File) => { println("File length: " + f.length); f.length } - } + val length = cached(lengthCache) { + (f: File) => { println("File length: " + f.length); f.length } + } - lazy val fileLength = length(create) + lazy val fileLength = length(create) - val c = cached(cCache) { (in: (File :+: Long :+: HNil)) => - val file :+: len :+: HNil = in - println("File: " + file + " (" + file.exists + "), length: " + len) - (len+1) :+: file :+: HNil - } - c(create :+: fileLength :+: HNil) - } + val c = cached(cCache) { (in: (File :+: Long :+: HNil)) => + val file :+: len :+: HNil = in + println("File: " + file + " (" + file.exists + "), length: " + len) + (len + 1) :+: file :+: HNil + } + c(create :+: fileLength :+: HNil) + } } \ No newline at end of file diff --git a/util/collection/src/test/scala/DagSpecification.scala b/util/collection/src/test/scala/DagSpecification.scala index 77ff80120..abf9ddf28 100644 --- a/util/collection/src/test/scala/DagSpecification.scala +++ b/util/collection/src/test/scala/DagSpecification.scala @@ -8,49 +8,43 @@ import Prop._ import scala.collection.mutable.HashSet -object DagSpecification extends Properties("Dag") -{ - property("No repeated nodes") = forAll{ (dag: TestDag) => isSet(dag.topologicalSort) } - property("Sort contains node") = forAll{ (dag: TestDag) => dag.topologicalSort.contains(dag) } - property("Dependencies precede node") = forAll{ (dag: TestDag) => dependenciesPrecedeNodes(dag.topologicalSort) } +object DagSpecification extends Properties("Dag") { + property("No repeated nodes") = forAll { (dag: TestDag) => isSet(dag.topologicalSort) } + property("Sort contains node") = forAll { (dag: TestDag) => dag.topologicalSort.contains(dag) } + property("Dependencies precede node") = forAll { (dag: TestDag) => dependenciesPrecedeNodes(dag.topologicalSort) } - implicit lazy val arbTestDag: Arbitrary[TestDag] = Arbitrary(Gen.sized(dagGen)) - private def dagGen(nodeCount: Int): Gen[TestDag] = - { - val nodes = new HashSet[TestDag] - def nonterminalGen(p: Gen.Parameters): Gen[TestDag] = - { - for(i <- 0 until nodeCount; nextDeps <- Gen.someOf(nodes).apply(p)) - nodes += new TestDag(i, nextDeps) - for(nextDeps <- Gen.someOf(nodes)) yield - new TestDag(nodeCount, nextDeps) - } - Gen.parameterized(nonterminalGen) - } + implicit lazy val arbTestDag: Arbitrary[TestDag] = Arbitrary(Gen.sized(dagGen)) + private def dagGen(nodeCount: Int): Gen[TestDag] = + { + val nodes = new HashSet[TestDag] + def nonterminalGen(p: Gen.Parameters): Gen[TestDag] = + { + for (i <- 0 until nodeCount; nextDeps <- Gen.someOf(nodes).apply(p)) + nodes += new TestDag(i, nextDeps) + for (nextDeps <- Gen.someOf(nodes)) yield new TestDag(nodeCount, nextDeps) + } + Gen.parameterized(nonterminalGen) + } - private def isSet[T](c: Seq[T]) = Set(c: _*).size == c.size - private def dependenciesPrecedeNodes(sort: List[TestDag]) = - { - val seen = new HashSet[TestDag] - def iterate(remaining: List[TestDag]): Boolean = - { - remaining match - { - case Nil => true - case node :: tail => - if(node.dependencies.forall(seen.contains) && !seen.contains(node)) - { - seen += node - iterate(tail) - } - else - false - } - } - iterate(sort) - } + private def isSet[T](c: Seq[T]) = Set(c: _*).size == c.size + private def dependenciesPrecedeNodes(sort: List[TestDag]) = + { + val seen = new HashSet[TestDag] + def iterate(remaining: List[TestDag]): Boolean = + { + remaining match { + case Nil => true + case node :: tail => + if (node.dependencies.forall(seen.contains) && !seen.contains(node)) { + seen += node + iterate(tail) + } else + false + } + } + iterate(sort) + } } -class TestDag(id: Int, val dependencies: Iterable[TestDag]) extends Dag[TestDag] -{ - override def toString = id + "->" + dependencies.mkString("[", ",", "]") +class TestDag(id: Int, val dependencies: Iterable[TestDag]) extends Dag[TestDag] { + override def toString = id + "->" + dependencies.mkString("[", ",", "]") } \ No newline at end of file diff --git a/util/collection/src/test/scala/KeyTest.scala b/util/collection/src/test/scala/KeyTest.scala index 9ac4f86bb..f48e3742a 100644 --- a/util/collection/src/test/scala/KeyTest.scala +++ b/util/collection/src/test/scala/KeyTest.scala @@ -1,35 +1,32 @@ package sbt - import org.scalacheck._ - import Prop._ +import org.scalacheck._ +import Prop._ -object KeyTest extends Properties("AttributeKey") -{ - property("equality") = { - compare(AttributeKey[Int]("test"), AttributeKey[Int]("test"), true) && - compare(AttributeKey[Int]("test"), AttributeKey[Int]("test", "description"), true) && - compare(AttributeKey[Int]("test", "a"), AttributeKey[Int]("test", "b"), true) && - compare(AttributeKey[Int]("test"), AttributeKey[Int]("tests"), false) && - compare(AttributeKey[Int]("test"), AttributeKey[Double]("test"), false) && - compare(AttributeKey[java.lang.Integer]("test"), AttributeKey[Int]("test"), false) && - compare(AttributeKey[Map[Int, String]]("test"), AttributeKey[Map[Int, String]]("test"), true) && - compare(AttributeKey[Map[Int, String]]("test"), AttributeKey[Map[Int, _]]("test"), false) - } +object KeyTest extends Properties("AttributeKey") { + property("equality") = { + compare(AttributeKey[Int]("test"), AttributeKey[Int]("test"), true) && + compare(AttributeKey[Int]("test"), AttributeKey[Int]("test", "description"), true) && + compare(AttributeKey[Int]("test", "a"), AttributeKey[Int]("test", "b"), true) && + compare(AttributeKey[Int]("test"), AttributeKey[Int]("tests"), false) && + compare(AttributeKey[Int]("test"), AttributeKey[Double]("test"), false) && + compare(AttributeKey[java.lang.Integer]("test"), AttributeKey[Int]("test"), false) && + compare(AttributeKey[Map[Int, String]]("test"), AttributeKey[Map[Int, String]]("test"), true) && + compare(AttributeKey[Map[Int, String]]("test"), AttributeKey[Map[Int, _]]("test"), false) + } - def compare(a: AttributeKey[_], b: AttributeKey[_], same: Boolean) = - ("a.label: " + a.label) |: - ("a.manifest: " + a.manifest) |: - ("b.label: " + b.label) |: - ("b.manifest: " + b.manifest) |: - ("expected equal? " + same) |: - compare0(a, b, same) + def compare(a: AttributeKey[_], b: AttributeKey[_], same: Boolean) = + ("a.label: " + a.label) |: + ("a.manifest: " + a.manifest) |: + ("b.label: " + b.label) |: + ("b.manifest: " + b.manifest) |: + ("expected equal? " + same) |: + compare0(a, b, same) - def compare0(a: AttributeKey[_], b: AttributeKey[_], same: Boolean) = - if(same) - { - ("equality" |: (a == b)) && - ("hash" |: (a.hashCode == b.hashCode)) - } - else - ("equality" |: (a != b)) + def compare0(a: AttributeKey[_], b: AttributeKey[_], same: Boolean) = + if (same) { + ("equality" |: (a == b)) && + ("hash" |: (a.hashCode == b.hashCode)) + } else + ("equality" |: (a != b)) } \ No newline at end of file diff --git a/util/collection/src/test/scala/LiteralTest.scala b/util/collection/src/test/scala/LiteralTest.scala index 76fffe80a..35ef373ca 100644 --- a/util/collection/src/test/scala/LiteralTest.scala +++ b/util/collection/src/test/scala/LiteralTest.scala @@ -7,11 +7,11 @@ import Types._ // compilation test object LiteralTest { - def x[A[_],B[_]](f: A ~> B) = f + def x[A[_], B[_]](f: A ~> B) = f import Param._ - val f = x { (p: Param[Option,List]) => p.ret( p.in.toList ) } + val f = x { (p: Param[Option, List]) => p.ret(p.in.toList) } - val a: List[Int] = f( Some(3) ) - val b: List[String] = f( Some("aa") ) + val a: List[Int] = f(Some(3)) + val b: List[String] = f(Some("aa")) } \ No newline at end of file diff --git a/util/collection/src/test/scala/PMapTest.scala b/util/collection/src/test/scala/PMapTest.scala index 7970e175e..6a6c558c1 100644 --- a/util/collection/src/test/scala/PMapTest.scala +++ b/util/collection/src/test/scala/PMapTest.scala @@ -6,14 +6,13 @@ package sbt import Types._ // compilation test -object PMapTest -{ - val mp = new DelegatingPMap[Some, Id](new collection.mutable.HashMap) - mp(Some("asdf")) = "a" - mp(Some(3)) = 9 - val x = Some(3) :^: Some("asdf") :^: KNil - val y = x.transform[Id](mp) - assert(y.head == 9) - assert(y.tail.head == "a") - assert(y.tail.tail == KNil) +object PMapTest { + val mp = new DelegatingPMap[Some, Id](new collection.mutable.HashMap) + mp(Some("asdf")) = "a" + mp(Some(3)) = 9 + val x = Some(3) :^: Some("asdf") :^: KNil + val y = x.transform[Id](mp) + assert(y.head == 9) + assert(y.tail.head == "a") + assert(y.tail.tail == KNil) } \ No newline at end of file diff --git a/util/collection/src/test/scala/SettingsExample.scala b/util/collection/src/test/scala/SettingsExample.scala index 9d863be31..b48bb27fc 100644 --- a/util/collection/src/test/scala/SettingsExample.scala +++ b/util/collection/src/test/scala/SettingsExample.scala @@ -10,78 +10,78 @@ final case class Scope(nestIndex: Int, idAtIndex: Int = 0) // Lots of type constructors would become binary, which as you may know requires lots of type lambdas // when you want a type function with only one parameter. // That would be a general pain.) -object SettingsExample extends Init[Scope] -{ - // Provides a way of showing a Scope+AttributeKey[_] - val showFullKey: Show[ScopedKey[_]] = new Show[ScopedKey[_]] { - def apply(key: ScopedKey[_]) = s"${key.scope.nestIndex}(${key.scope.idAtIndex})/${key.key.label}" - } +object SettingsExample extends Init[Scope] { + // Provides a way of showing a Scope+AttributeKey[_] + val showFullKey: Show[ScopedKey[_]] = new Show[ScopedKey[_]] { + def apply(key: ScopedKey[_]) = s"${key.scope.nestIndex}(${key.scope.idAtIndex})/${key.key.label}" + } - // A sample delegation function that delegates to a Scope with a lower index. - val delegates: Scope => Seq[Scope] = { case s @ Scope(index, proj) => - s +: (if(index <= 0) Nil else { (if (proj > 0) List(Scope(index)) else Nil) ++: delegates(Scope(index-1)) }) - } + // A sample delegation function that delegates to a Scope with a lower index. + val delegates: Scope => Seq[Scope] = { + case s @ Scope(index, proj) => + s +: (if (index <= 0) Nil else { (if (proj > 0) List(Scope(index)) else Nil) ++: delegates(Scope(index - 1)) }) + } - // Not using this feature in this example. - val scopeLocal: ScopeLocal = _ => Nil + // Not using this feature in this example. + val scopeLocal: ScopeLocal = _ => Nil - // These three functions + a scope (here, Scope) are sufficient for defining our settings system. + // These three functions + a scope (here, Scope) are sufficient for defining our settings system. } /** Usage Example **/ -object SettingsUsage -{ - import SettingsExample._ - import Types._ +object SettingsUsage { + import SettingsExample._ + import Types._ - // Define some keys - val a = AttributeKey[Int]("a") - val b = AttributeKey[Int]("b") + // Define some keys + val a = AttributeKey[Int]("a") + val b = AttributeKey[Int]("b") - // Scope these keys - val a3 = ScopedKey(Scope(3), a) - val a4 = ScopedKey(Scope(4), a) - val a5 = ScopedKey(Scope(5), a) + // Scope these keys + val a3 = ScopedKey(Scope(3), a) + val a4 = ScopedKey(Scope(4), a) + val a5 = ScopedKey(Scope(5), a) - val b4 = ScopedKey(Scope(4), b) + val b4 = ScopedKey(Scope(4), b) - // Define some settings - val mySettings: Seq[Setting[_]] = Seq( - setting( a3, value( 3 ) ), - setting( b4, map(a4)(_ * 3)), - update(a5)(_ + 1) - ) + // Define some settings + val mySettings: Seq[Setting[_]] = Seq( + setting(a3, value(3)), + setting(b4, map(a4)(_ * 3)), + update(a5)(_ + 1) + ) - // "compiles" and applies the settings. - // This can be split into multiple steps to access intermediate results if desired. - // The 'inspect' command operates on the output of 'compile', for example. - val applied: Settings[Scope] = make(mySettings)(delegates, scopeLocal, showFullKey) + // "compiles" and applies the settings. + // This can be split into multiple steps to access intermediate results if desired. + // The 'inspect' command operates on the output of 'compile', for example. + val applied: Settings[Scope] = make(mySettings)(delegates, scopeLocal, showFullKey) - // Show results. -/* for(i <- 0 to 5; k <- Seq(a, b)) { + // Show results. + /* for(i <- 0 to 5; k <- Seq(a, b)) { println( k.label + i + " = " + applied.get( Scope(i), k) ) }*/ -/** Output: -* For the None results, we never defined the value and there was no value to delegate to. -* For a3, we explicitly defined it to be 3. -* a4 wasn't defined, so it delegates to a3 according to our delegates function. -* b4 gets the value for a4 (which delegates to a3, so it is 3) and multiplies by 3 -* a5 is defined as the previous value of a5 + 1 and -* since no previous value of a5 was defined, it delegates to a4, resulting in 3+1=4. -* b5 isn't defined explicitly, so it delegates to b4 and is therefore equal to 9 as well -a0 = None -b0 = None -a1 = None -b1 = None -a2 = None -b2 = None -a3 = Some(3) -b3 = None -a4 = Some(3) -b4 = Some(9) -a5 = Some(4) -b5 = Some(9) -**/ + /** + * Output: + * For the None results, we never defined the value and there was no value to delegate to. + * For a3, we explicitly defined it to be 3. + * a4 wasn't defined, so it delegates to a3 according to our delegates function. + * b4 gets the value for a4 (which delegates to a3, so it is 3) and multiplies by 3 + * a5 is defined as the previous value of a5 + 1 and + * since no previous value of a5 was defined, it delegates to a4, resulting in 3+1=4. + * b5 isn't defined explicitly, so it delegates to b4 and is therefore equal to 9 as well + * a0 = None + * b0 = None + * a1 = None + * b1 = None + * a2 = None + * b2 = None + * a3 = Some(3) + * b3 = None + * a4 = Some(3) + * b4 = Some(9) + * a5 = Some(4) + * b5 = Some(9) + */ } diff --git a/util/collection/src/test/scala/SettingsTest.scala b/util/collection/src/test/scala/SettingsTest.scala index 1bdea8f38..f8c99a735 100644 --- a/util/collection/src/test/scala/SettingsTest.scala +++ b/util/collection/src/test/scala/SettingsTest.scala @@ -5,175 +5,174 @@ import Prop._ import SettingsUsage._ import SettingsExample._ -object SettingsTest extends Properties("settings") -{ +object SettingsTest extends Properties("settings") { - import scala.reflect.Manifest + import scala.reflect.Manifest - final val ChainMax = 5000 - lazy val chainLengthGen = Gen.choose(1, ChainMax) + final val ChainMax = 5000 + lazy val chainLengthGen = Gen.choose(1, ChainMax) - property("Basic settings test") = secure( all( tests: _*) ) + property("Basic settings test") = secure(all(tests: _*)) - property("Basic chain") = forAll(chainLengthGen) { (i: Int) => - val abs = math.abs(i) - singleIntTest( chain( abs, value(0)), abs ) - } - property("Basic bind chain") = forAll(chainLengthGen) { (i: Int) => - val abs = math.abs(i) - singleIntTest( chainBind(value(abs)), 0 ) - } + property("Basic chain") = forAll(chainLengthGen) { (i: Int) => + val abs = math.abs(i) + singleIntTest(chain(abs, value(0)), abs) + } + property("Basic bind chain") = forAll(chainLengthGen) { (i: Int) => + val abs = math.abs(i) + singleIntTest(chainBind(value(abs)), 0) + } - property("Allows references to completed settings") = forAllNoShrink(30) { allowedReference } - final def allowedReference(intermediate: Int): Prop = - { - val top = value(intermediate) - def iterate(init: Initialize[Int]): Initialize[Int] = - bind(init) { t => - if(t <= 0) - top - else - iterate(value(t-1) ) - } - evaluate( setting(chk, iterate(top)) :: Nil); true - } + property("Allows references to completed settings") = forAllNoShrink(30) { allowedReference } + final def allowedReference(intermediate: Int): Prop = + { + val top = value(intermediate) + def iterate(init: Initialize[Int]): Initialize[Int] = + bind(init) { t => + if (t <= 0) + top + else + iterate(value(t - 1)) + } + evaluate(setting(chk, iterate(top)) :: Nil); true + } - property("Derived setting chain depending on (prev derived, normal setting)") = forAllNoShrink(Gen.choose(1, 100)) { derivedSettings } - final def derivedSettings(nr: Int): Prop = - { - val genScopedKeys = { - val attrKeys = mkAttrKeys[Int](nr) - attrKeys map (_ map (ak => ScopedKey(Scope(0), ak))) - } - forAll(genScopedKeys) { scopedKeys => - val last = scopedKeys.last - val derivedSettings: Seq[Setting[Int]] = ( - for { - List(scoped0, scoped1) <- chk :: scopedKeys sliding 2 - nextInit = if (scoped0 == chk) chk - else (scoped0 zipWith chk) { (p, _) => p + 1 } - } yield derive(setting(scoped1, nextInit)) - ).toSeq + property("Derived setting chain depending on (prev derived, normal setting)") = forAllNoShrink(Gen.choose(1, 100)) { derivedSettings } + final def derivedSettings(nr: Int): Prop = + { + val genScopedKeys = { + val attrKeys = mkAttrKeys[Int](nr) + attrKeys map (_ map (ak => ScopedKey(Scope(0), ak))) + } + forAll(genScopedKeys) { scopedKeys => + val last = scopedKeys.last + val derivedSettings: Seq[Setting[Int]] = ( + for { + List(scoped0, scoped1) <- chk :: scopedKeys sliding 2 + nextInit = if (scoped0 == chk) chk + else (scoped0 zipWith chk) { (p, _) => p + 1 } + } yield derive(setting(scoped1, nextInit)) + ).toSeq - { checkKey(last, Some(nr-1), evaluate(setting(chk, value(0)) +: derivedSettings)) :| "Not derived?" } && - { checkKey( last, None, evaluate(derivedSettings)) :| "Should not be derived" } - } - } + { checkKey(last, Some(nr - 1), evaluate(setting(chk, value(0)) +: derivedSettings)) :| "Not derived?" } && + { checkKey(last, None, evaluate(derivedSettings)) :| "Should not be derived" } + } + } - private def mkAttrKeys[T](nr: Int)(implicit mf: Manifest[T]): Gen[List[AttributeKey[T]]] = - { - val alphaStr = Gen.alphaStr - for { - list <- Gen.listOfN(nr, alphaStr) suchThat (l => l.size == l.distinct.size) - item <- list - } yield AttributeKey[T](item) - } + private def mkAttrKeys[T](nr: Int)(implicit mf: Manifest[T]): Gen[List[AttributeKey[T]]] = + { + val alphaStr = Gen.alphaStr + for { + list <- Gen.listOfN(nr, alphaStr) suchThat (l => l.size == l.distinct.size) + item <- list + } yield AttributeKey[T](item) + } - property("Derived setting(s) replace DerivedSetting in the Seq[Setting[_]]") = derivedKeepsPosition - final def derivedKeepsPosition: Prop = - { - val a: ScopedKey[Int] = ScopedKey(Scope(0), AttributeKey[Int]("a")) - val b: ScopedKey[Int] = ScopedKey(Scope(0), AttributeKey[Int]("b")) - val prop1 = { - val settings: Seq[Setting[_]] = Seq( - setting(a, value(3)), - setting(b, value(6)), - derive(setting(b, a)), - setting(a, value(5)), - setting(b, value(8)) - ) - val ev = evaluate(settings) - checkKey(a, Some(5), ev) && checkKey(b, Some(8), ev) - } - val prop2 = { - val settings: Seq[Setting[Int]] = Seq( - setting(a, value(3)), - setting(b, value(6)), - derive(setting(b, a)), - setting(a, value(5)) - ) - val ev = evaluate(settings) - checkKey(a, Some(5), ev) && checkKey(b, Some(5), ev) - } - prop1 && prop2 - } + property("Derived setting(s) replace DerivedSetting in the Seq[Setting[_]]") = derivedKeepsPosition + final def derivedKeepsPosition: Prop = + { + val a: ScopedKey[Int] = ScopedKey(Scope(0), AttributeKey[Int]("a")) + val b: ScopedKey[Int] = ScopedKey(Scope(0), AttributeKey[Int]("b")) + val prop1 = { + val settings: Seq[Setting[_]] = Seq( + setting(a, value(3)), + setting(b, value(6)), + derive(setting(b, a)), + setting(a, value(5)), + setting(b, value(8)) + ) + val ev = evaluate(settings) + checkKey(a, Some(5), ev) && checkKey(b, Some(8), ev) + } + val prop2 = { + val settings: Seq[Setting[Int]] = Seq( + setting(a, value(3)), + setting(b, value(6)), + derive(setting(b, a)), + setting(a, value(5)) + ) + val ev = evaluate(settings) + checkKey(a, Some(5), ev) && checkKey(b, Some(5), ev) + } + prop1 && prop2 + } - property("DerivedSetting in ThisBuild scopes derived settings under projects thus allowing safe +=") = forAllNoShrink(Gen.choose(1, 100)) { derivedSettingsScope } - final def derivedSettingsScope(nrProjects: Int): Prop = - { - forAll(mkAttrKeys[Int](2)) { case List(key, derivedKey) => - val projectKeys = for { proj <- 1 to nrProjects } yield ScopedKey(Scope(1, proj), key) - val projectDerivedKeys = for { proj <- 1 to nrProjects } yield ScopedKey(Scope(1, proj), derivedKey) - val globalKey = ScopedKey(Scope(0), key) - val globalDerivedKey = ScopedKey(Scope(0), derivedKey) - // Each project defines an initial value, but the update is defined in globalKey. - // However, the derived Settings that come from this should be scoped in each project. - val settings: Seq[Setting[_]] = - derive(setting(globalDerivedKey, SettingsExample.map(globalKey)(_ + 1))) +: projectKeys.map(pk => setting(pk, value(0))) - val ev = evaluate(settings) - // Also check that the key has no value at the "global" scope - val props = for { pk <- projectDerivedKeys } yield checkKey(pk, Some(1), ev) - checkKey(globalDerivedKey, None, ev) && Prop.all(props: _*) - } - } + property("DerivedSetting in ThisBuild scopes derived settings under projects thus allowing safe +=") = forAllNoShrink(Gen.choose(1, 100)) { derivedSettingsScope } + final def derivedSettingsScope(nrProjects: Int): Prop = + { + forAll(mkAttrKeys[Int](2)) { + case List(key, derivedKey) => + val projectKeys = for { proj <- 1 to nrProjects } yield ScopedKey(Scope(1, proj), key) + val projectDerivedKeys = for { proj <- 1 to nrProjects } yield ScopedKey(Scope(1, proj), derivedKey) + val globalKey = ScopedKey(Scope(0), key) + val globalDerivedKey = ScopedKey(Scope(0), derivedKey) + // Each project defines an initial value, but the update is defined in globalKey. + // However, the derived Settings that come from this should be scoped in each project. + val settings: Seq[Setting[_]] = + derive(setting(globalDerivedKey, SettingsExample.map(globalKey)(_ + 1))) +: projectKeys.map(pk => setting(pk, value(0))) + val ev = evaluate(settings) + // Also check that the key has no value at the "global" scope + val props = for { pk <- projectDerivedKeys } yield checkKey(pk, Some(1), ev) + checkKey(globalDerivedKey, None, ev) && Prop.all(props: _*) + } + } -// Circular (dynamic) references currently loop infinitely. -// This is the expected behavior (detecting dynamic cycles is expensive), -// but it may be necessary to provide an option to detect them (with a performance hit) -// This would test that cycle detection. -// property("Catches circular references") = forAll(chainLengthGen) { checkCircularReferences _ } - final def checkCircularReferences(intermediate: Int): Prop = - { - val ccr = new CCR(intermediate) - try { evaluate( setting(chk, ccr.top) :: Nil); false } - catch { case e: java.lang.Exception => true } - } + // Circular (dynamic) references currently loop infinitely. + // This is the expected behavior (detecting dynamic cycles is expensive), + // but it may be necessary to provide an option to detect them (with a performance hit) + // This would test that cycle detection. + // property("Catches circular references") = forAll(chainLengthGen) { checkCircularReferences _ } + final def checkCircularReferences(intermediate: Int): Prop = + { + val ccr = new CCR(intermediate) + try { evaluate(setting(chk, ccr.top) :: Nil); false } + catch { case e: java.lang.Exception => true } + } - def tests = - for(i <- 0 to 5; k <- Seq(a, b)) yield { - val expected = expectedValues(2*i + (if(k == a) 0 else 1)) - checkKey[Int]( ScopedKey( Scope(i), k ), expected, applied) - } + def tests = + for (i <- 0 to 5; k <- Seq(a, b)) yield { + val expected = expectedValues(2 * i + (if (k == a) 0 else 1)) + checkKey[Int](ScopedKey(Scope(i), k), expected, applied) + } - lazy val expectedValues = None :: None :: None :: None :: None :: None :: Some(3) :: None :: Some(3) :: Some(9) :: Some(4) :: Some(9) :: Nil + lazy val expectedValues = None :: None :: None :: None :: None :: None :: Some(3) :: None :: Some(3) :: Some(9) :: Some(4) :: Some(9) :: Nil - lazy val ch = AttributeKey[Int]("ch") - lazy val chk = ScopedKey( Scope(0), ch) - def chain(i: Int, prev: Initialize[Int]): Initialize[Int] = - if(i <= 0) prev else chain(i - 1, prev(_ + 1)) + lazy val ch = AttributeKey[Int]("ch") + lazy val chk = ScopedKey(Scope(0), ch) + def chain(i: Int, prev: Initialize[Int]): Initialize[Int] = + if (i <= 0) prev else chain(i - 1, prev(_ + 1)) - def chainBind(prev: Initialize[Int]): Initialize[Int] = - bind(prev) { v => - if(v <= 0) prev else chainBind(value(v - 1) ) - } - def singleIntTest(i: Initialize[Int], expected: Int) = - { - val eval = evaluate( setting( chk, i ) :: Nil ) - checkKey( chk, Some(expected), eval ) - } + def chainBind(prev: Initialize[Int]): Initialize[Int] = + bind(prev) { v => + if (v <= 0) prev else chainBind(value(v - 1)) + } + def singleIntTest(i: Initialize[Int], expected: Int) = + { + val eval = evaluate(setting(chk, i) :: Nil) + checkKey(chk, Some(expected), eval) + } - def checkKey[T](key: ScopedKey[T], expected: Option[T], settings: Settings[Scope]) = - { - val value = settings.get( key.scope, key.key) - ("Key: " + key) |: - ("Value: " + value) |: - ("Expected: " + expected) |: - (value == expected) - } + def checkKey[T](key: ScopedKey[T], expected: Option[T], settings: Settings[Scope]) = + { + val value = settings.get(key.scope, key.key) + ("Key: " + key) |: + ("Value: " + value) |: + ("Expected: " + expected) |: + (value == expected) + } - def evaluate(settings: Seq[Setting[_]]): Settings[Scope] = - try { make(settings)(delegates, scopeLocal, showFullKey) } - catch { case e: Throwable => e.printStackTrace; throw e } + def evaluate(settings: Seq[Setting[_]]): Settings[Scope] = + try { make(settings)(delegates, scopeLocal, showFullKey) } + catch { case e: Throwable => e.printStackTrace; throw e } } // This setup is a workaround for module synchronization issues -final class CCR(intermediate: Int) -{ - lazy val top = iterate(value(intermediate), intermediate) - def iterate(init: Initialize[Int], i: Int): Initialize[Int] = - bind(init) { t => - if(t <= 0) - top - else - iterate(value(t - 1), t-1) - } +final class CCR(intermediate: Int) { + lazy val top = iterate(value(intermediate), intermediate) + def iterate(init: Initialize[Int], i: Int): Initialize[Int] = + bind(init) { t => + if (t <= 0) + top + else + iterate(value(t - 1), t - 1) + } } diff --git a/util/complete/src/test/scala/ParserTest.scala b/util/complete/src/test/scala/ParserTest.scala index 78ee28dc0..53d6cb1db 100644 --- a/util/complete/src/test/scala/ParserTest.scala +++ b/util/complete/src/test/scala/ParserTest.scala @@ -1,154 +1,148 @@ package sbt.complete -object JLineTest -{ - import DefaultParsers._ +object JLineTest { + import DefaultParsers._ - val one = "blue" | "green" | "black" - val two = token("color" ~> Space) ~> token(one) - val three = token("color" ~> Space) ~> token(ID.examples("blue", "green", "black")) - val four = token("color" ~> Space) ~> token(ID, "") + val one = "blue" | "green" | "black" + val two = token("color" ~> Space) ~> token(one) + val three = token("color" ~> Space) ~> token(ID.examples("blue", "green", "black")) + val four = token("color" ~> Space) ~> token(ID, "") - val num = token(NatBasic) - val five = (num ~ token("+" | "-") ~ num) <~ token('=') flatMap { - case a ~ "+" ~ b => token((a+b).toString) - case a ~ "-" ~ b => token((a-b).toString) - } + val num = token(NatBasic) + val five = (num ~ token("+" | "-") ~ num) <~ token('=') flatMap { + case a ~ "+" ~ b => token((a + b).toString) + case a ~ "-" ~ b => token((a - b).toString) + } - val parsers = Map("1" -> one, "2" -> two, "3" -> three, "4" -> four, "5" -> five) - def main(args: Array[String]) - { - import jline.TerminalFactory - import jline.console.ConsoleReader - val reader = new ConsoleReader() - TerminalFactory.get.init + val parsers = Map("1" -> one, "2" -> two, "3" -> three, "4" -> four, "5" -> five) + def main(args: Array[String]) { + import jline.TerminalFactory + import jline.console.ConsoleReader + val reader = new ConsoleReader() + TerminalFactory.get.init - val parser = parsers(args(0)) - JLineCompletion.installCustomCompletor(reader, parser) - def loop() { - val line = reader.readLine("> ") - if(line ne null) { - println("Result: " + apply(parser)(line).resultEmpty) - loop() - } - } - loop() - } + val parser = parsers(args(0)) + JLineCompletion.installCustomCompletor(reader, parser) + def loop() { + val line = reader.readLine("> ") + if (line ne null) { + println("Result: " + apply(parser)(line).resultEmpty) + loop() + } + } + loop() + } } - import Parser._ - import org.scalacheck._ +import Parser._ +import org.scalacheck._ -object ParserTest extends Properties("Completing Parser") -{ - import Parsers._ - import DefaultParsers.matches +object ParserTest extends Properties("Completing Parser") { + import Parsers._ + import DefaultParsers.matches - val nested = (token("a1") ~ token("b2")) ~ "c3" - val nestedDisplay = (token("a1", "") ~ token("b2", "")) ~ "c3" + val nested = (token("a1") ~ token("b2")) ~ "c3" + val nestedDisplay = (token("a1", "") ~ token("b2", "")) ~ "c3" - val spacePort = (token(Space) ~> Port) + val spacePort = (token(Space) ~> Port) - def p[T](f: T): T = { println(f); f } + def p[T](f: T): T = { println(f); f } - def checkSingle(in: String, expect: Completion)(expectDisplay: Completion = expect) = - ( ("token '" + in + "'") |: checkOne(in, nested, expect)) && - ( ("display '" + in + "'") |: checkOne(in, nestedDisplay, expectDisplay) ) - - def checkOne(in: String, parser: Parser[_], expect: Completion): Prop = - completions(parser, in, 1) == Completions.single(expect) + def checkSingle(in: String, expect: Completion)(expectDisplay: Completion = expect) = + (("token '" + in + "'") |: checkOne(in, nested, expect)) && + (("display '" + in + "'") |: checkOne(in, nestedDisplay, expectDisplay)) - def checkAll(in: String, parser: Parser[_], expect: Completions): Prop = - { - val cs = completions(parser, in, 1) - ("completions: " + cs) |: ("Expected: " + expect) |: ( (cs == expect): Prop) - } - - def checkInvalid(in: String) = - ( ("token '" + in + "'") |: checkInv(in, nested) ) && - ( ("display '" + in + "'") |: checkInv(in, nestedDisplay) ) + def checkOne(in: String, parser: Parser[_], expect: Completion): Prop = + completions(parser, in, 1) == Completions.single(expect) - def checkInv(in: String, parser: Parser[_]): Prop = - { - val cs = completions(parser, in, 1) - ("completions: " + cs) |: (( cs == Completions.nil): Prop) - } - - property("nested tokens a") = checkSingle("", Completion.tokenStrict("","a1") )( Completion.displayStrict("")) - property("nested tokens a1") = checkSingle("a", Completion.tokenStrict("a","1") )( Completion.displayStrict("")) - property("nested tokens a inv") = checkInvalid("b") - property("nested tokens b") = checkSingle("a1", Completion.tokenStrict("","b2") )( Completion.displayStrict("")) - property("nested tokens b2") = checkSingle("a1b", Completion.tokenStrict("b","2") )( Completion.displayStrict("")) - property("nested tokens b inv") = checkInvalid("a1a") - property("nested tokens c") = checkSingle("a1b2", Completion.suggestStrict("c3") )() - property("nested tokens c3") = checkSingle("a1b2c", Completion.suggestStrict("3"))() - property("nested tokens c inv") = checkInvalid("a1b2a") + def checkAll(in: String, parser: Parser[_], expect: Completions): Prop = + { + val cs = completions(parser, in, 1) + ("completions: " + cs) |: ("Expected: " + expect) |: ((cs == expect): Prop) + } - property("suggest space") = checkOne("", spacePort, Completion.tokenStrict("", " ")) - property("suggest port") = checkOne(" ", spacePort, Completion.displayStrict("") ) - property("no suggest at end") = checkOne("asdf", "asdf", Completion.suggestStrict("")) - property("no suggest at token end") = checkOne("asdf", token("asdf"), Completion.suggestStrict("")) - property("empty suggest for examples") = checkOne("asdf", any.+.examples("asdf", "qwer"), Completion.suggestStrict("")) - property("empty suggest for examples token") = checkOne("asdf", token(any.+.examples("asdf", "qwer")), Completion.suggestStrict("")) + def checkInvalid(in: String) = + (("token '" + in + "'") |: checkInv(in, nested)) && + (("display '" + in + "'") |: checkInv(in, nestedDisplay)) - val colors = Set("blue", "green", "red") - val base = (seen: Seq[String]) => token( ID examples (colors -- seen) ) - val sep = token( Space ) - val repeat = repeatDep( base, sep) - def completionStrings(ss: Set[String]): Completions = Completions(ss.map { s => Completion.tokenStrict("", s) }) + def checkInv(in: String, parser: Parser[_]): Prop = + { + val cs = completions(parser, in, 1) + ("completions: " + cs) |: ((cs == Completions.nil): Prop) + } - property("repeatDep no suggestions for bad input") = checkInv(".", repeat) - property("repeatDep suggest all") = checkAll("", repeat, completionStrings(colors)) - property("repeatDep suggest remaining two") = { - val first = colors.toSeq.head - checkAll(first + " ", repeat, completionStrings(colors - first)) - } - property("repeatDep suggest remaining one") = { - val take = colors.toSeq.take(2) - checkAll(take.mkString("", " ", " "), repeat, completionStrings(colors -- take)) - } - property("repeatDep requires at least one token") = !matches(repeat, "") - property("repeatDep accepts one token") = matches(repeat, colors.toSeq.head) - property("repeatDep accepts two tokens") = matches(repeat, colors.toSeq.take(2).mkString(" ")) + property("nested tokens a") = checkSingle("", Completion.tokenStrict("", "a1"))(Completion.displayStrict("")) + property("nested tokens a1") = checkSingle("a", Completion.tokenStrict("a", "1"))(Completion.displayStrict("")) + property("nested tokens a inv") = checkInvalid("b") + property("nested tokens b") = checkSingle("a1", Completion.tokenStrict("", "b2"))(Completion.displayStrict("")) + property("nested tokens b2") = checkSingle("a1b", Completion.tokenStrict("b", "2"))(Completion.displayStrict("")) + property("nested tokens b inv") = checkInvalid("a1a") + property("nested tokens c") = checkSingle("a1b2", Completion.suggestStrict("c3"))() + property("nested tokens c3") = checkSingle("a1b2c", Completion.suggestStrict("3"))() + property("nested tokens c inv") = checkInvalid("a1b2a") + + property("suggest space") = checkOne("", spacePort, Completion.tokenStrict("", " ")) + property("suggest port") = checkOne(" ", spacePort, Completion.displayStrict("")) + property("no suggest at end") = checkOne("asdf", "asdf", Completion.suggestStrict("")) + property("no suggest at token end") = checkOne("asdf", token("asdf"), Completion.suggestStrict("")) + property("empty suggest for examples") = checkOne("asdf", any.+.examples("asdf", "qwer"), Completion.suggestStrict("")) + property("empty suggest for examples token") = checkOne("asdf", token(any.+.examples("asdf", "qwer")), Completion.suggestStrict("")) + + val colors = Set("blue", "green", "red") + val base = (seen: Seq[String]) => token(ID examples (colors -- seen)) + val sep = token(Space) + val repeat = repeatDep(base, sep) + def completionStrings(ss: Set[String]): Completions = Completions(ss.map { s => Completion.tokenStrict("", s) }) + + property("repeatDep no suggestions for bad input") = checkInv(".", repeat) + property("repeatDep suggest all") = checkAll("", repeat, completionStrings(colors)) + property("repeatDep suggest remaining two") = { + val first = colors.toSeq.head + checkAll(first + " ", repeat, completionStrings(colors - first)) + } + property("repeatDep suggest remaining one") = { + val take = colors.toSeq.take(2) + checkAll(take.mkString("", " ", " "), repeat, completionStrings(colors -- take)) + } + property("repeatDep requires at least one token") = !matches(repeat, "") + property("repeatDep accepts one token") = matches(repeat, colors.toSeq.head) + property("repeatDep accepts two tokens") = matches(repeat, colors.toSeq.take(2).mkString(" ")) } -object ParserExample -{ - val ws = charClass(_.isWhitespace)+ - val notws = charClass(!_.isWhitespace)+ +object ParserExample { + val ws = charClass(_.isWhitespace)+ + val notws = charClass(!_.isWhitespace)+ - val name = token("test") - val options = (ws ~> token("quick" | "failed" | "new") )* - val exampleSet = Set("am", "is", "are", "was", "were") - val include = (ws ~> token(examples(notws.string, new FixedSetExamples(exampleSet), exampleSet.size, false )) )* + val name = token("test") + val options = (ws ~> token("quick" | "failed" | "new"))* + val exampleSet = Set("am", "is", "are", "was", "were") + val include = (ws ~> token(examples(notws.string, new FixedSetExamples(exampleSet), exampleSet.size, false)))* - val t = name ~ options ~ include + val t = name ~ options ~ include - // Get completions for some different inputs - println(completions(t, "te", 1)) - println(completions(t, "test ",1)) - println(completions(t, "test w", 1)) + // Get completions for some different inputs + println(completions(t, "te", 1)) + println(completions(t, "test ", 1)) + println(completions(t, "test w", 1)) - // Get the parsed result for different inputs - println(apply(t)("te").resultEmpty) - println(apply(t)("test").resultEmpty) - println(apply(t)("test w").resultEmpty) - println(apply(t)("test was were").resultEmpty) + // Get the parsed result for different inputs + println(apply(t)("te").resultEmpty) + println(apply(t)("test").resultEmpty) + println(apply(t)("test w").resultEmpty) + println(apply(t)("test was were").resultEmpty) - def run(n: Int) - { - val a = 'a'.id - val aq = a.? - val aqn = repeat(aq, min = n, max = n) - val an = repeat(a, min = n, max = n) - val ann = aqn ~ an + def run(n: Int) { + val a = 'a'.id + val aq = a.? + val aqn = repeat(aq, min = n, max = n) + val an = repeat(a, min = n, max = n) + val ann = aqn ~ an - def r = apply(ann)("a"*(n*2)).resultEmpty - println(r.isValid) - } - def run2(n: Int) - { - val ab = "ab".?.* - val r = apply(ab)("a"*n).resultEmpty - println(r) - } + def r = apply(ann)("a" * (n * 2)).resultEmpty + println(r.isValid) + } + def run2(n: Int) { + val ab = "ab".?.* + val r = apply(ab)("a" * n).resultEmpty + println(r) + } } \ No newline at end of file diff --git a/util/complete/src/test/scala/sbt/complete/FileExamplesTest.scala b/util/complete/src/test/scala/sbt/complete/FileExamplesTest.scala index 08c9a5884..03b495bf0 100644 --- a/util/complete/src/test/scala/sbt/complete/FileExamplesTest.scala +++ b/util/complete/src/test/scala/sbt/complete/FileExamplesTest.scala @@ -6,87 +6,85 @@ import sbt.IO.withTemporaryDirectory import java.io.File import sbt.IO._ -class FileExamplesTest extends Specification -{ +class FileExamplesTest extends Specification { - "listing all files in an absolute base directory" should { - "produce the entire base directory's contents" in new directoryStructure { - fileExamples().toList should containTheSameElementsAs(allRelativizedPaths) - } - } + "listing all files in an absolute base directory" should { + "produce the entire base directory's contents" in new directoryStructure { + fileExamples().toList should containTheSameElementsAs(allRelativizedPaths) + } + } - "listing files with a prefix that matches none" should { - "produce an empty list" in new directoryStructure(withCompletionPrefix = "z") { - fileExamples().toList should beEmpty - } - } + "listing files with a prefix that matches none" should { + "produce an empty list" in new directoryStructure(withCompletionPrefix = "z") { + fileExamples().toList should beEmpty + } + } - "listing single-character prefixed files" should { - "produce matching paths only" in new directoryStructure(withCompletionPrefix = "f") { - fileExamples().toList should containTheSameElementsAs(prefixedPathsOnly) - } - } + "listing single-character prefixed files" should { + "produce matching paths only" in new directoryStructure(withCompletionPrefix = "f") { + fileExamples().toList should containTheSameElementsAs(prefixedPathsOnly) + } + } - "listing directory-prefixed files" should { - "produce matching paths only" in new directoryStructure(withCompletionPrefix = "far") { - fileExamples().toList should containTheSameElementsAs(prefixedPathsOnly) - } + "listing directory-prefixed files" should { + "produce matching paths only" in new directoryStructure(withCompletionPrefix = "far") { + fileExamples().toList should containTheSameElementsAs(prefixedPathsOnly) + } - "produce sub-dir contents only when appending a file separator to the directory" in new directoryStructure(withCompletionPrefix = "far" + File.separator) { - fileExamples().toList should containTheSameElementsAs(prefixedPathsOnly) - } - } + "produce sub-dir contents only when appending a file separator to the directory" in new directoryStructure(withCompletionPrefix = "far" + File.separator) { + fileExamples().toList should containTheSameElementsAs(prefixedPathsOnly) + } + } - "listing files with a sub-path prefix" should { - "produce matching paths only" in new directoryStructure(withCompletionPrefix = "far" + File.separator + "ba") { - fileExamples().toList should containTheSameElementsAs(prefixedPathsOnly) - } - } + "listing files with a sub-path prefix" should { + "produce matching paths only" in new directoryStructure(withCompletionPrefix = "far" + File.separator + "ba") { + fileExamples().toList should containTheSameElementsAs(prefixedPathsOnly) + } + } - "completing a full path" should { - "produce a list with an empty string" in new directoryStructure(withCompletionPrefix = "bazaar") { - fileExamples().toList shouldEqual List("") - } - } + "completing a full path" should { + "produce a list with an empty string" in new directoryStructure(withCompletionPrefix = "bazaar") { + fileExamples().toList shouldEqual List("") + } + } - class directoryStructure(withCompletionPrefix: String = "") extends Scope with DelayedInit - { - var fileExamples: FileExamples = _ - var baseDir: File = _ - var childFiles: List[File] = _ - var childDirectories: List[File] = _ - var nestedFiles: List[File] = _ - var nestedDirectories: List[File] = _ + class directoryStructure(withCompletionPrefix: String = "") extends Scope with DelayedInit { + var fileExamples: FileExamples = _ + var baseDir: File = _ + var childFiles: List[File] = _ + var childDirectories: List[File] = _ + var nestedFiles: List[File] = _ + var nestedDirectories: List[File] = _ - def allRelativizedPaths: List[String] = - (childFiles ++ childDirectories ++ nestedFiles ++ nestedDirectories).map(relativize(baseDir, _).get) + def allRelativizedPaths: List[String] = + (childFiles ++ childDirectories ++ nestedFiles ++ nestedDirectories).map(relativize(baseDir, _).get) - def prefixedPathsOnly: List[String] = - allRelativizedPaths.filter(_ startsWith withCompletionPrefix).map(_ substring withCompletionPrefix.length) + def prefixedPathsOnly: List[String] = + allRelativizedPaths.filter(_ startsWith withCompletionPrefix).map(_ substring withCompletionPrefix.length) - override def delayedInit(testBody: => Unit): Unit = { - withTemporaryDirectory { - tempDir => - createSampleDirStructure(tempDir) - fileExamples = new FileExamples(baseDir, withCompletionPrefix) - testBody - } - } + override def delayedInit(testBody: => Unit): Unit = { + withTemporaryDirectory { + tempDir => + createSampleDirStructure(tempDir) + fileExamples = new FileExamples(baseDir, withCompletionPrefix) + testBody + } + } - private def createSampleDirStructure(tempDir: File): Unit = { - childFiles = toChildFiles(tempDir, List("foo", "bar", "bazaar")) - childDirectories = toChildFiles(tempDir, List("moo", "far")) - nestedFiles = toChildFiles(childDirectories(1), List("farfile1", "barfile2")) - nestedDirectories = toChildFiles(childDirectories(1), List("fardir1", "bardir2")) + private def createSampleDirStructure(tempDir: File): Unit = { + childFiles = toChildFiles(tempDir, List("foo", "bar", "bazaar")) + childDirectories = toChildFiles(tempDir, List("moo", "far")) + nestedFiles = toChildFiles(childDirectories(1), List("farfile1", "barfile2")) + nestedDirectories = toChildFiles(childDirectories(1), List("fardir1", "bardir2")) - (childDirectories ++ nestedDirectories).map(_.mkdirs()) - (childFiles ++ nestedFiles).map(_.createNewFile()) + (childDirectories ++ nestedDirectories).map(_.mkdirs()) + (childFiles ++ nestedFiles).map(_.createNewFile()) - // NOTE: Creating a new file here because `tempDir.listFiles()` returned an empty list. - baseDir = new File(tempDir.getCanonicalPath) - } + // NOTE: Creating a new file here because `tempDir.listFiles()` returned an empty list. + baseDir = new File(tempDir.getCanonicalPath) + } - private def toChildFiles(baseDir: File, files: List[String]): List[File] = files.map(new File(baseDir, _)) - } + private def toChildFiles(baseDir: File, files: List[String]): List[File] = files.map(new File(baseDir, _)) + } } diff --git a/util/complete/src/test/scala/sbt/complete/FixedSetExamplesTest.scala b/util/complete/src/test/scala/sbt/complete/FixedSetExamplesTest.scala index b9a5b2de2..b5aa14250 100644 --- a/util/complete/src/test/scala/sbt/complete/FixedSetExamplesTest.scala +++ b/util/complete/src/test/scala/sbt/complete/FixedSetExamplesTest.scala @@ -5,22 +5,22 @@ import org.specs2.specification.Scope class FixedSetExamplesTest extends Specification { - "adding a prefix" should { - "produce a smaller set of examples with the prefix removed" in new examples { - fixedSetExamples.withAddedPrefix("f")() must containTheSameElementsAs(List("oo", "ool", "u")) - fixedSetExamples.withAddedPrefix("fo")() must containTheSameElementsAs(List("o", "ol")) - fixedSetExamples.withAddedPrefix("b")() must containTheSameElementsAs(List("ar")) - } - } + "adding a prefix" should { + "produce a smaller set of examples with the prefix removed" in new examples { + fixedSetExamples.withAddedPrefix("f")() must containTheSameElementsAs(List("oo", "ool", "u")) + fixedSetExamples.withAddedPrefix("fo")() must containTheSameElementsAs(List("o", "ol")) + fixedSetExamples.withAddedPrefix("b")() must containTheSameElementsAs(List("ar")) + } + } - "without a prefix" should { - "produce the original set" in new examples { - fixedSetExamples() mustEqual exampleSet - } - } + "without a prefix" should { + "produce the original set" in new examples { + fixedSetExamples() mustEqual exampleSet + } + } - trait examples extends Scope { - val exampleSet = List("foo", "bar", "fool", "fu") - val fixedSetExamples = FixedSetExamples(exampleSet) - } + trait examples extends Scope { + val exampleSet = List("foo", "bar", "fool", "fu") + val fixedSetExamples = FixedSetExamples(exampleSet) + } } diff --git a/util/complete/src/test/scala/sbt/complete/ParserWithExamplesTest.scala b/util/complete/src/test/scala/sbt/complete/ParserWithExamplesTest.scala index 1151e1b0d..dff68803c 100644 --- a/util/complete/src/test/scala/sbt/complete/ParserWithExamplesTest.scala +++ b/util/complete/src/test/scala/sbt/complete/ParserWithExamplesTest.scala @@ -6,88 +6,88 @@ import Completion._ class ParserWithExamplesTest extends Specification { - "listing a limited number of completions" should { - "grab only the needed number of elements from the iterable source of examples" in new parserWithLazyExamples { - parserWithExamples.completions(0) - examples.size shouldEqual maxNumberOfExamples - } - } + "listing a limited number of completions" should { + "grab only the needed number of elements from the iterable source of examples" in new parserWithLazyExamples { + parserWithExamples.completions(0) + examples.size shouldEqual maxNumberOfExamples + } + } - "listing only valid completions" should { - "use the delegate parser to remove invalid examples" in new parserWithValidExamples { - val validCompletions = Completions(Set( - suggestion("blue"), - suggestion("red") - )) - parserWithExamples.completions(0) shouldEqual validCompletions - } - } + "listing only valid completions" should { + "use the delegate parser to remove invalid examples" in new parserWithValidExamples { + val validCompletions = Completions(Set( + suggestion("blue"), + suggestion("red") + )) + parserWithExamples.completions(0) shouldEqual validCompletions + } + } - "listing valid completions in a derived parser" should { - "produce only valid examples that start with the character of the derivation" in new parserWithValidExamples { - val derivedCompletions = Completions(Set( - suggestion("lue") - )) - parserWithExamples.derive('b').completions(0) shouldEqual derivedCompletions - } - } + "listing valid completions in a derived parser" should { + "produce only valid examples that start with the character of the derivation" in new parserWithValidExamples { + val derivedCompletions = Completions(Set( + suggestion("lue") + )) + parserWithExamples.derive('b').completions(0) shouldEqual derivedCompletions + } + } - "listing valid and invalid completions" should { - "produce the entire source of examples" in new parserWithAllExamples { - val completions = Completions(examples.map(suggestion(_)).toSet) - parserWithExamples.completions(0) shouldEqual completions - } - } + "listing valid and invalid completions" should { + "produce the entire source of examples" in new parserWithAllExamples { + val completions = Completions(examples.map(suggestion(_)).toSet) + parserWithExamples.completions(0) shouldEqual completions + } + } - "listing valid and invalid completions in a derived parser" should { - "produce only examples that start with the character of the derivation" in new parserWithAllExamples { - val derivedCompletions = Completions(Set( - suggestion("lue"), - suggestion("lock") - )) - parserWithExamples.derive('b').completions(0) shouldEqual derivedCompletions - } - } + "listing valid and invalid completions in a derived parser" should { + "produce only examples that start with the character of the derivation" in new parserWithAllExamples { + val derivedCompletions = Completions(Set( + suggestion("lue"), + suggestion("lock") + )) + parserWithExamples.derive('b').completions(0) shouldEqual derivedCompletions + } + } - class parserWithLazyExamples extends parser(GrowableSourceOfExamples(), maxNumberOfExamples = 5, removeInvalidExamples = false) + class parserWithLazyExamples extends parser(GrowableSourceOfExamples(), maxNumberOfExamples = 5, removeInvalidExamples = false) - class parserWithValidExamples extends parser(removeInvalidExamples = true) + class parserWithValidExamples extends parser(removeInvalidExamples = true) - class parserWithAllExamples extends parser(removeInvalidExamples = false) + class parserWithAllExamples extends parser(removeInvalidExamples = false) - case class parser(examples: Iterable[String] = Set("blue", "yellow", "greeen", "block", "red"), - maxNumberOfExamples: Int = 25, - removeInvalidExamples: Boolean) extends Scope { + case class parser(examples: Iterable[String] = Set("blue", "yellow", "greeen", "block", "red"), + maxNumberOfExamples: Int = 25, + removeInvalidExamples: Boolean) extends Scope { - import DefaultParsers._ + import DefaultParsers._ - val colorParser = "blue" | "green" | "black" | "red" - val parserWithExamples: Parser[String] = new ParserWithExamples[String]( - colorParser, - FixedSetExamples(examples), - maxNumberOfExamples, - removeInvalidExamples - ) - } + val colorParser = "blue" | "green" | "black" | "red" + val parserWithExamples: Parser[String] = new ParserWithExamples[String]( + colorParser, + FixedSetExamples(examples), + maxNumberOfExamples, + removeInvalidExamples + ) + } - case class GrowableSourceOfExamples() extends Iterable[String] { - private var numberOfIteratedElements: Int = 0 + case class GrowableSourceOfExamples() extends Iterable[String] { + private var numberOfIteratedElements: Int = 0 - override def iterator: Iterator[String] = { - new Iterator[String] { - var currentElement = 0 + override def iterator: Iterator[String] = { + new Iterator[String] { + var currentElement = 0 - override def next(): String = { - currentElement += 1 - numberOfIteratedElements = Math.max(currentElement, numberOfIteratedElements) - numberOfIteratedElements.toString - } + override def next(): String = { + currentElement += 1 + numberOfIteratedElements = Math.max(currentElement, numberOfIteratedElements) + numberOfIteratedElements.toString + } - override def hasNext: Boolean = true - } - } + override def hasNext: Boolean = true + } + } - override def size: Int = numberOfIteratedElements - } + override def size: Int = numberOfIteratedElements + } } diff --git a/util/log/src/test/scala/Escapes.scala b/util/log/src/test/scala/Escapes.scala index f90499574..f780d25bf 100644 --- a/util/log/src/test/scala/Escapes.scala +++ b/util/log/src/test/scala/Escapes.scala @@ -2,90 +2,85 @@ package sbt import org.scalacheck._ import Prop._ -import Gen.{listOf, oneOf} +import Gen.{ listOf, oneOf } -import ConsoleLogger.{ESC, hasEscapeSequence, isEscapeTerminator, removeEscapeSequences} +import ConsoleLogger.{ ESC, hasEscapeSequence, isEscapeTerminator, removeEscapeSequences } -object Escapes extends Properties("Escapes") -{ - property("genTerminator only generates terminators") = - forAllNoShrink(genTerminator) { (c: Char) => isEscapeTerminator(c) } +object Escapes extends Properties("Escapes") { + property("genTerminator only generates terminators") = + forAllNoShrink(genTerminator) { (c: Char) => isEscapeTerminator(c) } - property("genWithoutTerminator only generates terminators") = - forAllNoShrink(genWithoutTerminator) { (s: String) => - s.forall { c => !isEscapeTerminator(c) } - } + property("genWithoutTerminator only generates terminators") = + forAllNoShrink(genWithoutTerminator) { (s: String) => + s.forall { c => !isEscapeTerminator(c) } + } - property("hasEscapeSequence is false when no escape character is present") = forAllNoShrink(genWithoutEscape) { (s: String) => - !hasEscapeSequence(s) - } + property("hasEscapeSequence is false when no escape character is present") = forAllNoShrink(genWithoutEscape) { (s: String) => + !hasEscapeSequence(s) + } - property("hasEscapeSequence is true when escape character is present") = forAllNoShrink(genWithRandomEscapes) { (s: String) => - hasEscapeSequence(s) - } + property("hasEscapeSequence is true when escape character is present") = forAllNoShrink(genWithRandomEscapes) { (s: String) => + hasEscapeSequence(s) + } - property("removeEscapeSequences is the identity when no escape character is present") = forAllNoShrink(genWithoutEscape) { (s: String) => - val removed: String = removeEscapeSequences(s) - ("Escape sequence removed: '" + removed + "'") |: - (removed == s) - } + property("removeEscapeSequences is the identity when no escape character is present") = forAllNoShrink(genWithoutEscape) { (s: String) => + val removed: String = removeEscapeSequences(s) + ("Escape sequence removed: '" + removed + "'") |: + (removed == s) + } - property("No escape characters remain after removeEscapeSequences") = forAll { (s: String) => - val removed: String = removeEscapeSequences(s) - ("Escape sequence removed: '" + removed + "'") |: - !hasEscapeSequence(removed) - } + property("No escape characters remain after removeEscapeSequences") = forAll { (s: String) => + val removed: String = removeEscapeSequences(s) + ("Escape sequence removed: '" + removed + "'") |: + !hasEscapeSequence(removed) + } - property("removeEscapeSequences returns string without escape sequences") = - forAllNoShrink( genWithoutEscape, genEscapePairs ) { (start: String, escapes: List[EscapeAndNot]) => - val withEscapes: String = start + escapes.map { ean => ean.escape.makeString + ean.notEscape } - val removed: String = removeEscapeSequences(withEscapes) - val original = start + escapes.map(_.notEscape) - ("Input string with escapes: '" + withEscapes + "'") |: - ("Escapes removed '" + removed + "'") |: - (original == removed) - } + property("removeEscapeSequences returns string without escape sequences") = + forAllNoShrink(genWithoutEscape, genEscapePairs) { (start: String, escapes: List[EscapeAndNot]) => + val withEscapes: String = start + escapes.map { ean => ean.escape.makeString + ean.notEscape } + val removed: String = removeEscapeSequences(withEscapes) + val original = start + escapes.map(_.notEscape) + ("Input string with escapes: '" + withEscapes + "'") |: + ("Escapes removed '" + removed + "'") |: + (original == removed) + } - final case class EscapeAndNot(escape: EscapeSequence, notEscape: String) - final case class EscapeSequence(content: String, terminator: Char) - { - assert( content.forall(c => !isEscapeTerminator(c) ), "Escape sequence content contains an escape terminator: '" + content + "'" ) - assert( isEscapeTerminator(terminator) ) - def makeString: String = ESC + content + terminator - } - private[this] def noEscape(s: String): String = s.replace(ESC, ' ') + final case class EscapeAndNot(escape: EscapeSequence, notEscape: String) + final case class EscapeSequence(content: String, terminator: Char) { + assert(content.forall(c => !isEscapeTerminator(c)), "Escape sequence content contains an escape terminator: '" + content + "'") + assert(isEscapeTerminator(terminator)) + def makeString: String = ESC + content + terminator + } + private[this] def noEscape(s: String): String = s.replace(ESC, ' ') - lazy val genEscapeSequence: Gen[EscapeSequence] = oneOf(genKnownSequence, genArbitraryEscapeSequence) - lazy val genEscapePair: Gen[EscapeAndNot] = for(esc <- genEscapeSequence; not <- genWithoutEscape) yield EscapeAndNot(esc, not) - lazy val genEscapePairs: Gen[List[EscapeAndNot]] = listOf(genEscapePair) + lazy val genEscapeSequence: Gen[EscapeSequence] = oneOf(genKnownSequence, genArbitraryEscapeSequence) + lazy val genEscapePair: Gen[EscapeAndNot] = for (esc <- genEscapeSequence; not <- genWithoutEscape) yield EscapeAndNot(esc, not) + lazy val genEscapePairs: Gen[List[EscapeAndNot]] = listOf(genEscapePair) - lazy val genArbitraryEscapeSequence: Gen[EscapeSequence] = - for(content <- genWithoutTerminator; term <- genTerminator) yield - new EscapeSequence(content, term) - - lazy val genKnownSequence: Gen[EscapeSequence] = - oneOf((misc ++ setGraphicsMode ++ setMode ++ resetMode).map(toEscapeSequence)) - - def toEscapeSequence(s: String): EscapeSequence = EscapeSequence(s.init, s.last) + lazy val genArbitraryEscapeSequence: Gen[EscapeSequence] = + for (content <- genWithoutTerminator; term <- genTerminator) yield new EscapeSequence(content, term) - lazy val misc = Seq("14;23H", "5;3f", "2A", "94B", "19C", "85D", "s", "u", "2J", "K") + lazy val genKnownSequence: Gen[EscapeSequence] = + oneOf((misc ++ setGraphicsMode ++ setMode ++ resetMode).map(toEscapeSequence)) - lazy val setGraphicsMode: Seq[String] = - for(txt <- 0 to 8; fg <- 30 to 37; bg <- 40 to 47) yield - txt.toString + ";" + fg.toString + ";" + bg.toString + "m" + def toEscapeSequence(s: String): EscapeSequence = EscapeSequence(s.init, s.last) - lazy val resetMode = setModeLike('I') - lazy val setMode = setModeLike('h') - def setModeLike(term: Char): Seq[String] = (0 to 19).map(i => "=" + i.toString + term) - - lazy val genWithoutTerminator = genRawString.map( _.filter { c => !isEscapeTerminator(c) } ) + lazy val misc = Seq("14;23H", "5;3f", "2A", "94B", "19C", "85D", "s", "u", "2J", "K") - lazy val genTerminator: Gen[Char] = Gen.choose('@', '~') - lazy val genWithoutEscape: Gen[String] = genRawString.map(noEscape) + lazy val setGraphicsMode: Seq[String] = + for (txt <- 0 to 8; fg <- 30 to 37; bg <- 40 to 47) yield txt.toString + ";" + fg.toString + ";" + bg.toString + "m" - def genWithRandomEscapes: Gen[String] = - for(ls <- listOf(genRawString); end <- genRawString) yield - ls.mkString("", ESC.toString, ESC.toString + end) + lazy val resetMode = setModeLike('I') + lazy val setMode = setModeLike('h') + def setModeLike(term: Char): Seq[String] = (0 to 19).map(i => "=" + i.toString + term) - private def genRawString = Arbitrary.arbString.arbitrary + lazy val genWithoutTerminator = genRawString.map(_.filter { c => !isEscapeTerminator(c) }) + + lazy val genTerminator: Gen[Char] = Gen.choose('@', '~') + lazy val genWithoutEscape: Gen[String] = genRawString.map(noEscape) + + def genWithRandomEscapes: Gen[String] = + for (ls <- listOf(genRawString); end <- genRawString) yield ls.mkString("", ESC.toString, ESC.toString + end) + + private def genRawString = Arbitrary.arbString.arbitrary } diff --git a/util/log/src/test/scala/LogWriterTest.scala b/util/log/src/test/scala/LogWriterTest.scala index 95736d524..d51919ad7 100644 --- a/util/log/src/test/scala/LogWriterTest.scala +++ b/util/log/src/test/scala/LogWriterTest.scala @@ -4,157 +4,147 @@ package sbt import org.scalacheck._ -import Arbitrary.{arbitrary => arb, _} -import Gen.{listOfN, oneOf} +import Arbitrary.{ arbitrary => arb, _ } +import Gen.{ listOfN, oneOf } import Prop._ import java.io.Writer -object LogWriterTest extends Properties("Log Writer") -{ - final val MaxLines = 100 - final val MaxSegments = 10 +object LogWriterTest extends Properties("Log Writer") { + final val MaxLines = 100 + final val MaxSegments = 10 - /* Tests that content written through a LoggerWriter is properly passed to the underlying Logger. + /* Tests that content written through a LoggerWriter is properly passed to the underlying Logger. * Each line, determined by the specified newline separator, must be logged at the correct logging level. */ - property("properly logged") = forAll { (output: Output, newLine: NewLine) => - import output.{lines, level} - val log = new RecordingLogger - val writer = new LoggerWriter(log, Some(level), newLine.str) - logLines(writer, lines, newLine.str) - val events = log.getEvents - ("Recorded:\n" + events.map(show).mkString("\n")) |: - check( toLines(lines), events, level) - } - - /** Displays a LogEvent in a useful format for debugging. In particular, we are only interested in `Log` types - * and non-printable characters should be escaped*/ - def show(event: LogEvent): String = - event match - { - case l: Log => "Log('" + Escape(l.msg) + "', " + l.level + ")" - case _ => "Not Log" - } - /** Writes the given lines to the Writer. `lines` is taken to be a list of lines, which are - * represented as separately written segments (ToLog instances). ToLog.`byCharacter` - * indicates whether to write the segment by character (true) or all at once (false)*/ - def logLines(writer: Writer, lines: List[List[ToLog]], newLine: String) - { - for(line <- lines; section <- line) - { - val content = section.content - val normalized = Escape.newline(content, newLine) - if(section.byCharacter) - normalized.foreach { c => writer.write(c.toInt) } - else - writer.write(normalized) - } - writer.flush() - } - - /** Converts the given lines in segments to lines as Strings for checking the results of the test.*/ - def toLines(lines: List[List[ToLog]]): List[String] = - lines.map(_.map(_.contentOnly).mkString) - /** Checks that the expected `lines` were recorded as `events` at level `Lvl`.*/ - def check(lines: List[String], events: List[LogEvent], Lvl: Level.Value): Boolean = - (lines zip events) forall { - case (line, log : Log) => log.level == Lvl && line == log.msg - case _ => false - } - - /* The following are implicit generators to build up a write sequence. + property("properly logged") = forAll { (output: Output, newLine: NewLine) => + import output.{ lines, level } + val log = new RecordingLogger + val writer = new LoggerWriter(log, Some(level), newLine.str) + logLines(writer, lines, newLine.str) + val events = log.getEvents + ("Recorded:\n" + events.map(show).mkString("\n")) |: + check(toLines(lines), events, level) + } + + /** + * Displays a LogEvent in a useful format for debugging. In particular, we are only interested in `Log` types + * and non-printable characters should be escaped + */ + def show(event: LogEvent): String = + event match { + case l: Log => "Log('" + Escape(l.msg) + "', " + l.level + ")" + case _ => "Not Log" + } + /** + * Writes the given lines to the Writer. `lines` is taken to be a list of lines, which are + * represented as separately written segments (ToLog instances). ToLog.`byCharacter` + * indicates whether to write the segment by character (true) or all at once (false) + */ + def logLines(writer: Writer, lines: List[List[ToLog]], newLine: String) { + for (line <- lines; section <- line) { + val content = section.content + val normalized = Escape.newline(content, newLine) + if (section.byCharacter) + normalized.foreach { c => writer.write(c.toInt) } + else + writer.write(normalized) + } + writer.flush() + } + + /** Converts the given lines in segments to lines as Strings for checking the results of the test.*/ + def toLines(lines: List[List[ToLog]]): List[String] = + lines.map(_.map(_.contentOnly).mkString) + /** Checks that the expected `lines` were recorded as `events` at level `Lvl`.*/ + def check(lines: List[String], events: List[LogEvent], Lvl: Level.Value): Boolean = + (lines zip events) forall { + case (line, log: Log) => log.level == Lvl && line == log.msg + case _ => false + } + + /* The following are implicit generators to build up a write sequence. * ToLog represents a written segment. NewLine represents one of the possible * newline separators. A List[ToLog] represents a full line and always includes a * final ToLog with a trailing '\n'. Newline characters are otherwise not present in * the `content` of a ToLog instance.*/ - - implicit lazy val arbOut: Arbitrary[Output] = Arbitrary(genOutput) - implicit lazy val arbLog: Arbitrary[ToLog] = Arbitrary(genLog) - implicit lazy val arbLine: Arbitrary[List[ToLog]] = Arbitrary(genLine) - implicit lazy val arbNewLine: Arbitrary[NewLine] = Arbitrary(genNewLine) - implicit lazy val arbLevel : Arbitrary[Level.Value] = Arbitrary(genLevel) - - implicit def genLine(implicit logG: Gen[ToLog]): Gen[List[ToLog]] = - for(l <- listOf[ToLog](MaxSegments); last <- logG) yield - (addNewline(last) :: l.filter(!_.content.isEmpty)).reverse - implicit def genLog(implicit content: Arbitrary[String], byChar: Arbitrary[Boolean]): Gen[ToLog] = - for(c <- content.arbitrary; by <- byChar.arbitrary) yield - { - assert(c != null) - new ToLog(removeNewlines(c), by) - } - - implicit lazy val genNewLine: Gen[NewLine] = - for(str <- oneOf("\n", "\r", "\r\n")) yield - new NewLine(str) - - implicit lazy val genLevel: Gen[Level.Value] = - oneOf(Level.values.toSeq) - - implicit lazy val genOutput: Gen[Output] = - for(ls <- listOf[List[ToLog]](MaxLines); lv <- genLevel) yield - new Output(ls, lv) - - def removeNewlines(s: String) = s.replaceAll("""[\n\r]+""", "") - def addNewline(l: ToLog): ToLog = - new ToLog(l.content + "\n", l.byCharacter) // \n will be replaced by a random line terminator for all lines + implicit lazy val arbOut: Arbitrary[Output] = Arbitrary(genOutput) + implicit lazy val arbLog: Arbitrary[ToLog] = Arbitrary(genLog) + implicit lazy val arbLine: Arbitrary[List[ToLog]] = Arbitrary(genLine) + implicit lazy val arbNewLine: Arbitrary[NewLine] = Arbitrary(genNewLine) + implicit lazy val arbLevel: Arbitrary[Level.Value] = Arbitrary(genLevel) - def listOf[T](max: Int)(implicit content: Arbitrary[T]): Gen[List[T]] = - Gen.choose(0, max) flatMap { sz => listOfN(sz, content.arbitrary) } + implicit def genLine(implicit logG: Gen[ToLog]): Gen[List[ToLog]] = + for (l <- listOf[ToLog](MaxSegments); last <- logG) yield (addNewline(last) :: l.filter(!_.content.isEmpty)).reverse + + implicit def genLog(implicit content: Arbitrary[String], byChar: Arbitrary[Boolean]): Gen[ToLog] = + for (c <- content.arbitrary; by <- byChar.arbitrary) yield { + assert(c != null) + new ToLog(removeNewlines(c), by) + } + + implicit lazy val genNewLine: Gen[NewLine] = + for (str <- oneOf("\n", "\r", "\r\n")) yield new NewLine(str) + + implicit lazy val genLevel: Gen[Level.Value] = + oneOf(Level.values.toSeq) + + implicit lazy val genOutput: Gen[Output] = + for (ls <- listOf[List[ToLog]](MaxLines); lv <- genLevel) yield new Output(ls, lv) + + def removeNewlines(s: String) = s.replaceAll("""[\n\r]+""", "") + def addNewline(l: ToLog): ToLog = + new ToLog(l.content + "\n", l.byCharacter) // \n will be replaced by a random line terminator for all lines + + def listOf[T](max: Int)(implicit content: Arbitrary[T]): Gen[List[T]] = + Gen.choose(0, max) flatMap { sz => listOfN(sz, content.arbitrary) } } /* Helper classes*/ -final class Output(val lines: List[List[ToLog]], val level: Level.Value) extends NotNull -{ - override def toString = - "Level: " + level + "\n" + lines.map(_.mkString).mkString("\n") +final class Output(val lines: List[List[ToLog]], val level: Level.Value) extends NotNull { + override def toString = + "Level: " + level + "\n" + lines.map(_.mkString).mkString("\n") } -final class NewLine(val str: String) extends NotNull -{ - override def toString = Escape(str) +final class NewLine(val str: String) extends NotNull { + override def toString = Escape(str) } -final class ToLog(val content: String, val byCharacter: Boolean) extends NotNull -{ - def contentOnly = Escape.newline(content, "") - override def toString = if(content.isEmpty) "" else "ToLog('" + Escape(contentOnly) + "', " + byCharacter + ")" +final class ToLog(val content: String, val byCharacter: Boolean) extends NotNull { + def contentOnly = Escape.newline(content, "") + override def toString = if (content.isEmpty) "" else "ToLog('" + Escape(contentOnly) + "', " + byCharacter + ")" } /** Defines some utility methods for escaping unprintable characters.*/ -object Escape -{ - /** Escapes characters with code less than 20 by printing them as unicode escapes.*/ - def apply(s: String): String = - { - val builder = new StringBuilder(s.length) - for(c <- s) - { - def escaped = pad(c.toInt.toHexString.toUpperCase, 4, '0') - if(c < 20) builder.append("\\u").append(escaped) else builder.append(c) - } - builder.toString - } - def pad(s: String, minLength: Int, extra: Char) = - { - val diff = minLength - s.length - if(diff <= 0) s else List.make(diff, extra).mkString("", "", s) - } - /** Replaces a \n character at the end of a string `s` with `nl`.*/ - def newline(s: String, nl: String): String = - if(s.endsWith("\n")) s.substring(0, s.length - 1) + nl else s +object Escape { + /** Escapes characters with code less than 20 by printing them as unicode escapes.*/ + def apply(s: String): String = + { + val builder = new StringBuilder(s.length) + for (c <- s) { + def escaped = pad(c.toInt.toHexString.toUpperCase, 4, '0') + if (c < 20) builder.append("\\u").append(escaped) else builder.append(c) + } + builder.toString + } + def pad(s: String, minLength: Int, extra: Char) = + { + val diff = minLength - s.length + if (diff <= 0) s else List.make(diff, extra).mkString("", "", s) + } + /** Replaces a \n character at the end of a string `s` with `nl`.*/ + def newline(s: String, nl: String): String = + if (s.endsWith("\n")) s.substring(0, s.length - 1) + nl else s } /** Records logging events for later retrieval.*/ -final class RecordingLogger extends BasicLogger -{ - private var events: List[LogEvent] = Nil - - def getEvents = events.reverse - - override def ansiCodesSupported = true - def trace(t: => Throwable) { events ::= new Trace(t) } - def log(level: Level.Value, message: => String) { events ::= new Log(level, message) } - def success(message: => String) { events ::= new Success(message) } - def logAll(es: Seq[LogEvent]) { events :::= es.toList } - def control(event: ControlEvent.Value, message: => String) { events ::= new ControlEvent(event, message) } - +final class RecordingLogger extends BasicLogger { + private var events: List[LogEvent] = Nil + + def getEvents = events.reverse + + override def ansiCodesSupported = true + def trace(t: => Throwable) { events ::= new Trace(t) } + def log(level: Level.Value, message: => String) { events ::= new Log(level, message) } + def success(message: => String) { events ::= new Success(message) } + def logAll(es: Seq[LogEvent]) { events :::= es.toList } + def control(event: ControlEvent.Value, message: => String) { events ::= new ControlEvent(event, message) } + } \ No newline at end of file diff --git a/util/log/src/test/scala/TestLogger.scala b/util/log/src/test/scala/TestLogger.scala index edf2b00dd..e7b6bee49 100644 --- a/util/log/src/test/scala/TestLogger.scala +++ b/util/log/src/test/scala/TestLogger.scala @@ -1,11 +1,10 @@ package sbt -object TestLogger -{ - def apply[T](f: Logger => T): T = - { - val log = new BufferedLogger(ConsoleLogger()) - log.setLevel(Level.Debug) - log.bufferQuietly(f(log)) - } +object TestLogger { + def apply[T](f: Logger => T): T = + { + val log = new BufferedLogger(ConsoleLogger()) + log.setLevel(Level.Debug) + log.bufferQuietly(f(log)) + } } \ No newline at end of file diff --git a/util/logic/src/test/scala/sbt/logic/Test.scala b/util/logic/src/test/scala/sbt/logic/Test.scala index cf50ef9fd..e66a3b9b2 100644 --- a/util/logic/src/test/scala/sbt/logic/Test.scala +++ b/util/logic/src/test/scala/sbt/logic/Test.scala @@ -1,117 +1,115 @@ package sbt package logic - import org.scalacheck._ - import Prop.secure - import Logic.{LogicException, Matched} +import org.scalacheck._ +import Prop.secure +import Logic.{ LogicException, Matched } -object LogicTest extends Properties("Logic") -{ - import TestClauses._ +object LogicTest extends Properties("Logic") { + import TestClauses._ - property("Handles trivial resolution.") = secure( expect(trivial, Set(A) ) ) - property("Handles less trivial resolution.") = secure( expect(lessTrivial, Set(B,A,D)) ) - property("Handles cycles without negation") = secure( expect(cycles, Set(F,A,B)) ) - property("Handles basic exclusion.") = secure( expect(excludedPos, Set()) ) - property("Handles exclusion of head proved by negation.") = secure( expect(excludedNeg, Set()) ) - // TODO: actually check ordering, probably as part of a check that dependencies are satisifed - property("Properly orders results.") = secure( expect(ordering, Set(B,A,C,E,F))) - property("Detects cyclic negation") = secure( - Logic.reduceAll(badClauses, Set()) match { - case Right(res) => false - case Left(err: Logic.CyclicNegation) => true - case Left(err) => error(s"Expected cyclic error, got: $err") - } - ) + property("Handles trivial resolution.") = secure(expect(trivial, Set(A))) + property("Handles less trivial resolution.") = secure(expect(lessTrivial, Set(B, A, D))) + property("Handles cycles without negation") = secure(expect(cycles, Set(F, A, B))) + property("Handles basic exclusion.") = secure(expect(excludedPos, Set())) + property("Handles exclusion of head proved by negation.") = secure(expect(excludedNeg, Set())) + // TODO: actually check ordering, probably as part of a check that dependencies are satisifed + property("Properly orders results.") = secure(expect(ordering, Set(B, A, C, E, F))) + property("Detects cyclic negation") = secure( + Logic.reduceAll(badClauses, Set()) match { + case Right(res) => false + case Left(err: Logic.CyclicNegation) => true + case Left(err) => error(s"Expected cyclic error, got: $err") + } + ) - def expect(result: Either[LogicException, Matched], expected: Set[Atom]) = result match { - case Left(err) => false - case Right(res) => - val actual = res.provenSet - (actual == expected) || error(s"Expected to prove $expected, but actually proved $actual") - } + def expect(result: Either[LogicException, Matched], expected: Set[Atom]) = result match { + case Left(err) => false + case Right(res) => + val actual = res.provenSet + (actual == expected) || error(s"Expected to prove $expected, but actually proved $actual") + } } -object TestClauses -{ +object TestClauses { - val A = Atom("A") - val B = Atom("B") - val C = Atom("C") - val D = Atom("D") - val E = Atom("E") - val F = Atom("F") - val G = Atom("G") + val A = Atom("A") + val B = Atom("B") + val C = Atom("C") + val D = Atom("D") + val E = Atom("E") + val F = Atom("F") + val G = Atom("G") - val clauses = - A.proves(B) :: - A.proves(F) :: - B.proves(F) :: - F.proves(A) :: - (!C).proves(F) :: - D.proves(C) :: - C.proves(D) :: - Nil + val clauses = + A.proves(B) :: + A.proves(F) :: + B.proves(F) :: + F.proves(A) :: + (!C).proves(F) :: + D.proves(C) :: + C.proves(D) :: + Nil - val cycles = Logic.reduceAll(clauses, Set()) + val cycles = Logic.reduceAll(clauses, Set()) - val badClauses = - A.proves(D) :: - clauses + val badClauses = + A.proves(D) :: + clauses - val excludedNeg = { - val cs = - (!A).proves(B) :: - Nil - val init = - (!A) :: - (!B) :: - Nil - Logic.reduceAll(cs, init.toSet) - } + val excludedNeg = { + val cs = + (!A).proves(B) :: + Nil + val init = + (!A) :: + (!B) :: + Nil + Logic.reduceAll(cs, init.toSet) + } - val excludedPos = { - val cs = - A.proves(B) :: - Nil - val init = - A :: - (!B) :: - Nil - Logic.reduceAll(cs, init.toSet) - } + val excludedPos = { + val cs = + A.proves(B) :: + Nil + val init = + A :: + (!B) :: + Nil + Logic.reduceAll(cs, init.toSet) + } - val trivial = { - val cs = - Formula.True.proves(A) :: - Nil - Logic.reduceAll(cs, Set.empty) - } + val trivial = { + val cs = + Formula.True.proves(A) :: + Nil + Logic.reduceAll(cs, Set.empty) + } - val lessTrivial = { - val cs = - Formula.True.proves(A) :: - Formula.True.proves(B) :: - (A && B && (!C)).proves(D) :: - Nil - Logic.reduceAll(cs, Set()) - } + val lessTrivial = { + val cs = + Formula.True.proves(A) :: + Formula.True.proves(B) :: + (A && B && (!C)).proves(D) :: + Nil + Logic.reduceAll(cs, Set()) + } - val ordering = { - val cs = - E.proves(F) :: - (C && !D).proves(E) :: - (A && B).proves(C) :: - Nil - Logic.reduceAll(cs, Set(A,B)) - } + val ordering = { + val cs = + E.proves(F) :: + (C && !D).proves(E) :: + (A && B).proves(C) :: + Nil + Logic.reduceAll(cs, Set(A, B)) + } - def all { - println(s"Cycles: $cycles") - println(s"xNeg: $excludedNeg") - println(s"xPos: $excludedPos") - println(s"trivial: $trivial") - println(s"lessTrivial: $lessTrivial") - println(s"ordering: $ordering") - } + def all { + println(s"Cycles: $cycles") + println(s"xNeg: $excludedNeg") + println(s"xPos: $excludedPos") + println(s"trivial: $trivial") + println(s"lessTrivial: $lessTrivial") + println(s"ordering: $ordering") + } } diff --git a/util/process/src/test/scala/ProcessSpecification.scala b/util/process/src/test/scala/ProcessSpecification.scala index 6298ce544..67bd5e625 100644 --- a/util/process/src/test/scala/ProcessSpecification.scala +++ b/util/process/src/test/scala/ProcessSpecification.scala @@ -1,133 +1,131 @@ package sbt import java.io.File -import org.scalacheck.{Arbitrary, Gen, Prop, Properties} +import org.scalacheck.{ Arbitrary, Gen, Prop, Properties } import Prop._ import Process._ -object ProcessSpecification extends Properties("Process I/O") -{ - implicit val exitCodeArb: Arbitrary[Array[Byte]] = Arbitrary( - for(size <- Gen.choose(0, 10); - l <- Gen.listOfN[Byte](size, Arbitrary.arbByte.arbitrary)) - yield - l.toArray - ) +object ProcessSpecification extends Properties("Process I/O") { + implicit val exitCodeArb: Arbitrary[Array[Byte]] = Arbitrary( + for ( + size <- Gen.choose(0, 10); + l <- Gen.listOfN[Byte](size, Arbitrary.arbByte.arbitrary) + ) yield l.toArray + ) - /*property("Correct exit code") = forAll( (exitCode: Byte) => checkExit(exitCode)) + /*property("Correct exit code") = forAll( (exitCode: Byte) => checkExit(exitCode)) property("#&& correct") = forAll( (exitCodes: Array[Byte]) => checkBinary(exitCodes)(_ #&& _)(_ && _)) property("#|| correct") = forAll( (exitCodes: Array[Byte]) => checkBinary(exitCodes)(_ #|| _)(_ || _)) property("### correct") = forAll( (exitCodes: Array[Byte]) => checkBinary(exitCodes)(_ ### _)( (x,latest) => latest))*/ - property("Pipe to output file") = forAll( (data: Array[Byte]) => checkFileOut(data)) - property("Pipe from input file") = forAll( (data: Array[Byte]) => checkFileIn(data)) - property("Pipe to process") = forAll( (data: Array[Byte]) => checkPipe(data)) - property("Pipe to process ignores input exit code") = forAll( (data: Array[Byte], code: Byte) => checkPipeExit(data, code)) - property("Pipe from input file to bad process preserves correct exit code.") = forAll( (data: Array[Byte], code: Byte) => checkFileInExit(data, code)) - property("Pipe to output file from bad process preserves correct exit code.") = forAll( (data: Array[Byte], code: Byte) => checkFileOutExit(data, code)) + property("Pipe to output file") = forAll((data: Array[Byte]) => checkFileOut(data)) + property("Pipe from input file") = forAll((data: Array[Byte]) => checkFileIn(data)) + property("Pipe to process") = forAll((data: Array[Byte]) => checkPipe(data)) + property("Pipe to process ignores input exit code") = forAll((data: Array[Byte], code: Byte) => checkPipeExit(data, code)) + property("Pipe from input file to bad process preserves correct exit code.") = forAll((data: Array[Byte], code: Byte) => checkFileInExit(data, code)) + property("Pipe to output file from bad process preserves correct exit code.") = forAll((data: Array[Byte], code: Byte) => checkFileOutExit(data, code)) - private def checkBinary(codes: Array[Byte])(reduceProcesses: (ProcessBuilder, ProcessBuilder) => ProcessBuilder)(reduceExit: (Boolean, Boolean) => Boolean) = - { - (codes.length > 1) ==> - { - val unsignedCodes = codes.map(unsigned) - val exitCode = unsignedCodes.map(code => Process(process("sbt.exit " + code))).reduceLeft(reduceProcesses) ! - val expectedExitCode = unsignedCodes.map(toBoolean).reduceLeft(reduceExit) - toBoolean(exitCode) == expectedExitCode - } - } - private def toBoolean(exitCode: Int) = exitCode == 0 - private def checkExit(code: Byte) = - { - val exitCode = unsigned(code) - (process("sbt.exit " + exitCode) !) == exitCode - } - private def checkFileOut(data: Array[Byte]) = - { - withData(data) { (temporaryFile, temporaryFile2) => - val catCommand = process("sbt.cat " + temporaryFile.getAbsolutePath) - catCommand #> temporaryFile2 - } - } - private def checkFileIn(data: Array[Byte]) = - { - withData(data) { (temporaryFile, temporaryFile2) => - val catCommand = process("sbt.cat") - temporaryFile #> catCommand #> temporaryFile2 - } - } - private def checkPipe(data: Array[Byte]) = - { - withData(data) { (temporaryFile, temporaryFile2) => - val catCommand = process("sbt.cat") - temporaryFile #> catCommand #| catCommand #> temporaryFile2 - } - } - private def checkPipeExit(data: Array[Byte], code: Byte) = - withTempFiles { (a,b) => - IO.write(a, data) - val catCommand = process("sbt.cat") - val exitCommand = process(s"sbt.exit $code") - val exit = (a #> exitCommand #| catCommand #> b).! - (s"Exit code: $exit") |: - (s"Output file length: ${b.length}") |: - (exit == 0) && - (b.length == 0) - } + private def checkBinary(codes: Array[Byte])(reduceProcesses: (ProcessBuilder, ProcessBuilder) => ProcessBuilder)(reduceExit: (Boolean, Boolean) => Boolean) = + { + (codes.length > 1) ==> + { + val unsignedCodes = codes.map(unsigned) + val exitCode = unsignedCodes.map(code => Process(process("sbt.exit " + code))).reduceLeft(reduceProcesses) ! + val expectedExitCode = unsignedCodes.map(toBoolean).reduceLeft(reduceExit) + toBoolean(exitCode) == expectedExitCode + } + } + private def toBoolean(exitCode: Int) = exitCode == 0 + private def checkExit(code: Byte) = + { + val exitCode = unsigned(code) + (process("sbt.exit " + exitCode) !) == exitCode + } + private def checkFileOut(data: Array[Byte]) = + { + withData(data) { (temporaryFile, temporaryFile2) => + val catCommand = process("sbt.cat " + temporaryFile.getAbsolutePath) + catCommand #> temporaryFile2 + } + } + private def checkFileIn(data: Array[Byte]) = + { + withData(data) { (temporaryFile, temporaryFile2) => + val catCommand = process("sbt.cat") + temporaryFile #> catCommand #> temporaryFile2 + } + } + private def checkPipe(data: Array[Byte]) = + { + withData(data) { (temporaryFile, temporaryFile2) => + val catCommand = process("sbt.cat") + temporaryFile #> catCommand #| catCommand #> temporaryFile2 + } + } + private def checkPipeExit(data: Array[Byte], code: Byte) = + withTempFiles { (a, b) => + IO.write(a, data) + val catCommand = process("sbt.cat") + val exitCommand = process(s"sbt.exit $code") + val exit = (a #> exitCommand #| catCommand #> b).! + (s"Exit code: $exit") |: + (s"Output file length: ${b.length}") |: + (exit == 0) && + (b.length == 0) + } - private def checkFileOutExit(data: Array[Byte], exitCode: Byte) = - withTempFiles { (a,b) => - IO.write(a, data) - val code = unsigned(exitCode) - val command = process(s"sbt.exit $code") - val exit = (a #> command #> b).! - (s"Exit code: $exit, expected: $code") |: - (s"Output file length: ${b.length}") |: - (exit == code) && - (b.length == 0) - } + private def checkFileOutExit(data: Array[Byte], exitCode: Byte) = + withTempFiles { (a, b) => + IO.write(a, data) + val code = unsigned(exitCode) + val command = process(s"sbt.exit $code") + val exit = (a #> command #> b).! + (s"Exit code: $exit, expected: $code") |: + (s"Output file length: ${b.length}") |: + (exit == code) && + (b.length == 0) + } - private def checkFileInExit(data: Array[Byte], exitCode: Byte) = - withTempFiles { (a,b) => - IO.write(a, data) - val code = unsigned(exitCode) - val command = process(s"sbt.exit $code") - val exit = (a #> command).! - (s"Exit code: $exit, expected: $code") |: - (exit == code) - } + private def checkFileInExit(data: Array[Byte], exitCode: Byte) = + withTempFiles { (a, b) => + IO.write(a, data) + val code = unsigned(exitCode) + val command = process(s"sbt.exit $code") + val exit = (a #> command).! + (s"Exit code: $exit, expected: $code") |: + (exit == code) + } - private def temp() = File.createTempFile("sbt", "") - private def withData(data: Array[Byte])(f: (File, File) => ProcessBuilder) = - withTempFiles { (a, b) => - IO.write(a, data) - val process = f(a, b) - ( process ! ) == 0 && sameFiles(a, b) - } - private def sameFiles(a: File, b: File) = - IO.readBytes(a) sameElements IO.readBytes(b) + private def temp() = File.createTempFile("sbt", "") + private def withData(data: Array[Byte])(f: (File, File) => ProcessBuilder) = + withTempFiles { (a, b) => + IO.write(a, data) + val process = f(a, b) + (process !) == 0 && sameFiles(a, b) + } + private def sameFiles(a: File, b: File) = + IO.readBytes(a) sameElements IO.readBytes(b) - private def withTempFiles[T](f: (File, File) => T): T = - { - val temporaryFile1 = temp() - val temporaryFile2 = temp() - try f(temporaryFile1, temporaryFile2) - finally - { - temporaryFile1.delete() - temporaryFile2.delete() - } - } - private def unsigned(b: Int): Int = ((b: Int) +256) % 256 - private def unsigned(b: Byte): Int = unsigned(b: Int) - private def process(command: String) = - { - val ignore = echo // just for the compile dependency so that this test is rerun when TestedProcess.scala changes, not used otherwise + private def withTempFiles[T](f: (File, File) => T): T = + { + val temporaryFile1 = temp() + val temporaryFile2 = temp() + try f(temporaryFile1, temporaryFile2) + finally { + temporaryFile1.delete() + temporaryFile2.delete() + } + } + private def unsigned(b: Int): Int = ((b: Int) + 256) % 256 + private def unsigned(b: Byte): Int = unsigned(b: Int) + private def process(command: String) = + { + val ignore = echo // just for the compile dependency so that this test is rerun when TestedProcess.scala changes, not used otherwise - val thisClasspath = List(getSource[Product], getSource[IO.type], getSource[SourceTag]).mkString(File.pathSeparator) - "java -cp " + thisClasspath + " " + command - } - private def getSource[T : Manifest]: String = - IO.classLocationFile[T].getAbsolutePath + val thisClasspath = List(getSource[Product], getSource[IO.type], getSource[SourceTag]).mkString(File.pathSeparator) + "java -cp " + thisClasspath + " " + command + } + private def getSource[T: Manifest]: String = + IO.classLocationFile[T].getAbsolutePath } private trait SourceTag diff --git a/util/process/src/test/scala/TestedProcess.scala b/util/process/src/test/scala/TestedProcess.scala index c013de531..5daea8bab 100644 --- a/util/process/src/test/scala/TestedProcess.scala +++ b/util/process/src/test/scala/TestedProcess.scala @@ -1,56 +1,47 @@ package sbt -import java.io.{File, FileNotFoundException, IOException} +import java.io.{ File, FileNotFoundException, IOException } -object exit -{ - def main(args: Array[String]) - { - System.exit(java.lang.Integer.parseInt(args(0))) - } +object exit { + def main(args: Array[String]) { + System.exit(java.lang.Integer.parseInt(args(0))) + } } -object cat -{ - def main(args: Array[String]) - { - try { - if(args.length == 0) - IO.transfer(System.in, System.out) - else - catFiles(args.toList) - System.exit(0) - } catch { - case e => - e.printStackTrace() - System.err.println("Error: " + e.toString) - System.exit(1) - } - } - private def catFiles(filenames: List[String]): Option[String] = - { - filenames match - { - case head :: tail => - val file = new File(head) - if(file.isDirectory) - throw new IOException("Is directory: " + file) - else if(file.exists) - { - Using.fileInputStream(file) { stream => - IO.transfer(stream, System.out) - } - catFiles(tail) - } - else - throw new FileNotFoundException("No such file or directory: " + file) - case Nil => None - } - } +object cat { + def main(args: Array[String]) { + try { + if (args.length == 0) + IO.transfer(System.in, System.out) + else + catFiles(args.toList) + System.exit(0) + } catch { + case e => + e.printStackTrace() + System.err.println("Error: " + e.toString) + System.exit(1) + } + } + private def catFiles(filenames: List[String]): Option[String] = + { + filenames match { + case head :: tail => + val file = new File(head) + if (file.isDirectory) + throw new IOException("Is directory: " + file) + else if (file.exists) { + Using.fileInputStream(file) { stream => + IO.transfer(stream, System.out) + } + catFiles(tail) + } else + throw new FileNotFoundException("No such file or directory: " + file) + case Nil => None + } + } } -object echo -{ - def main(args: Array[String]) - { - System.out.println(args.mkString(" ")) - } +object echo { + def main(args: Array[String]) { + System.out.println(args.mkString(" ")) + } } \ No newline at end of file diff --git a/util/relation/src/test/scala/RelationTest.scala b/util/relation/src/test/scala/RelationTest.scala index 3dcc03f38..558935bdb 100644 --- a/util/relation/src/test/scala/RelationTest.scala +++ b/util/relation/src/test/scala/RelationTest.scala @@ -6,79 +6,79 @@ package sbt import org.scalacheck._ import Prop._ -object RelationTest extends Properties("Relation") -{ - property("Added entry check") = forAll { (pairs: List[(Int, Double)]) => - val r = Relation.empty[Int, Double] ++ pairs - check(r, pairs) - } - def check(r: Relation[Int, Double], pairs: Seq[(Int, Double)]) = - { - val _1s = pairs.map(_._1).toSet - val _2s = pairs.map(_._2).toSet - - r._1s == _1s && r.forwardMap.keySet == _1s && - r._2s == _2s && r.reverseMap.keySet == _2s && - pairs.forall { case (a, b) => - (r.forward(a) contains b) && - (r.reverse(b) contains a) && - (r.forwardMap(a) contains b) && - (r.reverseMap(b) contains a) - } - } - - property("Does not contain removed entries") = forAll { (pairs: List[(Int, Double, Boolean)]) => - val add = pairs.map { case (a,b,c) => (a,b) } - val added = Relation.empty[Int, Double] ++ add - - val removeFine = pairs.collect { case (a,b,true) => (a,b) } - val removeCoarse = removeFine.map(_._1) - val r = added -- removeCoarse - - def notIn[X,Y](map: Map[X, Set[Y]], a: X, b: Y) = map.get(a).forall(set => ! (set contains b) ) - - all(removeCoarse) { rem => - ("_1s does not contain removed" |: (!r._1s.contains(rem)) ) && - ("Forward does not contain removed" |: r.forward(rem).isEmpty ) && - ("Forward map does not contain removed" |: !r.forwardMap.contains(rem) ) && - ("Removed is not a value in reverse map" |: !r.reverseMap.values.toSet.contains(rem) ) - } && - all(removeFine) { case (a, b) => - ("Forward does not contain removed" |: ( !r.forward(a).contains(b) ) ) && - ("Reverse does not contain removed" |: ( !r.reverse(b).contains(a) ) ) && - ("Forward map does not contain removed" |: ( notIn(r.forwardMap, a, b) ) ) && - ("Reverse map does not contain removed" |: ( notIn(r.reverseMap, b, a) ) ) - } - } +object RelationTest extends Properties("Relation") { + property("Added entry check") = forAll { (pairs: List[(Int, Double)]) => + val r = Relation.empty[Int, Double] ++ pairs + check(r, pairs) + } + def check(r: Relation[Int, Double], pairs: Seq[(Int, Double)]) = + { + val _1s = pairs.map(_._1).toSet + val _2s = pairs.map(_._2).toSet - property("Groups correctly") = forAll { (entries: List[(Int, Double)], randomInt: Int) => - val splitInto = math.abs(randomInt) % 10 + 1 // Split into 1-10 groups. - val rel = Relation.empty[Int, Double] ++ entries - val grouped = rel groupBy (_._1 % splitInto) - all(grouped.toSeq) { - case (k, rel_k) => rel_k._1s forall { _ % splitInto == k } - } - } + r._1s == _1s && r.forwardMap.keySet == _1s && + r._2s == _2s && r.reverseMap.keySet == _2s && + pairs.forall { + case (a, b) => + (r.forward(a) contains b) && + (r.reverse(b) contains a) && + (r.forwardMap(a) contains b) && + (r.reverseMap(b) contains a) + } + } + + property("Does not contain removed entries") = forAll { (pairs: List[(Int, Double, Boolean)]) => + val add = pairs.map { case (a, b, c) => (a, b) } + val added = Relation.empty[Int, Double] ++ add + + val removeFine = pairs.collect { case (a, b, true) => (a, b) } + val removeCoarse = removeFine.map(_._1) + val r = added -- removeCoarse + + def notIn[X, Y](map: Map[X, Set[Y]], a: X, b: Y) = map.get(a).forall(set => !(set contains b)) + + all(removeCoarse) { rem => + ("_1s does not contain removed" |: (!r._1s.contains(rem))) && + ("Forward does not contain removed" |: r.forward(rem).isEmpty) && + ("Forward map does not contain removed" |: !r.forwardMap.contains(rem)) && + ("Removed is not a value in reverse map" |: !r.reverseMap.values.toSet.contains(rem)) + } && + all(removeFine) { + case (a, b) => + ("Forward does not contain removed" |: (!r.forward(a).contains(b))) && + ("Reverse does not contain removed" |: (!r.reverse(b).contains(a))) && + ("Forward map does not contain removed" |: (notIn(r.forwardMap, a, b))) && + ("Reverse map does not contain removed" |: (notIn(r.reverseMap, b, a))) + } + } + + property("Groups correctly") = forAll { (entries: List[(Int, Double)], randomInt: Int) => + val splitInto = math.abs(randomInt) % 10 + 1 // Split into 1-10 groups. + val rel = Relation.empty[Int, Double] ++ entries + val grouped = rel groupBy (_._1 % splitInto) + all(grouped.toSeq) { + case (k, rel_k) => rel_k._1s forall { _ % splitInto == k } + } + } property("Computes size correctly") = forAll { (entries: List[(Int, Double)]) => val rel = Relation.empty[Int, Double] ++ entries - val expected = rel.all.size // Note: not entries.length, as entries may have duplicates. + val expected = rel.all.size // Note: not entries.length, as entries may have duplicates. val computed = rel.size "Expected size: %d. Computed size: %d.".format(expected, computed) |: expected == computed } - def all[T](s: Seq[T])(p: T => Prop): Prop = - if(s.isEmpty) true else s.map(p).reduceLeft(_ && _) + def all[T](s: Seq[T])(p: T => Prop): Prop = + if (s.isEmpty) true else s.map(p).reduceLeft(_ && _) } -object EmptyRelationTest extends Properties("Empty relation") -{ - lazy val e = Relation.empty[Int, Double] +object EmptyRelationTest extends Properties("Empty relation") { + lazy val e = Relation.empty[Int, Double] - property("Forward empty") = forAll { (i: Int) => e.forward(i).isEmpty } - property("Reverse empty") = forAll { (i: Double) => e.reverse(i).isEmpty } - property("Forward map empty") = e.forwardMap.isEmpty - property("Reverse map empty") = e.reverseMap.isEmpty - property("_1 empty") = e._1s.isEmpty - property("_2 empty") = e._2s.isEmpty + property("Forward empty") = forAll { (i: Int) => e.forward(i).isEmpty } + property("Reverse empty") = forAll { (i: Double) => e.reverse(i).isEmpty } + property("Forward map empty") = e.forwardMap.isEmpty + property("Reverse map empty") = e.reverseMap.isEmpty + property("_1 empty") = e._1s.isEmpty + property("_2 empty") = e._2s.isEmpty } \ No newline at end of file