Fixed tests

This commit is contained in:
Mark Harrah 2009-09-06 16:05:31 -04:00
parent 39546077ee
commit 72ce84933d
9 changed files with 99 additions and 89 deletions

View File

@ -5,11 +5,9 @@ package xsbt
import java.net.URLClassLoader
/** Interface to the Scala compiler that uses the dependency analysis plugin. This class uses the Scala library and compiler
* obtained through the 'scalaLoader' class loader. This class requires a ComponentManager in order to obtain the
* interface code to scalac and the analysis plugin. Because these call Scala code for a different Scala version, they must
* be compiled for the version of Scala being used. It is essential that the provided 'scalaVersion' be a 1:1 mapping to the
* actual version of Scala being used for compilation (-SNAPSHOT is not acceptable). Otherwise, binary compatibility
* issues will ensue!*/
* provided by scalaInstance. This class requires a ComponentManager in order to obtain the interface code to scalac and
* the analysis plugin. Because these call Scala code for a different Scala version than the one used for this class, they must
* be compiled for the version of Scala being used.*/
class AnalyzingCompiler(scalaInstance: ScalaInstance, manager: ComponentManager) extends NotNull
{
def apply(sources: Set[File], classpath: Set[File], outputDirectory: File, options: Seq[String], callback: AnalysisCallback, maximumErrors: Int, log: CompileLogger): Unit =

View File

@ -1,25 +0,0 @@
package xsbt
import java.io.File
import org.specs.Specification
object CheckBasic extends Specification
{
val basicName = new File("Basic.scala")
val basicSource = "package org.example { object Basic }"
"Compiling basic file should succeed" in {
WithFiles(basicName -> basicSource){ files =>
TestCompile(files){ loader => Class.forName("org.example.Basic", false, loader) }
true must beTrue // don't know how to just check that previous line completes without exception
}
}
"Analyzer plugin should send source begin and end" in {
WithFiles(basicName -> basicSource) { files =>
CallbackTest(files) { callback =>
(callback.beganSources) must haveTheSameElementsAs(files)
(callback.endedSources) must haveTheSameElementsAs(files)
}
}
}
}

View File

@ -1,38 +0,0 @@
package xsbt
import java.io.File
import java.net.URLClassLoader
import xsbti.TestCallback
import FileUtilities.withTemporaryDirectory
object TestCompile
{
/** Tests running the compiler interface with the analyzer plugin with a test callback. The test callback saves all information
* that the plugin sends it for post-compile analysis by the provided function.*/
def apply[T](arguments: Seq[String], superclassNames: Seq[String])(f: (TestCallback, Logger) => T): T =
{
val testCallback = new TestCallback(superclassNames.toArray)
val i = new CompilerInterface
val log = new BufferedLogger(new ConsoleLogger)
log.bufferQuietly {
i.run(arguments.toArray, testCallback, 5, log)
f(testCallback, log)
}
}
/** Tests running the compiler interface with the analyzer plugin. The provided function is given a ClassLoader that can
* load the compiled classes..*/
def apply[T](sources: Seq[File])(f: ClassLoader => T): T =
CallbackTest.apply(sources, Nil){ case (callback, outputDir, log) => f(new URLClassLoader(Array(outputDir.toURI.toURL))) }
}
object CallbackTest
{
def apply[T](sources: Iterable[File])(f: TestCallback => T): T =
apply(sources.toSeq, Nil){ case (callback, outputDir, log) => f(callback) }
def apply[T](sources: Seq[File], superclassNames: Seq[String])(f: (TestCallback, File, Logger) => T): T =
{
withTemporaryDirectory { outputDir =>
val newArgs = "-d" :: outputDir.getAbsolutePath :: sources.map(_.getAbsolutePath).toList
TestCompile(newArgs, superclassNames) { case (callback, log) => f(callback, outputDir, log) }
}
}
}

View File

@ -98,13 +98,14 @@ object ApplicationsTest extends Specification
"Analysis plugin should detect applications" in {
WithFiles(sources : _*) { case files @ Seq(main, main2, main3, main4, main5, main6, main7, main8, main9, mainA, mainB, mainC, mainD, mainE) =>
CallbackTest(files, Nil) { (callback, file, log) =>
val expected = Seq( main -> "Main", main4 -> "Main4", main8 -> "Main8", main9 -> "Main9", mainB -> "MainB",
mainE -> "MainE1", mainE -> "MainE2", mainE -> "MainE3", mainE -> "MainE4", mainE -> "MainE5" )
(callback.applications) must haveTheSameElementsAs(expected)
val loader = new URLClassLoader(Array(file.toURI.toURL), getClass.getClassLoader)
for( (_, className) <- expected) testRun(loader, className)
}
for(scalaVersion <- TestCompile.allVersions)
CallbackTest(scalaVersion, files, Nil) { (callback, file, log) =>
val expected = Seq( main -> "Main", main4 -> "Main4", main8 -> "Main8", main9 -> "Main9", mainB -> "MainB",
mainE -> "MainE1", mainE -> "MainE2", mainE -> "MainE3", mainE -> "MainE4", mainE -> "MainE5" )
(callback.applications) must haveTheSameElementsAs(expected)
val loader = new URLClassLoader(Array(file.toURI.toURL), getClass.getClassLoader)
for( (_, className) <- expected) testRun(loader, className)
}
}
}
private def testRun(loader: ClassLoader, className: String)

View File

@ -0,0 +1,29 @@
package xsbt
import java.io.File
import org.specs.Specification
object CheckBasic extends Specification
{
val basicName = new File("Basic.scala")
val basicSource = "package org.example { object Basic }"
"Compiling basic file should succeed" in {
WithFiles(basicName -> basicSource){ files =>
for(scalaVersion <- TestCompile.allVersions)
{
TestCompile(scalaVersion, files){ loader => Class.forName("org.example.Basic", false, loader) }
true must beTrue // don't know how to just check that previous line completes without exception
}
}
}
"Analyzer plugin should send source begin and end" in {
WithFiles(basicName -> basicSource) { files =>
for(scalaVersion <- TestCompile.allVersions)
CallbackTest(scalaVersion, files) { callback =>
(callback.beganSources) must haveTheSameElementsAs(files)
(callback.endedSources) must haveTheSameElementsAs(files)
}
}
}
}

View File

@ -4,13 +4,15 @@ import java.io.File
import FileUtilities.withTemporaryDirectory
import org.specs._
// compile w/ analysis a bit hard to test properly right now:
// requires compile project to depend on +publish-local, which is not possible in sbt (addressed in xsbt, but that doesn't help here!)
object CompileTest extends Specification
{
"Analysis compiler" should {
"compile basic sources" in {
WithCompiler( "2.7.2" )(testCompileAnalysis)
WithCompiler( "2.7.3" )(testCompileAnalysis)
WithCompiler( "2.7.4" )(testCompileAnalysis)
WithCompiler( "2.7.5" )(testCompileAnalysis)
WithCompiler( "2.8.0-SNAPSHOT" )(testCompileAnalysis)
}
}
private def testCompileAnalysis(compiler: AnalyzingCompiler, log: CompileLogger)
@ -38,7 +40,12 @@ object WithCompiler
val manager = new ComponentManager(launch.getSbtHome(sbtVersion, scalaVersion), log)
prepare(manager, ComponentCompiler.compilerInterfaceSrcID, "CompilerInterface.scala")
prepare(manager, ComponentCompiler.xsbtiID, classOf[xsbti.AnalysisCallback])
f(AnalyzingCompiler(scalaVersion, launch, manager), log)
val result = f(AnalyzingCompiler(scalaVersion, launch, manager), log)
launch.clearScalaLoaderCache
System.gc()
System.gc()
System.gc()
result
}
}
}

