From 3f12f2eb9fd2b7224e0134b8aa581b628eccd74d Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Sun, 1 Jul 2012 15:16:41 -0400 Subject: [PATCH] drop compilation tests 1. overlapped with integration tests 2. slower than integration tests 3. more fragile than integration tests --- compile/src/test/scala/ApplicationsTest.scala | 142 ------------------ compile/src/test/scala/BasicAPI.scala | 68 --------- compile/src/test/scala/CheckBasic.scala | 43 ------ compile/src/test/scala/CompileTest.scala | 97 ------------ .../src/test/scala/DetectAnnotations.scala | 61 -------- compile/src/test/scala/DetectSubclasses.scala | 43 ------ compile/src/test/scala/TestCompile.scala | 38 ----- compile/src/test/scala/WithCompiler.scala | 39 ----- 8 files changed, 531 deletions(-) delete mode 100644 compile/src/test/scala/ApplicationsTest.scala delete mode 100644 compile/src/test/scala/BasicAPI.scala delete mode 100644 compile/src/test/scala/CheckBasic.scala delete mode 100644 compile/src/test/scala/CompileTest.scala delete mode 100644 compile/src/test/scala/DetectAnnotations.scala delete mode 100644 compile/src/test/scala/DetectSubclasses.scala delete mode 100644 compile/src/test/scala/TestCompile.scala delete mode 100644 compile/src/test/scala/WithCompiler.scala diff --git a/compile/src/test/scala/ApplicationsTest.scala b/compile/src/test/scala/ApplicationsTest.scala deleted file mode 100644 index 564ab05a3..000000000 --- a/compile/src/test/scala/ApplicationsTest.scala +++ /dev/null @@ -1,142 +0,0 @@ -package xsbt.api - - import java.io.File - import java.net.URLClassLoader - import org.specs.Specification - import sbt.WithFiles - import sbt.compiler.{CallbackTest,TestCompile} - -/** Verifies that the analyzer plugin properly detects main methods. The main method must be -* public with the right signature and be defined on a public, top-level module.*/ -object ApplicationsTest extends Specification -{ - val sourceContent = - """ - object Main { def main(args: Array[String]) {} } - """ :: """ - class Main2 { def main(args: Array[String]) {} } - """ :: """ - object Main3 { private def main(args: Array[String]) {} } - private object Main3b extends Main2 - object Main3c { private def main(args: Array[String]) {} } - protected object Main3d { def main(args: Array[String]) {} } - object Main3e { - protected def main(args: Array[String]) {} - } - package a { - object Main3f { private[a] def main(args: Array[String]) {} } - object Main3g { protected[a] def main(args: Array[String]) {} } - } - """ ::""" - object Main4 extends Main2 - """ :: """ - trait Main5 { def main(args: Array[String]) {} }; trait Main5b extends Main5; trait Main5c extends Main2; abstract class Main5d { def main(args: Array[String]) {} }; - trait Main5e[T] { def main(args: Array[T]) {} } - trait Main5f[T <: String] { def main(args: Array[T]) {} } - """ :: """ - object Main6a { var main = () } - object Main6b { var main = (args: Array[String]) => () } - """ :: """ - object Main7 { object Main7b extends Main2 } - """ :: """ - object Main8 extends Main2 { object Main7b extends Main2 } - """ :: """ - object Main9 { - def main() {} - def main(i: Int) {} - def main(args: Array[String]) {} - } - """ :: """ - object MainA { - def main() {} - def main(i: Int) {} - def main(args: Array[String], other: String) {} - def main(i: Array[Int]) {} - } - object MainA2 { - def main[T](args: Array[T]) {} - } - """ :: """ - object MainB extends Main2 { - def main() {} - def main(i: Int) {} - } - """ :: """ - object MainC1 { - def main(args: Array[String]) = 3 - } - object MainC2 { - def main1(args: Array[String]) {} - } - """ :: """ - object MainD1 { - val main = () - } - object MainD2 { - val main = (args: Array[String]) => () - } - """ :: """ - object MainE1 { - type T = String - def main(args: Array[T]) {} - } - object MainE2 { - type AT = Array[String] - def main(args: AT) {} - } - object MainE3 { - type U = Unit - type T = String - def main(args: Array[T]): U = () - } - object MainE4 { - def main[T](args: Array[String]) {} - } - object MainE5 { - type A[T] = Array[String] - def main[T](args: A[T]) {} - } - object MainE6 extends Main5e[String] - object MainE7 extends Main5e[Int] - object MainE8 extends Main5f[String] - """ :: """ - object MainF1 extends Application { var x = 3; x = 5 } - object MainF2 { def main(args: Array[java.lang.String]) {} } - trait MainF3 { def main(args: Array[String]) {} } - object MainF4 extends MainF3 { } - """ :: - Nil - val sources = for((source, index) <- sourceContent.zipWithIndex) yield new File("Main" + (index+1) + ".scala") -> source - - "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, mainF) => - for(scalaVersion <- TestCompile.allVersions) - CallbackTest.full(scalaVersion, files) { (callback, file, scalaInstance, log) => - val expected = Set( main -> "Main", main4 -> "Main4", main8 -> "Main8", main9 -> "Main9", mainB -> "MainB", - mainE -> "MainE1", mainE -> "MainE2", mainE -> "MainE3", mainE -> "MainE4", mainE -> "MainE5", mainE -> "MainE6", mainE -> "MainE8", - mainF -> "MainF1", mainF -> "MainF2", mainF -> "MainF4") - // the source signature is valid for the following, but the binary signature is not, so they can't actually be run. - // these are then known discrepancies between detected and actual entry points - val erased = Set( mainE -> "MainE6", mainE -> "MainE8" ) - val actual = applications(callback).toSet - (actual -- expected) must beEmpty - (expected -- actual) must beEmpty - val loader = new URLClassLoader(Array(file.toURI.toURL), scalaInstance.loader) - for( (_, className) <- expected filterNot erased) testRun(loader, className) - } - } - } - def applications(callback: xsbti.TestCallback): Seq[(File, String)] = - for( (file, api) <- CallbackTest.apis(callback); - x = println("\n" + file + ":\n" + (api.definitions.flatMap { case c: xsbti.api.ClassLike => c.structure.inherited.filter(_.name == "main"); case _ => Nil }).map(xsbt.api.DefaultShowAPI.apply).mkString("\n")); - application <- applications(api)) - yield (file, application) - def applications(src: xsbti.api.SourceAPI): Seq[String] = - Discovery.applications(src.definitions) collect { case (definition, Discovered(_, _, true, _)) => definition.name } - - private def testRun(loader: ClassLoader, className: String) - { - val obj = Class.forName(className, true, loader) - obj.getMethod("main", classOf[Array[String]]).invoke(null, new Array[String](0)) - } -} \ No newline at end of file diff --git a/compile/src/test/scala/BasicAPI.scala b/compile/src/test/scala/BasicAPI.scala deleted file mode 100644 index 0c191d09d..000000000 --- a/compile/src/test/scala/BasicAPI.scala +++ /dev/null @@ -1,68 +0,0 @@ -package sbt -package compiler - - import java.io.File - import org.specs.Specification - -object CheckBasicAPI extends Specification -{ - val basicName = new File("Basic.scala") - val basicSource = -""" -package org.example { - trait Parent[A] { def x: A } - abstract class Child extends Parent[String] - class S { - def x = new { def y = new S { def z = new Child { def x = "asdf" } } } - final val xconst = 3 - private[this] def zz: Seq[_] = Nil - type L[M[_], P >: Int <: Int] = M[P] - type Q = L[Option, Int] - } - object Basic - trait Out { - trait In - def t: In - } -} -package org.example3 { - trait A extends Iterator[Int] -} -package org.example2 { - trait ZZ[S] { - val p: S - val q: ZZZ[S] { val what: S } - class A extends ZZZ[S] { - val p = error("") - val q = error("") - } - } - trait ZZZ[T] extends ZZ[List[T]] - trait ZZZZ extends ZZZ[Int] - trait Z extends ZZZZ - trait P[S] { - trait Q - def x(s: S): S - def q(v: Q): Q - val u: Q - val p: S - } - trait Out { self: P[String] => - trait In - def z = p - def t(i: In): In - def y(q: Q): Q - } -} -""" - - "Compiling 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 - } - } - } -} \ No newline at end of file diff --git a/compile/src/test/scala/CheckBasic.scala b/compile/src/test/scala/CheckBasic.scala deleted file mode 100644 index 0195706ca..000000000 --- a/compile/src/test/scala/CheckBasic.scala +++ /dev/null @@ -1,43 +0,0 @@ -package sbt -package compiler - - import java.io.File - import org.specs.Specification - -object CheckBasic extends Specification -{ - val basicName = new File("Basic.scala") - val basicSource = "package org.example { /** A comment */ 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 - } - } - } - "Scaladoc on basic file should succeed" in { - WithFiles(basicName -> basicSource){ files => - for(scalaVersion <- TestCompile.allVersions) - { - IO.withTemporaryDirectory { outputDirectory => - WithCompiler(scalaVersion) { (compiler, log) => - compiler.doc(files.toSeq, Nil, outputDirectory, Nil, 5, log) - } - } - 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.simple(scalaVersion, files) { callback => - (callback.beganSources) must haveTheSameElementsAs(files) - (callback.endedSources) must haveTheSameElementsAs(files) - } - } - } -} \ No newline at end of file diff --git a/compile/src/test/scala/CompileTest.scala b/compile/src/test/scala/CompileTest.scala deleted file mode 100644 index c5ab75db2..000000000 --- a/compile/src/test/scala/CompileTest.scala +++ /dev/null @@ -1,97 +0,0 @@ -package sbt -package compiler - - import java.io.File - import IO.withTemporaryDirectory - import org.specs._ - -object CompileTest extends Specification -{ - "Analysis compiler" should { - "compile basic sources" in { - WithCompiler( "2.9.1" )(testCompileAnalysis) - WithCompiler( "2.9.0-1" )(testCompileAnalysis) - WithCompiler( "2.8.0" )(testCompileAnalysis) - WithCompiler( "2.8.1" )(testCompileAnalysis) - } - } - - "Raw compiler" should { - "Properly handle classpaths" in { - testClasspath("2.9.1") - testClasspath("2.9.0-1") - testClasspath("2.8.1") - testClasspath("2.8.0") - } - } - - private def testCompileAnalysis(compiler: AnalyzingCompiler, log: Logger) - { - WithFiles( new File("Test.scala") -> "object Test" ) { sources => - withTemporaryDirectory { temp => - val callback = new xsbti.TestCallback - compiler(sources, noChanges, Nil, temp, Nil, callback, 10, CompilerCache.fresh, log) - (callback.beganSources) must haveTheSameElementsAs(sources) - } - } - } - val noChanges = new xsbti.compile.DependencyChanges { - def isEmpty = true - def modifiedBinaries = Array() - def modifiedClasses = Array() - } - - val UsingCompiler = "object Test { classOf[scala.tools.nsc.Global] }" - - private def shouldFail(act: => Unit) = - { - val success = try { act; true } catch { case t if expectedException(t) => false } - if(success) error("Expected exception not thrown") - } - private def expectedException(t: Throwable) = - t match - { - case e: Exception => true - case t if isMissingRequirementError(t) => true - case _ => false - } - private def shouldSucceed(act: => Unit) = - try { act } catch { case c: xsbti.CompileFailed => error(c.toString) } - - private def isMissingRequirementError(t: Throwable) = t.getClass.getName == "scala.tools.nsc.MissingRequirementError" - private def testClasspath(scalaVersion: String) = - WithCompiler.launcher { (launch, log) => - def compiler(bootLibrary: Boolean, compilerOnClasspath: Boolean): RawCompiler = - new RawCompiler(ScalaInstance(scalaVersion, launch), new ClasspathOptions(bootLibrary, compilerOnClasspath, true, true, bootLibrary), log) - - val callback = new xsbti.TestCallback - - val standard = compiler(true, true) - val noCompiler = compiler(true, false) - val fullExplicit = compiler(false, false) - - val fullBoot = "-bootclasspath" :: fullExplicit.compilerArguments.createBootClasspath(true) :: Nil - val withCompiler = noCompiler.scalaInstance.compilerJar :: Nil - val withLibrary = noCompiler.scalaInstance.libraryJar :: Nil - val withLibraryCompiler = withLibrary ++ withCompiler - - WithFiles( new File("Test.scala") -> "object Test", new File("Test2.scala") -> UsingCompiler ) { case Seq(plain, useCompiler) => - val plainSrcs = Seq[File](plain) - val compSrcs = Seq[File](useCompiler) - withTemporaryDirectory { out => - shouldSucceed( standard(plainSrcs, Nil, out, Nil) ) - shouldSucceed( standard(compSrcs, Nil, out, Nil) ) - - shouldSucceed( noCompiler(plainSrcs, Nil, out, Nil) ) - shouldFail( noCompiler(compSrcs, Nil, out, Nil) ) - shouldSucceed( noCompiler(compSrcs, withCompiler, out, Nil) ) - - shouldFail( fullExplicit(plainSrcs, Nil, out, Nil) ) - shouldFail( fullExplicit(compSrcs, Nil, out, Nil) ) - shouldSucceed( fullExplicit(plainSrcs, withLibrary, out, fullBoot) ) - shouldSucceed( fullExplicit(compSrcs, withLibraryCompiler, out, fullBoot) ) - true must beTrue - } - } - } -} diff --git a/compile/src/test/scala/DetectAnnotations.scala b/compile/src/test/scala/DetectAnnotations.scala deleted file mode 100644 index 4add99d09..000000000 --- a/compile/src/test/scala/DetectAnnotations.scala +++ /dev/null @@ -1,61 +0,0 @@ -package xsbt.api - - import sbt.WithFiles - import sbt.compiler.{CallbackTest,TestCompile} - import java.io.File - import org.specs.Specification - -object DetectAnnotations extends Specification -{ - val sources = - ("c/A.scala" -> "package c; class A(x: Int, y: Int) extends Annotation") :: - ("B.scala" -> "class B extends Annotation") :: - ("d/C.scala" -> "package d; class C extends Annotation") :: - ("a/Super1.scala" -> "package a; trait Super1") :: - ("a/Super2.scala" -> "package a; @c.A(3,4) trait Super2") :: - ("Super3.scala" -> "@B class Super3") :: - ("a/Super4.scala" -> "package a; trait Super4 { @d.C def test = () }") :: - ("b/Middle.scala" -> "package y.w; trait Mid extends a.Super2") :: - ("b/Sub1.scala" -> "class Sub1 extends Super3 with y.w.Mid") :: - ("b/Sub2.scala" -> "final class Sub2 extends a.Super1") :: - ("b/Sub3.scala" -> "@B @c.A(3,4) final class Sub3 extends a.Super1") :: - ("d/Sub4.scala" -> "@B private class Sub4 extends a.Super1") :: - ("d/Sub5.scala" -> "@B protected class Sub5 extends a.Super1") :: - ("d/Sub6.scala" -> "@B abstract class Sub6 extends a.Super1") :: - ("d/Sub7.scala" -> "class Sub7 extends a.Super4") :: - ("d/Sub8.scala" -> "class Sub8 { @c.A(5,6) def test(s: Int) = s }") :: - ("d/Sub9.scala" -> "object Sub9 { @B def test(s: String) = s }") :: - ("d/SubA.scala" -> "object SubA { @c.A(3,3) def test = () }\nclass SubA { @B private def test = 6 }") :: - ("d/SubB.scala" -> "object SubB { @c.A(3,3) def test = 3 }\nclass SubB { @d.C def test = () }") :: - Nil - - "Analysis plugin should detect annotations" in { - WithFiles(sources.map{case (file, content) => (new File(file), content)} : _*) - { - case files @ Seq(a, b, c, sup1File, sup2File, sup3File, sup4File, midFile, sub1File, sub2File, sub3File, sub4File, sub5File, sub6File, sub7File, sub8File, sub9File, subAFile, subBFile) => - for(scalaVersion <- TestCompile.allVersions) - CallbackTest.simple(scalaVersion, files) { callback => - val expected = - (sup3File, "Super3", Set("B"), false) :: - (sub3File, "Sub3", Set("B", "c.A"), false) :: - (sub7File, "Sub7", Set("d.C"), false) :: - (sub8File, "Sub8", Set("c.A"), false) :: - (sub9File, "Sub9", Set("B"), true) :: - (subAFile, "SubA", Set("c.A"), true) :: - (subBFile, "SubB", Set("c.A"), true) :: - (subBFile, "SubB", Set("d.C"), false) :: - Nil - val actual = subclasses(callback).toSet - val actualOnly = (actual -- expected) - val expectedOnly = (expected.toSet -- actual) - expectedOnly must beEmpty - actualOnly must beEmpty - } - } - } - def subclasses(callback: xsbti.TestCallback): Seq[(File, String, Set[String], Boolean)] = - for( (file, src) <- CallbackTest.apis(callback); (definition, discovered) <- Discovery(Set.empty, annotationNames)(src.definitions) if !discovered.isEmpty ) yield - (file, definition.name, discovered.annotations, discovered.isModule) - - def annotationNames = Set("c.A", "B", "d.C") -} \ No newline at end of file diff --git a/compile/src/test/scala/DetectSubclasses.scala b/compile/src/test/scala/DetectSubclasses.scala deleted file mode 100644 index b8d1760f6..000000000 --- a/compile/src/test/scala/DetectSubclasses.scala +++ /dev/null @@ -1,43 +0,0 @@ -package xsbt.api - - import sbt.WithFiles - import sbt.compiler.{CallbackTest,TestCompile} - import java.io.File - import org.specs.Specification - -object DetectSubclasses extends Specification -{ - val sources = - ("a/Super.scala" -> "package a; trait Super") :: - ("a/Super2.scala" -> "class Super2") :: - ("b/Middle.scala" -> "package y.w; trait Mid extends a.Super") :: - ("b/Sub1.scala" -> "package a; class Sub1 extends y.w.Mid") :: - ("b/Sub2.scala" -> "final class Sub2 extends a.Super") :: - ("Sub3.scala" -> "private class F extends a.Super; package c { object Sub3 extends Super2 }") :: - Nil - - "Analysis plugin should detect subclasses" in { - WithFiles(sources.map{case (file, content) => (new File(file), content)} : _*) - { - case files @ Seq(supFile, sup2File, midFile, sub1File, sub2File, sub3File) => - for(scalaVersion <- TestCompile.allVersions) - CallbackTest.simple(scalaVersion, files) { callback => - val expected = - (sub1File, "a.Sub1", Set("a.Super"), false) :: - (sub2File, "Sub2", Set("a.Super"), false) :: - (sup2File, "Super2", Set("Super2"), false) :: - (sub3File, "c.Sub3", Set("Super2"), true) :: - Nil - val actual = subclasses(callback).toSet - val actualOnly = actual -- expected - val expectedOnly = expected.toSet -- actual - actualOnly must beEmpty - expectedOnly must beEmpty - } - } - } - def subclasses(callback: xsbti.TestCallback): Seq[(File, String, Set[String], Boolean)] = - for( (file, src) <- CallbackTest.apis(callback); (definition, discovered) <- Discovery(subclassNames, Set.empty)(src.definitions) if !discovered.isEmpty ) yield - (file, definition.name, discovered.baseClasses, discovered.isModule) - def subclassNames = Set( "a.Super", "Super2", "x.Super3", "Super4") -} \ No newline at end of file diff --git a/compile/src/test/scala/TestCompile.scala b/compile/src/test/scala/TestCompile.scala deleted file mode 100644 index 3b6c9d5cb..000000000 --- a/compile/src/test/scala/TestCompile.scala +++ /dev/null @@ -1,38 +0,0 @@ -package sbt -package compiler - - import java.io.File - import java.net.URLClassLoader - import xsbti.TestCallback - import IO.withTemporaryDirectory - -object TestCompile -{ - def allVersions = List("2.8.1", "2.9.0-1", "2.8.0", "2.9.1") - /** 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: Seq[File], outputDirectory: File, options: Seq[String]) - (f: (TestCallback, xsbti.compile.ScalaInstance, Logger) => T): T = - { - val testCallback = new TestCallback - WithCompiler(scalaVersion) { (compiler, log) => - compiler(sources, CompileTest.noChanges, Nil, outputDirectory, options, testCallback, 5, CompilerCache.fresh, log) - f(testCallback, compiler.scalaInstance, 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](scalaVersion: String, sources: Seq[File])(f: ClassLoader => T): T = - CallbackTest.full(scalaVersion, sources){ case (_, outputDir, _, _) => f(new URLClassLoader(Array(outputDir.toURI.toURL))) } -} -object CallbackTest -{ - def simple[T](scalaVersion: String, sources: Seq[File])(f: TestCallback => T): T = - full(scalaVersion, sources){ case (callback, _, _, _) => f(callback) } - def full[T](scalaVersion: String, sources: Seq[File])(f: (TestCallback, File, xsbti.compile.ScalaInstance, Logger) => T): T = - withTemporaryDirectory { outputDir => - TestCompile(scalaVersion, sources, outputDir, Nil) { case (callback, instance, log) => f(callback, outputDir, instance, log) } - } - def apis(callback: xsbti.TestCallback) = - callback.apis.toSeq map { case (src, api) => (src, xsbt.api.APIUtil.minimize(api)) } -} \ No newline at end of file diff --git a/compile/src/test/scala/WithCompiler.scala b/compile/src/test/scala/WithCompiler.scala deleted file mode 100644 index c964096d2..000000000 --- a/compile/src/test/scala/WithCompiler.scala +++ /dev/null @@ -1,39 +0,0 @@ -package sbt -package compiler - - import xsbt.boot - import java.io.File - import IO.withTemporaryDirectory - -object WithCompiler -{ - def apply[T](scalaVersion: String)(f: (AnalyzingCompiler, Logger) => T): T = - { - launcher { (launch, log) => - withTemporaryDirectory { componentDirectory => - val manager = new ComponentManager(xsbt.boot.Locks, new boot.ComponentProvider(componentDirectory, true), None, log) - val compiler = new AnalyzingCompiler(ScalaInstance(scalaVersion, launch), manager, log) - compiler.newComponentCompiler(log).clearCache(ComponentCompiler.compilerInterfaceID) - define(manager, ComponentCompiler.compilerInterfaceSrcID, getResource("CompilerInterface.scala"), getClassResource(classOf[jline.Completor])) - define(manager, ComponentCompiler.xsbtiID, getClassResource(classOf[xsbti.AnalysisCallback])) - f(compiler, log) - } - } - } - def launcher[T](f: (xsbti.Launcher, Logger) => T): T = - TestLogger { log => - boot.LaunchTest.withLauncher { launch => f(launch, log) } - } - - def getClassResource(resource: Class[_]): File = IO.classLocationFile(resource) - def getResource(resource: String): File = - { - val src = getClass.getClassLoader.getResource(resource) - if(src ne null) IO.asFile(src) else error("Resource not found: " + resource) - } - def define(manager: ComponentManager, id: String, files: File*) - { - manager.clearCache(id) - manager.define(id, files) - } -} \ No newline at end of file