From 6351c6cc8c3014fd1fbb8244e872c9e28773dad0 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Wed, 19 Oct 2016 15:30:27 +0200 Subject: Create dotty-lib.jar for run tests --- test/dotc/build.scala | 22 ++++-- test/dotc/tests.scala | 64 ++++++++++++----- test/dotty/partest/DPConsoleRunner.scala | 113 +++++++++++++++++++++++++------ test/test/CompilerTest.scala | 42 ++++++++++-- test/test/DottyTest.scala | 9 ++- test/test/InterfaceEntryPointTest.scala | 15 +++- 6 files changed, 211 insertions(+), 54 deletions(-) (limited to 'test') diff --git a/test/dotc/build.scala b/test/dotc/build.scala index a805af7e5..b1c8db7c7 100644 --- a/test/dotc/build.scala +++ b/test/dotc/build.scala @@ -16,15 +16,25 @@ object build extends tests { } } if(deleteFolder) folder.delete() -} + } - def main(args: Array[String]): Unit = { - println("------------ Building dotty ------------") + def clearOutput() = { deleteFilesInFolder(new File(defaultOutputDir)) // clear previous output val keepFile = new File(defaultOutputDir + ".keep") keepFile.createNewFile() - dotty // build output dir - val p = Runtime.getRuntime.exec(Array("jar", "cf", "dotty.jar", "-C", "out", ".")) - p.waitFor() + } + + def main(args: Array[String]): Unit = { + println("---------- Building bootstrapped dotty-lib ----------------------------------------------") + clearOutput() + dottyBootedLib + val p1 = Runtime.getRuntime.exec(Array("jar", "cf", "dotty-lib.jar", "-C", "out", ".")) + p1.waitFor() + + println("---------- Building bootstrapped dotty depending on dotty-lib compiled by dotty ----------") + clearOutput() + dottyDependsOnBootedLib + val p2 = Runtime.getRuntime.exec(Array("jar", "cf", "dotty.jar", "-C", "out", ".")) + p2.waitFor() } } diff --git a/test/dotc/tests.scala b/test/dotc/tests.scala index 01539aa5a..4d3e8e1dd 100644 --- a/test/dotc/tests.scala +++ b/test/dotc/tests.scala @@ -14,19 +14,26 @@ class tests extends CompilerTest { val defaultOutputDir = "./out/" val noCheckOptions = List( -// "-verbose", -// "-Ylog:frontend", -// "-Xprompt", -// "-explaintypes", -// "-Yshow-suppressed-errors", - "-d", defaultOutputDir, - "-pagewidth", "160") - - implicit val defaultOptions = noCheckOptions ++ - List("-Yno-deep-subtypes", "-Yno-double-bindings", "-Yforce-sbt-phases", "-color:never") ++ { - if (isRunByJenkins) List("-Ycheck:tailrec,resolveSuper,mixin,restoreScopes,labelDef") // should be Ycheck:all, but #725 - else List("-Ycheck:tailrec,resolveSuper,mixin,restoreScopes,labelDef") - } +// "-verbose", +// "-Ylog:frontend", +// "-Xprompt", +// "-explaintypes", +// "-Yshow-suppressed-errors", + "-d", defaultOutputDir, + "-pagewidth", "80" + ) + + implicit val defaultOptions = noCheckOptions ++ { + if (isRunByJenkins) List("-Ycheck:tailrec,resolveSuper,mixin,restoreScopes,labelDef") // should be Ycheck:all, but #725 + else List("-Ycheck:tailrec,resolveSuper,mixin,restoreScopes,labelDef") + } ++ List( + "-Yno-deep-subtypes", + "-Yno-double-bindings", + "-Yforce-sbt-phases", + "-color:never", + "-classpath", + "./library/target/scala-2.11/dotty-library_2.11-0.1-SNAPSHOT.jar" + ) val testPickling = List("-Xprint-types", "-Ytest-pickler", "-Ystop-after:pickler", "-Yprintpos") @@ -58,6 +65,7 @@ class tests extends CompilerTest { val parsingDir = dotcDir + "parsing/" val dottyReplDir = dotcDir + "repl/" val typerDir = dotcDir + "typer/" + val libDir = "./library/src/" @Before def cleanup(): Unit = { // remove class files from stdlib and tests compilation @@ -177,7 +185,31 @@ class tests extends CompilerTest { |./scala-scala/src/library/scala/collection/generic/GenSeqFactory.scala""".stripMargin) @Test def compileIndexedSeq = compileLine("./scala-scala/src/library/scala/collection/immutable/IndexedSeq.scala") - @Test def dotty = compileDir(dottyDir, ".", List("-deep", "-Ycheck-reentrant", "-strict"))(allowDeepSubtypes) // note the -deep argument + // Not a junit test anymore since it is order dependent + def dottyBootedLib = compileDir( + libDir, + ".", + List( + "-deep", "-Ycheck-reentrant", "-strict", "-classpath", defaultOutputDir + + ":./target/scala-2.11/dotty-compiler_2.11-0.1-SNAPSHOT.jar" //WAT??? + ) + )(allowDeepSubtypes) // note the -deep argument + + // Not a junit test anymore since it is order dependent + def dottyDependsOnBootedLib = compileDir( + dottyDir, + ".", + List( + "-deep", "-Ycheck-reentrant", "-strict", "-classpath", defaultOutputDir + + ":./dotty-lib.jar" + + ":./interfaces/target/dotty-interfaces-0.1-SNAPSHOT.jar" + + // this needs to get compiled together with the compiler: + //":./target/scala-2.11/src_managed/main/scalajs-ir-src/" + // but falling back to: + ":/home/fixel/.ivy2/cache/org.scala-js/scalajs-ir_2.11/jars/scalajs-ir_2.11-0.6.8.jar" + // for the time being. + ) + )(allowDeepSubtypes) // note the -deep argument @Test def dotc_ast = compileDir(dotcDir, "ast") @Test def dotc_config = compileDir(dotcDir, "config") @@ -231,8 +263,8 @@ class tests extends CompilerTest { // Disabled because we get stale symbol errors on the SourceFile annotation, which is normal. // @Test def tasty_annotation_internal = compileDir(s"${dottyDir}annotation/", "internal", testPickling) - @Test def tasty_runtime = compileDir(s"$dottyDir", "runtime", testPickling) - @Test def tasty_runtime_vc = compileDir(s"${dottyDir}runtime/", "vc", testPickling) + @Test def tasty_runtime = compileDir(s"${libDir}dotty/", "runtime", testPickling) + @Test def tasty_runtime_vc = compileDir(s"${libDir}dotty/runtime/", "vc", testPickling) @Test def tasty_tools = compileDir(dottyDir, "tools", testPickling) diff --git a/test/dotty/partest/DPConsoleRunner.scala b/test/dotty/partest/DPConsoleRunner.scala index 18fac4de8..27d53159b 100644 --- a/test/dotty/partest/DPConsoleRunner.scala +++ b/test/dotty/partest/DPConsoleRunner.scala @@ -7,6 +7,9 @@ package dotty.partest import scala.reflect.io.AbstractFile import scala.tools.partest._ import scala.tools.partest.nest._ +import TestState.{ Pass, Fail, Crash, Uninitialized, Updated } +import ClassPath.{ join, split } +import FileManager.{ compareFiles, compareContents, joinPaths, withTempFile } import scala.util.matching.Regex import tools.nsc.io.{ File => NSCFile } import java.io.{ File, PrintStream, FileOutputStream, PrintWriter, FileWriter } @@ -27,6 +30,10 @@ object DPConsoleRunner { case Nil => sys.error("Error: DPConsoleRunner needs \"-dottyJars *\".") case jarFinder(nr, jarString) :: Nil => val jars = jarString.split(" ").toList + println("------------------------------------------------------------") + println("jars:") + jars.foreach(println) + println("------------------------------------------------------------") val count = nr.toInt if (jars.length < count) sys.error("Error: DPConsoleRunner found wrong number of dottyJars: " + jars + ", expected: " + nr) @@ -39,7 +46,6 @@ object DPConsoleRunner { // console runner has a suite runner which creates a test runner for each test class DPConsoleRunner(args: String, extraJars: List[String]) extends ConsoleRunner(args) { - override val suiteRunner = new DPSuiteRunner ( testSourcePath = optSourcePath getOrElse DPConfig.testRoot, fileManager = new DottyFileManager(extraJars), @@ -149,7 +155,11 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn "-d", outDir.getAbsolutePath, "-classpath", - joinPaths(outDir :: extraClasspath ++ testClassPath) + joinPaths(outDir :: extraClasspath.filter { fp => + fp.endsWith("dotty-lib.jar") || + fp.endsWith("scala-library-2.11.5.jar") || + fp.endsWith("scala-reflect-2.11.5.jar") + }) ) ++ files.map(_.getAbsolutePath) pushTranscript(args mkString " ") @@ -162,6 +172,59 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn } } + override def run(): TestState = { + if (kind == "run") { + // javac runner, for one, would merely append to an existing log file, so + // just delete it before we start + logFile.delete() + runTestCommon(execTest(outDir, logFile) && diffIsOk) + lastState + } else super.run() + } + + // Re-implemented for running tests + def execTest(outDir: File, logFile: File): Boolean = { + val argsFile = testFile changeExtension "javaopts" + val argString = file2String(argsFile) + if (argString != "") NestUI.verbose( + "Found javaopts file '%s', using options: '%s'".format(argsFile, argString) + ) + + val classpath = joinPaths { + val sep = sys.props("path.separator") + val fps = extraClasspath.filter { fp => + fp.endsWith("dotty-lib.jar") || + fp.endsWith("scala-library-2.11.5.jar") || + fp.endsWith("scala-reflect-2.11.5.jar") + } + + fps ++ fileManager.testClassPath + } + + val javaOpts: List[String] = ( + suiteRunner.javaOpts.split(' ') ++ + extraJavaOptions ++ + argString.split(' ') + ).map(_.trim).filter(_ != "").toList + + val cmd: List[String] = (suiteRunner.javaCmdPath :: javaOpts) ++ ( + "-classpath" :: join(outDir.toString, classpath) :: + "Test" :: "jvm" :: // default argument to Test class in super is "jvm" + Nil + ) + + pushTranscript((cmd mkString s" \\$EOL ") + " > " + logFile.getName) + nextTestAction(runCommand(cmd, logFile)) { + case false => + //_transcript append EOL + logFile.fileContents + // think this is equivalent: + val contents = logFile.fileContents + println(contents) + pushTranscript(contents) + genFail("non-zero exit code") + } + } + // FIXME: This is copy-pasted from nest.Runner where it is private // Remove this once https://github.com/scala/scala-partest/pull/61 is merged /** Runs command redirecting standard out and @@ -196,6 +259,7 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn if (specificFlags.isEmpty) defaultFlags else specificFlags } + val defaultFlags = { val defaultFile = parentFile.listFiles.toList.find(_.getName == "__defaultFlags.flags") defaultFile.map({ file => @@ -206,7 +270,6 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn // override to add the check for nr of compilation errors if there's a // target.nerr file override def runNegTest() = runInContext { - import TestState.{ Crash, Fail } import scala.reflect.internal.FatalError sealed abstract class NegTestState @@ -233,11 +296,14 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn // we keep the partest semantics where only one round needs to fail // compilation, not all - val compFailingRounds = compilationRounds(testFile).map({round => - val ok = round.isOk - setLastState(if (ok) genPass else genFail("compilation failed")) - (round.result, ok) - }).filter({ case (_, ok) => !ok }) + val compFailingRounds = + compilationRounds(testFile) + .map { round => + val ok = round.isOk + setLastState(if (ok) genPass else genFail("compilation failed")) + (round.result, ok) + } + .filter { case (_, ok) => !ok } val failureStates = compFailingRounds.map({ case (result, _) => result match { // or, OK, we'll let you crash the compiler with a FatalError if you supply a check file @@ -250,21 +316,24 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn true } else { val existsNerr = failureStates.exists({ - case CompFailedButWrongNErr(exp, found) => nextTestActionFailing(s"wrong number of compilation errors, expected: $exp, found: $found"); true - case _ => false + case CompFailedButWrongNErr(exp, found) => + nextTestActionFailing(s"wrong number of compilation errors, expected: $exp, found: $found") + true + case _ => + false }) - if (existsNerr) { - false - } else { + + if (existsNerr) false + else { val existsDiff = failureStates.exists({ - case CompFailedButWrongDiff() => nextTestActionFailing(s"output differs"); true - case _ => false + case CompFailedButWrongDiff() => + nextTestActionFailing(s"output differs") + true + case _ => + false }) - if (existsDiff) { - false - } else { - nextTestActionFailing("expected compilation failure") - } + if (existsDiff) false + else nextTestActionFailing("expected compilation failure") } } } @@ -297,14 +366,14 @@ class DPTestRunner(testFile: File, suiteRunner: DPSuiteRunner) extends nest.Runn } pushTranscript(bestDiff) genFail("output differs") - case None => genPass() // redundant default case + case None => genPass() // redundant default case } getOrElse true } // override to add dotty and scala jars to classpath override def extraClasspath = { val cp = suiteRunner.fileManager.asInstanceOf[DottyFileManager].extraJarList ::: super.extraClasspath - println(s"extraClasspath: $cp") + //println(s"extraClasspath: $cp") cp } diff --git a/test/test/CompilerTest.scala b/test/test/CompilerTest.scala index 8cf6b2feb..fe63106b5 100644 --- a/test/test/CompilerTest.scala +++ b/test/test/CompilerTest.scala @@ -124,6 +124,26 @@ abstract class CompilerTest { compileFile(prefix, fileName, args, extension, true) } + def findJarFromRuntime(partialName: String): String = { + val urls = ClassLoader.getSystemClassLoader.asInstanceOf[java.net.URLClassLoader].getURLs.map(_.getFile.toString) + urls.find(_.contains(partialName)).getOrElse { + throw new java.io.FileNotFoundException( + s"""Unable to locate $partialName on classpath:\n${urls.toList.mkString("\n")}""" + ) + } + } + + private def compileWithJavac(fs: Array[String], args: Array[String]): Unit = { + val scalaLib = findJarFromRuntime("scala-library") + val fullArgs = Array( + "javac", + "-classpath", + s".:$scalaLib" + ) ++ args ++ fs ++ Array("-d", defaultOutputDir) + + Runtime.getRuntime.exec(fullArgs).waitFor() + } + /** Compiles the code files in the given directory together. If args starts * with "-deep", all files in subdirectories (and so on) are included. */ def compileDir(prefix: String, dirName: String, args: List[String] = Nil, runTest: Boolean = false) @@ -134,14 +154,21 @@ abstract class CompilerTest { case "-deep" :: args1 => (dir.deepFiles, args1) case _ => (dir.files, args) } - val filePaths = files.toArray.map(_.toString).filter(name => (name endsWith ".scala") || (name endsWith ".java")) + val (filePaths, javaFilePaths) = files + .toArray.map(_.toString) + .foldLeft((Array.empty[String], Array.empty[String])) { case (acc @ (fp, jfp), name) => + if (name endsWith ".scala") (name +: fp, jfp) + else if (name endsWith ".java") (fp, name +: jfp) + else (fp, jfp) + } val expErrors = expectedErrors(filePaths.toList) - (filePaths, normArgs, expErrors) + (filePaths, javaFilePaths, normArgs, expErrors) } if (!generatePartestFiles || !partestableDir(prefix, dirName, args ++ defaultOptions)) { if (runTest) log(s"WARNING: run tests can only be run by partest, JUnit just verifies compilation: $prefix$dirName") - val (filePaths, normArgs, expErrors) = computeFilePathsAndExpErrors + val (filePaths, javaFilePaths, normArgs, expErrors) = computeFilePathsAndExpErrors + compileWithJavac(javaFilePaths, Array.empty) // javac needs to run first on dotty-library compileArgs(filePaths ++ normArgs, expErrors) } else { val (sourceDir, flags, deep) = args match { @@ -154,7 +181,7 @@ abstract class CompilerTest { if (sourceDir.exists) { val firstDest = Directory(DPConfig.testRoot + JFile.separator + kind + JFile.separator + dirName) val xerrors = if (isNegTest(prefix)) { - val (_, _, expErrors) = computeFilePathsAndExpErrors + val (_, _, _, expErrors) = computeFilePathsAndExpErrors expErrors.map(_.totalErrors).sum } else 0 computeDestAndCopyFiles(sourceDir, firstDest, kind, flags, xerrors.toString) @@ -234,6 +261,7 @@ abstract class CompilerTest { private def compileArgs(args: Array[String], expectedErrorsPerFile: List[ErrorsInFile]) (implicit defaultOptions: List[String]): Unit = { val allArgs = args ++ defaultOptions + //println(s"""all args: ${allArgs.mkString("\n")}""") val processor = if (allArgs.exists(_.startsWith("#"))) Bench else Main val storeReporter = new Reporter with UniqueMessagePositions with HideNonSensicalMessages { private val consoleReporter = new ConsoleReporter() @@ -472,16 +500,16 @@ abstract class CompilerTest { try { SFile(dest)(scala.io.Codec.UTF8).writeAll((s"/* !!!!! WARNING: DO NOT MODIFY. Original is at: $file !!!!! */").replace("\\", "/"), file.slurp("UTF-8")) } catch { - case unmappable: java.nio.charset.MalformedInputException => + case unmappable: java.nio.charset.MalformedInputException => copyfile(file, true) //there are bytes that can't be mapped with UTF-8. Bail and just do a straight byte-wise copy without the warning header. } } } - processFileDir(sourceFile, { sf => + processFileDir(sourceFile, { sf => if (extensionsToCopy.contains(sf.extension)) { dest.parent.jfile.mkdirs - copyfile(sf, false) + copyfile(sf, false) } else { log(s"WARNING: ignoring $sf") } diff --git a/test/test/DottyTest.scala b/test/test/DottyTest.scala index 4c8cd8a7b..57bd9bbc4 100644 --- a/test/test/DottyTest.scala +++ b/test/test/DottyTest.scala @@ -22,8 +22,14 @@ class DottyTest extends ContextEscapeDetection{ val base = new ContextBase {} import base.settings._ val ctx = base.initialCtx.fresh - base.initialize()(ctx) ctx.setSetting(ctx.settings.encoding, "UTF8") + ctx.setSetting( + ctx.settings.classpath, + "./library/target/scala-2.11/dotty-library_2.11-0.1-SNAPSHOT.jar" + ) + // when classpath is changed in ctx, we need to re-initialize to get the + // correct classpath from PathResolver + base.initialize()(ctx) ctx } @@ -31,6 +37,7 @@ class DottyTest extends ContextEscapeDetection{ override def clearCtx() = { ctx = null } + private def compilerWithChecker(phase: String)(assertion:(tpd.Tree, Context) => Unit) = new Compiler { override def phases = { val allPhases = super.phases diff --git a/test/test/InterfaceEntryPointTest.scala b/test/test/InterfaceEntryPointTest.scala index 438a9fa47..a1a8433d7 100644 --- a/test/test/InterfaceEntryPointTest.scala +++ b/test/test/InterfaceEntryPointTest.scala @@ -18,8 +18,17 @@ import scala.collection.mutable.ListBuffer */ class InterfaceEntryPointTest { @Test def runCompilerFromInterface = { - val sources = List("./tests/pos/HelloWorld.scala").map(p => new java.io.File(p).getPath()) - val args = sources ++ List("-d", "./out/") + val sources = + List("./tests/pos/HelloWorld.scala").map(p => new java.io.File(p).getPath()) + val dottyInterfaces = + new java.io.File("./interfaces/dotty-interfaces-0.1-SNAPSHOT.jar").getPath + val dottyLibrary = + new java.io.File("./library/target/scala-2.11/dotty-library_2.11-0.1-SNAPSHOT.jar").getPath + + val args = + sources ++ + List("-d", "./out/") ++ + List("-classpath", dottyInterfaces + ":" + dottyLibrary) val mainClass = Class.forName("dotty.tools.dotc.Main") val process = mainClass.getMethod("process", @@ -45,6 +54,8 @@ class InterfaceEntryPointTest { errorCount += 1 if (diag.level == Diagnostic.WARNING) warningCount += 1 + + println(diag.message) } } -- cgit v1.2.3