View File

@ -18,16 +18,17 @@ object DetectSubclasses extends Specification
WithFiles(sources.map{case (file, content) => (new File(file), content)} : _*)
{
case files @ Seq(supFile, sup2File, midFile, sub1File, sub2File, sub3File) =>
CallbackTest(files, Seq( "a.Super", "Super2", "x.Super3", "Super4") ) { (callback, x, xx) =>
val expected =
(sub1File, "a.Sub1", "a.Super", false) ::
(sub2File, "Sub2", "a.Super", false) ::
(sup2File, "Super2", "Super2", false) ::
(sub3File, "c.Sub3", "Super2", true) ::
Nil
(callback.foundSubclasses) must haveTheSameElementsAs(expected)
(callback.invalidSuperclasses) must haveTheSameElementsAs(Seq("x.Super3", "Super4"))
}
for(scalaVersion <- TestCompile.allVersions)
CallbackTest(scalaVersion, files, Seq( "a.Super", "Super2", "x.Super3", "Super4") ) { (callback, x, xx) =>
val expected =
(sub1File, "a.Sub1", "a.Super", false) ::
(sub2File, "Sub2", "a.Super", false) ::
(sup2File, "Super2", "Super2", false) ::
(sub3File, "c.Sub3", "Super2", true) ::
Nil
(callback.foundSubclasses) must haveTheSameElementsAs(expected)
(callback.invalidSuperclasses) must haveTheSameElementsAs(Seq("x.Super3", "Super4"))
}
}
}
}

