diff options
Diffstat (limited to 'examples/scala-js/compiler/src/test/scala/scala/scalajs/compiler/test/util')
3 files changed, 238 insertions, 0 deletions
diff --git a/examples/scala-js/compiler/src/test/scala/scala/scalajs/compiler/test/util/DirectTest.scala b/examples/scala-js/compiler/src/test/scala/scala/scalajs/compiler/test/util/DirectTest.scala new file mode 100644 index 0000000..8289129 --- /dev/null +++ b/examples/scala-js/compiler/src/test/scala/scala/scalajs/compiler/test/util/DirectTest.scala @@ -0,0 +1,70 @@ +package scala.scalajs.compiler.test.util + +import scala.tools.nsc._ +import reporters.{Reporter, ConsoleReporter} +import scala.reflect.internal.util.{ SourceFile, BatchSourceFile } + +import scala.scalajs.compiler.ScalaJSPlugin + +import scala.collection.mutable + +/** This is heavily inspired by scala's partest suite's DirectTest */ +abstract class DirectTest { + + /** these arguments are always added to the args passed to newSettings */ + def extraArgs: List[String] = Nil + + /** create settings objects for test from arg string */ + def newSettings(args: List[String]) = { + val s = new Settings + s processArguments (args, true) + s + } + + def newScalaJSCompiler(args: String*): Global = { + val settings = newSettings( + List( + "-d", testOutputPath, + "-bootclasspath", scalaLibPath, + "-classpath", scalaJSLibPath) ++ + extraArgs ++ args.toList) + + lazy val global: Global = new Global(settings, newReporter(settings)) { + override lazy val plugins = newScalaJSPlugin(global) :: Nil + } + + global + } + + def newScalaJSPlugin(global: Global): ScalaJSPlugin = + new ScalaJSPlugin(global) + + def newReporter(settings: Settings) = new ConsoleReporter(settings) + + def newSources(codes: String*) = codes.toList.zipWithIndex map { + case (src, idx) => new BatchSourceFile(s"newSource${idx + 1}.scala", src) + } + + def withRun[T](global: Global)(f: global.Run => T): T = { + global.reporter.reset() + f(new global.Run) + } + + def compileSources(global: Global)(sources: SourceFile*): Boolean = { + withRun(global)(_ compileSources sources.toList) + !global.reporter.hasErrors + } + + def compileString(global: Global)(sourceCode: String): Boolean = + compileSources(global)(newSources(sourceCode): _*) + + def compileString(sourceCode: String): Boolean = + compileString(defaultGlobal)(sourceCode) + + lazy val defaultGlobal = newScalaJSCompiler() + + def testOutputPath = sys.props("scala.scalajs.compiler.test.output") + def scalaJSLibPath = sys.props("scala.scalajs.compiler.test.scalajslib") + def scalaLibPath = sys.props("scala.scalajs.compiler.test.scalalib") + +} diff --git a/examples/scala-js/compiler/src/test/scala/scala/scalajs/compiler/test/util/JSASTTest.scala b/examples/scala-js/compiler/src/test/scala/scala/scalajs/compiler/test/util/JSASTTest.scala new file mode 100644 index 0000000..d3dfd75 --- /dev/null +++ b/examples/scala-js/compiler/src/test/scala/scala/scalajs/compiler/test/util/JSASTTest.scala @@ -0,0 +1,100 @@ +package scala.scalajs.compiler.test.util + +import language.implicitConversions + +import scala.tools.nsc._ +import scala.reflect.internal.util.SourceFile + +import scala.util.control.ControlThrowable + +import org.junit.Assert._ + +import scala.scalajs.compiler.{ScalaJSPlugin, JSTreeExtractors} +import JSTreeExtractors.jse +import scala.scalajs.ir +import ir.{Trees => js} + +abstract class JSASTTest extends DirectTest { + + private var lastAST: JSAST = _ + + class JSAST(val clDefs: List[js.Tree]) { + type Pat = PartialFunction[js.Tree, Unit] + + class PFTraverser(pf: Pat) extends ir.Traversers.Traverser { + private case object Found extends ControlThrowable + + private[this] var finding = false + + def find: Boolean = { + finding = true + try { + clDefs.map(traverse) + false + } catch { + case Found => true + } + } + + def traverse(): Unit = { + finding = false + clDefs.map(traverse) + } + + override def traverse(tree: js.Tree): Unit = { + if (finding && pf.isDefinedAt(tree)) + throw Found + + if (!finding) + pf.lift(tree) + + super.traverse(tree) + } + } + + def has(trgName: String)(pf: Pat): this.type = { + val tr = new PFTraverser(pf) + assertTrue(s"AST should have $trgName", tr.find) + this + } + + def hasNot(trgName: String)(pf: Pat): this.type = { + val tr = new PFTraverser(pf) + assertFalse(s"AST should not have $trgName", tr.find) + this + } + + def traverse(pf: Pat): this.type = { + val tr = new PFTraverser(pf) + tr.traverse() + this + } + + def show: this.type = { + clDefs foreach println _ + this + } + + } + + implicit def string2ast(str: String): JSAST = stringAST(str) + + override def newScalaJSPlugin(global: Global) = new ScalaJSPlugin(global) { + override def generatedJSAST(cld: List[js.Tree]): Unit = { + lastAST = new JSAST(cld) + } + } + + def stringAST(code: String): JSAST = stringAST(defaultGlobal)(code) + def stringAST(global: Global)(code: String): JSAST = { + compileString(global)(code) + lastAST + } + + def sourceAST(source: SourceFile): JSAST = sourceAST(defaultGlobal)(source) + def sourceAST(global: Global)(source: SourceFile): JSAST = { + compileSources(global)(source) + lastAST + } + +} diff --git a/examples/scala-js/compiler/src/test/scala/scala/scalajs/compiler/test/util/TestHelpers.scala b/examples/scala-js/compiler/src/test/scala/scala/scalajs/compiler/test/util/TestHelpers.scala new file mode 100644 index 0000000..adad89c --- /dev/null +++ b/examples/scala-js/compiler/src/test/scala/scala/scalajs/compiler/test/util/TestHelpers.scala @@ -0,0 +1,68 @@ +package scala.scalajs.compiler.test.util + +import java.io._ +import scala.tools.nsc._ + +import reporters.ConsoleReporter + +import org.junit.Assert._ + +import scala.util.matching.Regex + +trait TestHelpers extends DirectTest { + + private[this] val errBuffer = new CharArrayWriter + + override def newReporter(settings: Settings) = { + val in = new BufferedReader(new StringReader("")) + val out = new PrintWriter(errBuffer) + new ConsoleReporter(settings, in, out) + } + + /** will be prefixed to every code that is compiled. use for imports */ + def preamble = "" + + /** pimps a string to compile it and apply the specified test */ + implicit class CompileTests(val code: String) { + + def hasErrors(expected: String) = { + val reps = repResult { + assertFalse("snippet shouldn't compile", compileString(preamble + code)) + } + assertEquals("should have right errors", + expected.stripMargin.trim, reps.trim) + } + + def hasWarns(expected: String) = { + val reps = repResult { + assertTrue("snippet should compile", compileString(preamble + code)) + } + assertEquals("should have right warnings", + expected.stripMargin.trim, reps.trim) + } + + def fails() = + assertFalse("snippet shouldn't compile", compileString(preamble + code)) + + def warns() = { + val reps = repResult { + assertTrue("snippet should compile", compileString(preamble + code)) + } + assertFalse("should have warnings", reps.isEmpty) + } + + def succeeds() = + assertTrue("snippet should compile", compileString(preamble + code)) + + private def repResult(body: => Unit) = { + errBuffer.reset() + body + errBuffer.toString + } + } + + implicit class CodeWrappers(sc: StringContext) { + def expr() = new CompileTests(s"class A { ${sc.parts.mkString} }") + } + +} |