starting to convert integration tests

This commit is contained in:
Mark Harrah 2011-02-22 22:36:48 -05:00
parent 286e8865cf
commit ba8f43a23e
21 changed files with 139 additions and 147 deletions

View File

@ -21,8 +21,8 @@ final class EvalException(msg: String) extends RuntimeException(msg)
// not thread safe, since it reuses a Global instance // not thread safe, since it reuses a Global instance
final class Eval(optionsNoncp: Seq[String], classpath: Seq[File], mkReporter: Settings => Reporter, parent: ClassLoader, backing: Option[File]) final class Eval(optionsNoncp: Seq[String], classpath: Seq[File], mkReporter: Settings => Reporter, parent: ClassLoader, backing: Option[File])
{ {
def this(mkReporter: Settings => Reporter) = this(Nil, IO.classLocationFile[ScalaObject] :: Nil, mkReporter, getClass.getClassLoader, None) def this(mkReporter: Settings => Reporter, backing: Option[File]) = this(Nil, IO.classLocationFile[ScalaObject] :: Nil, mkReporter, getClass.getClassLoader, backing)
def this() = this(s => new ConsoleReporter(s)) def this() = this(s => new ConsoleReporter(s), None)
backing.foreach(IO.createDirectory) backing.foreach(IO.createDirectory)
val classpathString = Path.makeString(classpath) val classpathString = Path.makeString(classpath)

View File

@ -9,7 +9,7 @@ object EvalTest extends Properties("eval")
{ {
private[this] val reporter = new StoreReporter private[this] val reporter = new StoreReporter
import reporter.{ERROR,Info,Severity} import reporter.{ERROR,Info,Severity}
private[this] val eval = new Eval(_ => reporter) private[this] val eval = new Eval(_ => reporter, None)
property("inferred integer") = forAll{ (i: Int) => property("inferred integer") = forAll{ (i: Int) =>
val result = eval.eval(i.toString) val result = eval.eval(i.toString)
@ -33,8 +33,9 @@ object EvalTest extends Properties("eval")
} }
property("backed local class") = forAll{ (i: Int) => property("backed local class") = forAll{ (i: Int) =>
IO.withTemporaryDirectory { dir => IO.withTemporaryDirectory { dir =>
val result = eval.eval(local(i), backing = Some(dir)) val eval = new Eval(_ => reporter, backing = Some(dir))
val result = eval.eval(local(i))
val value = result.value.asInstanceOf[{def i: Int}].i val value = result.value.asInstanceOf[{def i: Int}].i
(label("Value", value) |: (value == i)) && (label("Value", value) |: (value == i)) &&
(label("Type", result.tpe) |: (result.tpe == LocalType)) && (label("Type", result.tpe) |: (result.tpe == LocalType)) &&

View File

@ -1,6 +1,6 @@
package xsbti package xsbti
object f0 object g0
{ {
def apply[T](s: => T) = new F0[T] { def apply = s } def apply[T](s: => T) = new F0[T] { def apply = s }
} }

View File

@ -40,13 +40,21 @@ final object Aggregation
{ {
case Implicit(false) => (Nil, false) case Implicit(false) => (Nil, false)
case Implicit(true) => (projectAggregate(key, structure), true) case Implicit(true) => (projectAggregate(key, structure), true)
case e: Explicit => (e.dependencies, e.transitive) case e: Explicit => (subCurrentBuild(key, e.dependencies), e.transitive)
} }
agg flatMap { a => agg flatMap { a =>
val newKey = ScopedKey(key.scope.copy(project = Select(a)), key.key) val newKey = ScopedKey(key.scope.copy(project = Select(a)), key.key)
getTasks(newKey, structure, transitive) getTasks(newKey, structure, transitive)
} }
} }
private def subCurrentBuild(key: ScopedKey[_], refs: Seq[ProjectRef]): Seq[ProjectRef] =
key.scope.project match
{
case Select(ProjectRef(Some(current), _)) => refs map { ref => Scope.mapRefBuild(current, ref) }
case _ => refs
}
def printSettings[T](xs: Seq[KeyValue[T]], log: Logger) = def printSettings[T](xs: Seq[KeyValue[T]], log: Logger) =
xs match xs match

View File

@ -521,8 +521,10 @@ object Load
{ {
val subclassSet = subclasses.toSet val subclassSet = subclasses.toSet
val ds = Discovery(subclassSet, Set.empty)(Test.allDefs(analysis)) val ds = Discovery(subclassSet, Set.empty)(Test.allDefs(analysis))
ds.flatMap { case (definition, Discovered(subs,_,_,true)) => ds.flatMap {
if((subs ** subclassSet).isEmpty) Nil else definition.name :: Nil case (definition, Discovered(subs,_,_,true)) =>
if((subs ** subclassSet).isEmpty) Nil else definition.name :: Nil
case _ => Nil
} }
} }

View File

@ -320,7 +320,7 @@ object Default
) )
lazy val packageConfig = Seq( lazy val packageConfig = Seq(
JarName <<= (JarName, Config) { (n,c) => n.copy(config = c.name) }, JarName <<= (JarName, Config) { (n,c) => n.copy(config = c.name) },
PackageOptions in Package <<= MainClass in Package map ( _.map(sbt.Package.MainClass.apply).toList ) PackageOptions in Package <<= (PackageOptions, MainClass in Package) map { _ ++ _.map(sbt.Package.MainClass.apply).toList }
) ++ ) ++
packageTasks(Package, "", packageBin) ++ packageTasks(Package, "", packageBin) ++
packageTasks(PackageSrc, "src", packageSrc) ++ packageTasks(PackageSrc, "src", packageSrc) ++

View File

@ -103,7 +103,7 @@ object Project extends Init[Scope]
def mapScope(f: Scope => Scope) = new (ScopedKey ~> ScopedKey) { def apply[T](key: ScopedKey[T]) = def mapScope(f: Scope => Scope) = new (ScopedKey ~> ScopedKey) { def apply[T](key: ScopedKey[T]) =
ScopedKey( f(key.scope), key.key) ScopedKey( f(key.scope), key.key)
} }
def resolveThis(thisScope: Scope) = mapScope(Scope.replaceThis(thisScope))
def transform(g: Scope => Scope, ss: Seq[Setting[_]]): Seq[Setting[_]] = { def transform(g: Scope => Scope, ss: Seq[Setting[_]]): Seq[Setting[_]] = {
val f = mapScope(g) val f = mapScope(g)
ss.map(_ mapKey f mapReferenced f) ss.map(_ mapKey f mapReferenced f)

View File

@ -354,15 +354,15 @@ class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths
override def normalizedName = "sbt" override def normalizedName = "sbt"
override def testWithCompileClasspath = super.testWithCompileClasspath ++ Seq(scriptedSbtSub) override def testWithCompileClasspath = super.testWithCompileClasspath ++ Seq(scriptedSbtSub)
override def testAction = super.testAction dependsOn(publishLocal) override def testAction = super.testAction dependsOn(publishLocal)
def scriptedScalaVersions = "2.8.1.RC4" def scriptedScalaVersions = "2.8.1"
lazy val scripted = task { args => task { lazy val scripted = task { args => task {
val launcher = launchSub.outputJar.asFile val launcher = launchSub.outputJar.asFile
val loader = ClasspathUtilities.toLoader(scriptedSbtSub.testClasspath, buildScalaInstance.loader) val loader = ClasspathUtilities.toLoader(scriptedSbtSub.testClasspath, scriptedSbtSub.buildScalaInstance.loader)
val m = ModuleUtilities.getObject("sbt.test.ScriptedTests", loader) val m = ModuleUtilities.getObject("sbt.test.ScriptedTests", loader)
val r = m.getClass.getMethod("run", classOf[File], classOf[Boolean], classOf[String], classOf[String], classOf[String], classOf[Array[String]], classOf[File]) val r = m.getClass.getMethod("run", classOf[File], classOf[Boolean], classOf[String], classOf[String], classOf[String], classOf[Array[String]], classOf[File])
try { r.invoke(m, sourcePath / "sbt-test" asFile, true: java.lang.Boolean, version.toString, buildScalaVersion, scriptedScalaVersions, args, launcher) } try { r.invoke(m, sourcePath / "sbt-test" asFile, true: java.lang.Boolean, version.toString, buildScalaVersion, scriptedScalaVersions, args, launcher) }
catch { case e: java.lang.reflect.InvocationTargetException => throw e.getCause } catch { case e: java.lang.reflect.InvocationTargetException => throw e.getCause }
None None
} dependsOn(publishLocal, scriptedSbtSub.compile) } } dependsOn(publishLocal, scriptedSbtSub.compile, testCompile) }
} }
} }

View File

@ -1,6 +0,0 @@
import sbt._
class TestProject(info: ProjectInfo) extends DefaultProject(info) with Marker
{
lazy val interactiveTest = interactiveTask { mark() }
}

View File

@ -1,7 +0,0 @@
import sbt._
class TestProject(info: ProjectInfo) extends ParentProject(info) with Marker
{
val subA = project("a", "A")
lazy val interactiveTest = interactiveTask { mark() }
}

View File

@ -1,10 +0,0 @@
import sbt._
class TestProject(info: ProjectInfo) extends ParentProject(info)
{
val subA = project("a", "A", new SubA(_))
class SubA(info: ProjectInfo) extends DefaultProject(info) with Marker
{
lazy val interactiveTest = interactiveTask { mark() }
}
}

View File

@ -1,12 +0,0 @@
import sbt._
class TestProject(info: ProjectInfo) extends ParentProject(info) with Marker
{
val subA = project("a", "A", new SubA(_))
lazy val interactiveTest = interactiveTask { mark() }
class SubA(info: ProjectInfo) extends DefaultProject(info)
{
lazy val interactiveTest = interactiveTask { Some("Child interactive task should not be called.") }
}
}

View File

@ -1,12 +0,0 @@
import sbt._
class TestProject(info: ProjectInfo) extends ParentProject(info)
{
val subA = project("a", "A", new SubA(_))
lazy val interactiveTest = task { Some("Parent task should not be called") }
class SubA(info: ProjectInfo) extends DefaultProject(info)
{
lazy val interactiveTest = interactiveTask { Some("Child task should not be called.") }
}
}

View File

@ -1,12 +0,0 @@
import sbt._
class TestProject(info: ProjectInfo) extends ParentProject(info) with Marker
{
val subA = project("a", "A", new SubA(_))
lazy val interactiveTest = task { mark() }
class SubA(info: ProjectInfo) extends DefaultProject(info) with Marker
{
lazy val interactiveTest = task { mark() }
}
}

View File

@ -0,0 +1,17 @@
import sbt._
import Keys._
import Project.Initialize
trait Marker
{
final lazy val Mark = TaskKey[Unit]("mark")
final def mark: Initialize[Task[Unit]] = mark(Base)
final def mark(project: ProjectRef): Initialize[Task[Unit]] = mark(Base in project)
final def mark(baseKey: ScopedSetting[File]): Initialize[Task[Unit]] = baseKey map { base =>
val toMark = base / "ran"
if(toMark.exists)
error("Already ran (" + toMark + " exists)")
else
IO touch toMark
}
}

View File

@ -0,0 +1,9 @@
import sbt._
object SingleBuild extends Build with Marker
{
lazy val projects = if(file("multi").exists) Seq(root, sub, sub2) else Seq(root)
lazy val root = Project("root", file("."), aggregate = if(file("aggregate").exists) Seq(sub) else Nil )
lazy val sub = Project("sub", file("sub"), aggregate = Seq(sub2))
lazy val sub2 = Project("sub2", file("sub") / "sub")
}

View File

@ -1,4 +0,0 @@
#Project properties
#Fri Jan 30 20:49:57 EST 2009
project.name=Interactive Actions Test
project.version=1.0

View File

@ -1,13 +0,0 @@
import sbt._
trait Marker extends NotNull
{ self: Project =>
def toMark: Path = "ran"
def mark() =
{
if(toMark.exists)
Some("Already ran")
else
FileUtilities.touch(toMark, log)
}
}

View File

@ -1,6 +0,0 @@
import sbt._
class TestProject(info: ProjectInfo) extends DefaultProject(info) with Marker
{
lazy val interactiveTest = task { mark() }
}

View File

@ -1,46 +1,102 @@
# This test verifies the behavior of actions declared interactive # single project, 'mark' not defined
-> mark
$ absent ran
# Single project, non-interactive task # single project, 'mark' defined
> interactive-test > set Mark <<= mark
> mark
$ exists ran $ exists ran
$ delete ran $ delete ran
# Single project, interactive task # single project, Aggregate = Enabled on Mark
$ copy-file changes/TestProject2.scala project/build/src/TestProject.scala > set Aggregate in Mark :== false
> reload > mark
> interactive-test
$ exists ran $ exists ran
$ delete ran $ delete ran
# Multi-project, single interactive task on parent project # single project, Aggregate = Disabled on Mark
$ copy-file changes/TestProject3.scala project/build/src/TestProject.scala > set Aggregate in Mark :== false
> reload > mark
> interactive-test
$ exists ran $ exists ran
$ delete ran $ delete ran
# Multi-project, single interactive task on child project # switch to multi-project, no aggregation yet. 'reload' will drop session settings
$ copy-file changes/TestProject4.scala project/build/src/TestProject.scala $ touch multi
$ mkdir sub sub/sub
> reload > reload
-> interactive-test
# Multi-project, two interactive tasks with same name, which is allowed because it is defined on parent # define in root project only
$ copy-file changes/TestProject5.scala project/build/src/TestProject.scala > set Mark <<= mark
> reload > mark
> interactive-test $ exists ran
$ exists "ran" $ absent sub/ran
$ delete "ran" $ delete ran
# Multi-project, interactive on subproject + non-interactive on parent, which cannot be run from parent # define in sub project, but shouldn't run without aggregation
$ copy-file changes/TestProject6.scala project/build/src/TestProject.scala > set Mark in sub <<= mark(sub)
> reload > mark
-> interactive-test $ exists ran
$ absent sub/ran
$ delete ran
# Multi-project, two non-interactive tasks with same name, which is allowed # should be able to run it directly...
$ copy-file changes/TestProject7.scala project/build/src/TestProject.scala > sub/mark
$ absent ran
$ exists sub/ran
$ delete sub/ran
# unset the root task. the sub task shouldn't be runnable from root
> session remove 1
-> mark
$ absent ran sub/ran
# enable aggregation. 'reload' resets session settings
$ touch aggregate
> reload > reload
> interactive-test
$ exists "ran" # add tasks to each subproject
$ exists "a/ran" > set Mark in sub <<= mark(sub)
$ delete "ran" > set Mark in sub2 <<= mark(sub2)
$ delete "a/ran"
# check that aggregation works when root project has no task
> mark
$ exists sub/ran sub/sub/ran
$ absent ran
$ delete sub/ran sub/sub/ran
# check that aggregation works on sub/
> sub/mark
$ exists sub/ran sub/sub/ran
$ absent ran
$ delete sub/ran sub/sub/ran
# add task to root project
> set Mark <<= mark
# disable aggregation for sub/mark so that sub2/mark doesn't run
> set Aggregate in (sub,Mark) :== false
> mark
$ exists ran sub/ran
$ absent sub/sub/ran
$ delete ran sub/ran
# check explicit aggregation. running on root should run root/mark and sub2/mark
> set Aggregate in Mark :== Aggregation(sub2 :: Nil)
> mark
$ exists ran sub/sub/ran
$ absent sub/ran
$ delete ran sub/sub/ran
# check intransitive aggregation. running on root should not continue to sub2/mark
> set Aggregate in Mark :== Aggregation(sub :: Nil, false)
> mark
$ exists ran sub/ran
$ absent sub/sub/ran
$ delete ran sub/ran
# the aggregation setting in a leaf shouldn't affect whether it can be run directly
> set Aggregate in (sub2, Mark) :== false
> sub2/mark
$ exists sub/sub/ran
$ absent ran sub/ran
$ delete sub/sub/ran

View File

@ -39,7 +39,6 @@ final class ScriptedTests(resourceBaseDirectory: File, bufferLog: Boolean, sbtVe
IPC.pullServer( scriptedTest0(label, testDirectory, log) ) IPC.pullServer( scriptedTest0(label, testDirectory, log) )
private def scriptedTest0(label: String, testDirectory: File, log: Logger)(server: IPC.Server) private def scriptedTest0(label: String, testDirectory: File, log: Logger)(server: IPC.Server)
{ {
FillProperties(testDirectory, sbtVersion, defScalaVersion, buildScalaVersions)
val buffered = new BufferedLogger(new FullLogger(log)) val buffered = new BufferedLogger(new FullLogger(log))
if(bufferLog) if(bufferLog)
buffered.record() buffered.record()
@ -114,25 +113,7 @@ object ScriptedTests
ScriptedTest(group,name) ScriptedTest(group,name)
} }
} }
object FillProperties
{
def apply(projectDirectory: File, sbtVersion: String, defScalaVersion: String, buildScalaVersions: String): Unit =
{
import sbt.Path._
fill(projectDirectory / "project" / "build.properties", sbtVersion, defScalaVersion, buildScalaVersions)
}
def fill(properties: File, sbtVersion: String, defScalaVersion: String, buildScalaVersions: String)
{
val toAppend = extraProperties(sbtVersion, defScalaVersion, buildScalaVersions)
IO.write(properties, toAppend, Charset.forName("ISO-8859-1"), true)
}
def extraProperties(sbtVersion: String, defScalaVersion: String, buildScalaVersions: String) =
<x>
sbt.version={sbtVersion}
def.scala.version={defScalaVersion}
build.scala.versions={buildScalaVersions}
</x>.text
}
final case class ScriptedTest(group: String, name: String) extends NotNull final case class ScriptedTest(group: String, name: String) extends NotNull
{ {
override def toString = group + "/" + name override def toString = group + "/" + name