View File

@ -0,0 +1,36 @@
package xsbt
import java.io.File
import java.net.URLClassLoader
import xsbti.TestCallback
import FileUtilities.withTemporaryDirectory
object TestCompile
{
// skip 2.7.3 and 2.7.4 for speed
def allVersions = List("2.7.2", "2.7.5", "2.8.0-SNAPSHOT")//List("2.7.2", "2.7.3", "2.7.4", "2.7.5", "2.8.0-SNAPSHOT")
/** Tests running the compiler interface with the analyzer plugin with a test callback. The test callback saves all information
* that the plugin sends it for post-compile analysis by the provided function.*/
def apply[T](scalaVersion: String, sources: Set[File], outputDirectory: File, options: Seq[String], superclassNames: Seq[String])(f: (TestCallback, CompileLogger) => T): T =
{
val testCallback = new TestCallback(superclassNames.toArray)
val result = WithCompiler(scalaVersion) { (compiler, log) =>
compiler(sources, Set.empty, outputDirectory, options, testCallback, 5, log)
f(testCallback, log)
}
result
}
/** Tests running the compiler interface with the analyzer plugin. The provided function is given a ClassLoader that can
* load the compiled classes..*/
def apply[T](scalaVersion: String, sources: Seq[File])(f: ClassLoader => T): T =
CallbackTest.apply(scalaVersion, sources, Nil){ case (callback, outputDir, log) => f(new URLClassLoader(Array(outputDir.toURI.toURL))) }
}
object CallbackTest
{
def apply[T](scalaVersion: String, sources: Iterable[File])(f: TestCallback => T): T =
apply(scalaVersion, sources.toSeq, Nil){ case (callback, outputDir, log) => f(callback) }
def apply[T](scalaVersion: String, sources: Seq[File], superclassNames: Seq[String])(f: (TestCallback, File, CompileLogger) => T): T =
withTemporaryDirectory { outputDir =>
TestCompile(scalaVersion, Set() ++ sources, outputDir, Nil, superclassNames) { case (callback, log) => f(callback, outputDir, log) }
}
}

View File

@ -109,7 +109,8 @@ class Launch(projectRootDirectory: File, mainClassName: String) extends Launcher
}
}
private val scalaLoaderCache = new scala.collection.jcl.WeakHashMap[String, ClassLoader]
private val scalaLoaderCache = new scala.collection.mutable.HashMap[String, ClassLoader]
def clearScalaLoaderCache { scalaLoaderCache.clear() }
def launcher(directory: File, mainClassName: String): Launcher = new Launch(directory, mainClassName)
def getScalaLoader(scalaVersion: String) = scalaLoaderCache.getOrElseUpdate(scalaVersion, createScalaLoader(scalaVersion))