From 5d36bf9f2ff6bb5339e05a7ca6aac48e90ada174 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Fri, 17 Mar 2017 18:51:31 +0100 Subject: Make tests composable --- .../test/dotty/tools/dotc/CompilationTests.scala | 497 +++++++-------------- .../test/dotty/tools/dotc/ParallelTesting.scala | 277 ++++++++---- 2 files changed, 360 insertions(+), 414 deletions(-) diff --git a/compiler/test/dotty/tools/dotc/CompilationTests.scala b/compiler/test/dotty/tools/dotc/CompilationTests.scala index 283430565..8136cb861 100644 --- a/compiler/test/dotty/tools/dotc/CompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/CompilationTests.scala @@ -14,354 +14,185 @@ class CompilationTests extends ParallelTesting { compileFilesInDir("../tests/pos", defaultOptions).pos @Test def compilePosScala2: Unit = - compileFilesInDir("../tests/pos-scala2", scala2Mode).pos - - @Test def nullarifyPos: Unit = - compileFile("../tests/pos/nullarify.scala", defaultOptions.and("-Ycheck:nullarify")).pos - - @Test def rewrites: Unit = - compileFile("../tests/pos-scala2/rewrites.scala", scala2Mode.and("-rewrite")).pos - - @Test def t8146aPos: Unit = - compileFile("../tests/pos-special/t8146a.scala", allowDeepSubtypes).pos - - @Test def t5545Pos: Unit = - compileFilesInDir("../tests/pos-special/spec-t5545", defaultOptions).pos - - @Test def utf8encodedPos: Unit = - compileFile("../tests/pos-special/utf8encoded.scala", explicitUTF8).pos - - @Test def utf16encodedPos: Unit = - compileFile("../tests/pos-special/utf16encoded.scala", explicitUTF16).pos - - @Test def compileStdLibPos: Unit = - compileList(StdLibSources.whitelisted, scala2Mode.and("-migration", "-Yno-inline")).pos - - @Test def compileMixedPos: Unit = compileList( - List( - "../tests/pos/B.scala", - "../scala-scala/src/library/scala/collection/immutable/Seq.scala", - "../scala-scala/src/library/scala/collection/parallel/ParSeq.scala", - "../scala-scala/src/library/scala/package.scala", - "../scala-scala/src/library/scala/collection/GenSeqLike.scala", - "../scala-scala/src/library/scala/collection/SeqLike.scala", - "../scala-scala/src/library/scala/collection/generic/GenSeqFactory.scala" - ), - defaultOptions - ).pos - - @Test def compileIndexedSeqPos: Unit = - compileFile("../scala-scala/src/library/scala/collection/immutable/IndexedSeq.scala", defaultOptions).pos - - @Test def compileParSetLikePos: Unit = - compileFile("../scala-scala/src/library/scala/collection/parallel/mutable/ParSetLike.scala", defaultOptions).pos - - @Test def compileParSetSubsetPos: Unit = compileList( - List( - "../scala-scala/src/library/scala/collection/parallel/mutable/ParSetLike.scala", - "../scala-scala/src/library/scala/collection/parallel/mutable/ParSet.scala", - "../scala-scala/src/library/scala/collection/mutable/SetLike.scala" - ), - scala2Mode - ).pos - - @Test def compileAstPos: Unit = - compileDir("../compiler/src/dotty/tools/dotc/ast", defaultOptions).pos - - @Test def compileConfigPos: Unit = - compileDir("../compiler/src/dotty/tools/dotc/config", defaultOptions).pos - - @Test def compileCorePos: Unit = - compileDir("../compiler/src/dotty/tools/dotc/core", allowDeepSubtypes).pos - - @Test def compileCoreNoCheckPos: Unit = - compileDir("../compiler/src/dotty/tools/dotc/core", noCheckOptions ++ classPath).pos - - @Test def compileTransformPos: Unit = - compileDir("../compiler/src/dotty/tools/dotc/transform", allowDeepSubtypes).pos - - @Test def compileParsingPos: Unit = - compileDir("../compiler/src/dotty/tools/dotc/parsing", defaultOptions).pos - - @Test def compilePrintingPos: Unit = - compileDir("../compiler/src/dotty/tools/dotc/printing", defaultOptions).pos - - @Test def compileReportingPos: Unit = - compileDir("../compiler/src/dotty/tools/dotc/reporting", defaultOptions).pos - - @Test def compileTyperPos: Unit = - compileDir("../compiler/src/dotty/tools/dotc/typer", defaultOptions).pos - - @Test def compileUtilPos: Unit = - compileDir("../compiler/src/dotty/tools/dotc/util", defaultOptions).pos - - @Test def compileIoPos: Unit = - compileDir("../compiler/src/dotty/tools/io", defaultOptions).pos - - @Test def labelsPos: Unit = - compileFile("../tests/pos/Labels.scala", defaultOptions).times(2).pos - - @Test def testNonCyclic: Unit = compileList( - List( - "../compiler/src/dotty/tools/dotc/CompilationUnit.scala", - "../compiler/src/dotty/tools/dotc/core/Types.scala", - "../compiler/src/dotty/tools/dotc/ast/Trees.scala" - ), - defaultOptions.and("-Xprompt") - ).times(2).pos - - @Test def issue34Pos: Unit = compileList( - List( - "../compiler/src/dotty/tools/dotc/config/Properties.scala", - "../compiler/src/dotty/tools/dotc/config/PathResolver.scala" - ), - defaultOptions.and("-Xprompt") - ).times(2).pos - - @Test def javaInteropPos: Unit = - compileFilesInDir("../tests/pos-java-interop", defaultOptions).times(2).pos + compileFilesInDir("../tests/pos-scala2", scala2Mode).pos() + + @Test def compilePosMixedFlags: Unit = { + compileList(StdLibSources.whitelisted, scala2Mode.and("-migration", "-Yno-inline")) + + compileFile("../tests/pos/nullarify.scala", defaultOptions.and("-Ycheck:nullarify")) + + // this guy sucks, he changes the sourcefile itself: + // compileFile("../tests/pos-scala2/rewrites.scala", scala2Mode.and("-rewrite")) + + compileFile("../tests/pos-special/t8146a.scala", allowDeepSubtypes) + + compileFile("../tests/pos-special/utf8encoded.scala", explicitUTF8) + + compileFile("../tests/pos-special/utf16encoded.scala", explicitUTF16) + + compileList( + List( + "../tests/pos/B.scala", + "../scala-scala/src/library/scala/collection/immutable/Seq.scala", + "../scala-scala/src/library/scala/collection/parallel/ParSeq.scala", + "../scala-scala/src/library/scala/package.scala", + "../scala-scala/src/library/scala/collection/GenSeqLike.scala", + "../scala-scala/src/library/scala/collection/SeqLike.scala", + "../scala-scala/src/library/scala/collection/generic/GenSeqFactory.scala" + ), + defaultOptions + ) + + compileFilesInDir("../tests/pos-special/spec-t5545", defaultOptions) + + compileFile("../scala-scala/src/library/scala/collection/immutable/IndexedSeq.scala", defaultOptions) + + compileFile("../scala-scala/src/library/scala/collection/parallel/mutable/ParSetLike.scala", defaultOptions) + + compileList( + List( + "../scala-scala/src/library/scala/collection/parallel/mutable/ParSetLike.scala", + "../scala-scala/src/library/scala/collection/parallel/mutable/ParSet.scala", + "../scala-scala/src/library/scala/collection/mutable/SetLike.scala" + ), + scala2Mode + ) + }.pos() + + @Test def compileCoreNoCheck: Unit = + compileDir("../compiler/src/dotty/tools/dotc/core", noCheckOptions ++ classPath).pos() + + @Test def compileDotcInternals: Unit = { + compileDir("../compiler/src/dotty/tools/dotc/ast", defaultOptions) + + compileDir("../compiler/src/dotty/tools/dotc/config", defaultOptions) + + compileDir("../compiler/src/dotty/tools/dotc/core", allowDeepSubtypes) + + compileDir("../compiler/src/dotty/tools/dotc/transform", allowDeepSubtypes) + + compileDir("../compiler/src/dotty/tools/dotc/parsing", defaultOptions) + + compileDir("../compiler/src/dotty/tools/dotc/printing", defaultOptions) + + compileDir("../compiler/src/dotty/tools/dotc/reporting", defaultOptions) + + compileDir("../compiler/src/dotty/tools/dotc/typer", defaultOptions) + + compileDir("../compiler/src/dotty/tools/dotc/util", defaultOptions) + + compileDir("../compiler/src/dotty/tools/io", defaultOptions) + }.pos() + + @Test def posTwice: Unit = { + compileFile("../tests/pos/Labels.scala", defaultOptions) + + compileFilesInDir("../tests/pos-java-interop", defaultOptions) + + compileFile("../tests/pos/t2168.scala", defaultOptions) + + compileFile("../tests/pos/erasure.scala", defaultOptions) + + compileFile("../tests/pos/Coder.scala", defaultOptions) + + compileFile("../tests/pos/blockescapes.scala", defaultOptions) + + compileFile("../tests/pos/collections.scala", defaultOptions) + + compileFile("../tests/pos/functions1.scala", defaultOptions) + + compileFile("../tests/pos/implicits1.scala", defaultOptions) + + compileFile("../tests/pos/inferred.scala", defaultOptions) + + compileFile("../tests/pos/Patterns.scala", defaultOptions) + + compileFile("../tests/pos/selftypes.scala", defaultOptions) + + compileFile("../tests/pos/varargs.scala", defaultOptions) + + compileFile("../tests/pos/vararg-pattern.scala", defaultOptions) + + compileFile("../tests/pos/opassign.scala", defaultOptions) + + compileFile("../tests/pos/typedapply.scala", defaultOptions) + + compileFile("../tests/pos/nameddefaults.scala", defaultOptions) + + compileFile("../tests/pos/desugar.scala", defaultOptions) + + compileFile("../tests/pos/sigs.scala", defaultOptions) + + compileFile("../tests/pos/typers.scala", defaultOptions) + + compileDir("../tests/pos/typedIdents", defaultOptions) + + compileFile("../tests/pos/assignments.scala", defaultOptions) + + compileFile("../tests/pos/packageobject.scala", defaultOptions) + + compileFile("../tests/pos/overloaded.scala", defaultOptions) + + compileFile("../tests/pos/overrides.scala", defaultOptions) + + compileDir("../tests/pos/java-override", defaultOptions) + + compileFile("../tests/pos/templateParents.scala", defaultOptions) + + compileFile("../tests/pos/overloadedAccess.scala", defaultOptions) + + compileFile("../tests/pos/approximateUnion.scala", defaultOptions) + + compileFilesInDir("../tests/pos/tailcall", defaultOptions) + + compileShallowFilesInDir("../tests/pos/pos_valueclasses", defaultOptions) + + compileFile("../tests/pos/subtyping.scala", defaultOptions) + + compileFile("../tests/pos/i0239.scala", defaultOptions) + + compileFile("../tests/pos/anonClassSubtyping.scala", defaultOptions) + + compileFile("../tests/pos/extmethods.scala", defaultOptions) + + compileFile("../tests/pos/companions.scala", defaultOptions) + + compileList( + List( + "../compiler/src/dotty/tools/dotc/CompilationUnit.scala", + "../compiler/src/dotty/tools/dotc/core/Types.scala", + "../compiler/src/dotty/tools/dotc/ast/Trees.scala" + ), + defaultOptions.and("-Xprompt") + ) + + compileList( + "testIssue34", + List( + "../compiler/src/dotty/tools/dotc/config/Properties.scala", + "../compiler/src/dotty/tools/dotc/config/PathResolver.scala" + ), + defaultOptions.and("-Xprompt") + ) + }.times(2).pos() // New tests ----------------------------------------------------------------- @Test def compileNew: Unit = - compileFilesInDir("../tests/new", defaultOptions).pos + compileFilesInDir("../tests/new", defaultOptions).pos() // Negative tests ------------------------------------------------------------ @Test def compileNeg: Unit = - compileShallowFilesInDir("../tests/neg", defaultOptions).neg - - @Test def typedIdentsNeg: Unit = - compileDir("../tests/neg/typedIdents", defaultOptions).neg - - @Test def typersNeg: Unit = - compileFile("../tests/neg/customArgs/typers.scala", allowDoubleBindings).neg - - @Test def overrideClassNeg: Unit = - compileFile("../tests/neg/customArgs/overrideClass.scala", scala2Mode).neg - - @Test def autoTuplingNeg: Unit = - compileFile("../tests/neg/customArgs/autoTuplingTest.scala", defaultOptions.and("-language:noAutoTupling")).neg - - @Test def i1050Neg: Unit = - compileFile("../tests/neg/customArgs/i1050.scala", defaultOptions.and("-strict")).neg - - @Test def i1240Neg: Unit = - compileFile("../tests/neg/customArgs/i1240.scala", allowDoubleBindings).neg - - @Test def i2002Neg: Unit = - compileFile("../tests/neg/customArgs/i2002.scala", allowDoubleBindings).neg - - @Test def nopredefNeg: Unit = - compileFile("../tests/neg/customArgs/nopredef.scala", defaultOptions.and("-Yno-predef")).neg - - @Test def noimportsNeg: Unit = - compileFile("../tests/neg/customArgs/noimports.scala", defaultOptions.and("-Yno-imports")).neg - - @Test def noimports2Neg: Unit = - compileFile("../tests/neg/customArgs/noimports2.scala", defaultOptions.and("-Yno-imports")).neg - - @Test def t1672bTailcallNeg: Unit = - compileFile("../tests/neg/tailcall/t1672b.scala", defaultOptions).neg - - @Test def t3275TailcallNeg: Unit = - compileFile("../tests/neg/tailcall/t3275.scala", defaultOptions).neg - - @Test def t6574TailcallNeg: Unit = - compileFile("../tests/neg/tailcall/t6574.scala", defaultOptions).neg - - @Test def tailrecTailcallNeg: Unit = - compileFile("../tests/neg/tailcall/tailrec.scala", defaultOptions).neg - - @Test def tailrec2TailcallNeg: Unit = - compileFile("../tests/neg/tailcall/tailrec-2.scala", defaultOptions).neg - - @Test def tailrec3TailcallNeg: Unit = - compileFile("../tests/neg/tailcall/tailrec-3.scala", defaultOptions).neg + compileShallowFilesInDir("../tests/neg", defaultOptions).neg() + + @Test def compileNegCustomFlags: Unit = { + compileFile("../tests/neg/customArgs/typers.scala", allowDoubleBindings) + + compileFile("../tests/neg/customArgs/overrideClass.scala", scala2Mode) + + compileFile("../tests/neg/customArgs/autoTuplingTest.scala", defaultOptions.and("-language:noAutoTupling")) + + compileFile("../tests/neg/customArgs/i1050.scala", defaultOptions.and("-strict")) + + compileFile("../tests/neg/customArgs/i1240.scala", allowDoubleBindings) + + compileFile("../tests/neg/customArgs/i2002.scala", allowDoubleBindings) + + compileFile("../tests/neg/customArgs/nopredef.scala", defaultOptions.and("-Yno-predef")) + + compileFile("../tests/neg/customArgs/noimports.scala", defaultOptions.and("-Yno-imports")) + + compileFile("../tests/neg/customArgs/noimports2.scala", defaultOptions.and("-Yno-imports")) + + compileFile("../tests/neg/tailcall/t1672b.scala", defaultOptions) + + compileFile("../tests/neg/tailcall/t3275.scala", defaultOptions) + + compileFile("../tests/neg/tailcall/t6574.scala", defaultOptions) + + compileFile("../tests/neg/tailcall/tailrec.scala", defaultOptions) + + compileFile("../tests/neg/tailcall/tailrec-2.scala", defaultOptions) + + compileFile("../tests/neg/tailcall/tailrec-3.scala", defaultOptions) + + compileDir("../tests/neg/typedIdents", defaultOptions) + }.neg() // Run tests ----------------------------------------------------------------- @Test def runAll: Unit = - compileFilesInDir("../tests/run", defaultOptions).run - - @Test def runArraycopy: Unit = - compileFile("../tests/run/arraycopy.scala", defaultOptions).run - - // Benchmark Tests ----------------------------------------------------------- - - @Test def t2168Pos: Unit = - compileFile("../tests/pos/t2168.scala", defaultOptions).times(2).pos - - @Test def erasurePos: Unit = - compileFile("../tests/pos/erasure.scala", defaultOptions).times(2).pos - - @Test def coderPos: Unit = - compileFile("../tests/pos/Coder.scala", defaultOptions).times(2).pos - - @Test def blockescapesPos: Unit = - compileFile("../tests/pos/blockescapes.scala", defaultOptions).times(2).pos - - @Test def collectionsPos: Unit = - compileFile("../tests/pos/collections.scala", defaultOptions).times(2).pos - - @Test def functions1Pos: Unit = - compileFile("../tests/pos/functions1.scala", defaultOptions).times(2).pos - - @Test def implicits1Pos: Unit = - compileFile("../tests/pos/implicits1.scala", defaultOptions).times(2).pos - - @Test def inferredPos: Unit = - compileFile("../tests/pos/inferred.scala", defaultOptions).times(2).pos - - @Test def patternsPos: Unit = - compileFile("../tests/pos/Patterns.scala", defaultOptions).times(2).pos - - @Test def selftypesPos: Unit = - compileFile("../tests/pos/selftypes.scala", defaultOptions).times(2).pos - - @Test def varargsPos: Unit = - compileFile("../tests/pos/varargs.scala", defaultOptions).times(2).pos - - @Test def varargPatternsPos: Unit = - compileFile("../tests/pos/vararg-pattern.scala", defaultOptions).times(2).pos - - @Test def opassignPos: Unit = - compileFile("../tests/pos/opassign.scala", defaultOptions).times(2).pos - - @Test def typedapplyPos: Unit = - compileFile("../tests/pos/typedapply.scala", defaultOptions).times(2).pos - - @Test def nameddefaultsPos: Unit = - compileFile("../tests/pos/nameddefaults.scala", defaultOptions).times(2).pos - - @Test def desugarPos: Unit = - compileFile("../tests/pos/desugar.scala", defaultOptions).times(2).pos - - @Test def sigsPos: Unit = - compileFile("../tests/pos/sigs.scala", defaultOptions).times(2).pos - - @Test def typersPos: Unit = - compileFile("../tests/pos/typers.scala", defaultOptions).times(2).pos - - @Test def typedIdentsPos: Unit = - compileDir("../tests/pos/typedIdents", defaultOptions).times(2).pos - - @Test def assignmentsPos: Unit = - compileFile("../tests/pos/assignments.scala", defaultOptions).times(2).pos - - @Test def packageobjectPos: Unit = - compileFile("../tests/pos/packageobject.scala", defaultOptions).times(2).pos - - @Test def overloadedPos: Unit = - compileFile("../tests/pos/overloaded.scala", defaultOptions).times(2).pos - - @Test def overridesPos: Unit = - compileFile("../tests/pos/overrides.scala", defaultOptions).times(2).pos - - @Test def javaOverridePos: Unit = - compileDir("../tests/pos/java-override", defaultOptions).times(2).pos - - @Test def templateParentsPos: Unit = - compileFile("../tests/pos/templateParents.scala", defaultOptions).times(2).pos - - @Test def overloadedAccessPos: Unit = - compileFile("../tests/pos/overloadedAccess.scala", defaultOptions).times(2).pos - - @Test def approximateUnionPos: Unit = - compileFile("../tests/pos/approximateUnion.scala", defaultOptions).times(2).pos - - @Test def tailcallPos: Unit = - compileFilesInDir("../tests/pos/tailcall", defaultOptions).times(2).pos - - @Test def valueclassesPos: Unit = - compileShallowFilesInDir("../tests/pos/pos_valueclasses", defaultOptions).times(2).pos - - @Test def subtypingPos: Unit = - compileFile("../tests/pos/subtyping.scala", defaultOptions).times(2).pos - - @Test def packageObjPos: Unit = - compileFile("../tests/pos/i0239.scala", defaultOptions).times(2).pos - - @Test def anonClassSubtypingPos: Unit = - compileFile("../tests/pos/anonClassSubtyping.scala", defaultOptions).times(2).pos - - @Test def extmethodsPos: Unit = - compileFile("../tests/pos/extmethods.scala", defaultOptions).times(2).pos - - @Test def companionsPos: Unit = - compileFile("../tests/pos/companions.scala", defaultOptions).times(2).pos + compileFilesInDir("../tests/run", defaultOptions).run() // Pickling Tests ------------------------------------------------------------ - @Test def testPickling: Unit = - compileFilesInDir("../tests/pickling", picklingOptions).pos - - @Test def testPicklingAst: Unit = - compileDir("../compiler/src/dotty/tools/dotc/ast", picklingOptions).pos - - @Test def testPicklingInf: Unit = - compileFile("../tests/pos/pickleinf.scala", picklingOptions).pos - - @Test def tastyNew: Unit = - compileFilesInDir("../tests/new", picklingOptions).pos - - @Test def tastyRuntime: Unit = - compileDir("../library/src/dotty/runtime", picklingOptions).pos - - @Test def tastyTools: Unit = - compileDir("../compiler/src/dotty/tools", picklingOptions).pos - - @Test def tastyBackendJvm: Unit = - compileDir("../compiler/src/dotty/tools/backend/jvm", picklingOptions).pos - - @Test def tastyDotc: Unit = - compileDir("../compiler/src/dotty/tools/dotc", picklingOptions).pos - - @Test def tastyDotcAst: Unit = - compileDir("../compiler/src/dotty/tools/dotc/ast", picklingOptions).pos - - @Test def tastyDotcConfig: Unit = - compileDir("../compiler/src/dotty/tools/dotc/config", picklingOptions).pos - - @Test def tastyCore: Unit = - compileDir("../compiler/src/dotty/tools/dotc/core", picklingOptions).pos - - @Test def tastyClassfile: Unit = - compileDir("../compiler/src/dotty/tools/dotc/core/classfile", picklingOptions).pos - - @Test def dotcTasty: Unit = - compileDir("../compiler/src/dotty/tools/dotc/core/tasty", picklingOptions).pos - - @Test def tastyUnpickleScala2: Unit = - compileDir("../compiler/src/dotty/tools/dotc/core/unpickleScala2", picklingOptions).pos - - @Test def tastyParsing: Unit = - compileDir("../compiler/src/dotty/tools/dotc/parsing", picklingOptions).pos - - @Test def tastyPrinting: Unit = - compileDir("../compiler/src/dotty/tools/dotc/printing", picklingOptions).pos - - @Test def tastyRepl: Unit = - compileDir("../compiler/src/dotty/tools/dotc/repl", picklingOptions).pos - - @Test def tastyRewrite: Unit = - compileDir("../compiler/src/dotty/tools/dotc/rewrite", picklingOptions).pos - - @Test def tastyTransform: Unit = - compileDir("../compiler/src/dotty/tools/dotc/transform", picklingOptions).pos - - @Test def tastyTyper: Unit = - compileDir("../compiler/src/dotty/tools/dotc/typer", picklingOptions).pos - - @Test def tastyUtil: Unit = - compileDir("../compiler/src/dotty/tools/dotc/util", picklingOptions).pos - - @Test def tastyIo: Unit = - compileDir("../compiler/src/dotty/tools/io", picklingOptions).pos - - @Test def tastyTests: Unit = - compileDir("../tests/tasty", picklingOptions).pos - + @Test def testPickling1: Unit = { + compileFilesInDir("../tests/new", picklingOptions) + + compileFilesInDir("../tests/pickling", picklingOptions) + + compileDir("../library/src/dotty/runtime", picklingOptions) + + compileDir("../compiler/src/dotty/tools/backend/jvm", picklingOptions) + + compileDir("../compiler/src/dotty/tools/dotc/ast", picklingOptions) + + compileDir("../compiler/src/dotty/tools/dotc/core", picklingOptions) + + compileDir("../compiler/src/dotty/tools/dotc/config", picklingOptions) + + compileDir("../compiler/src/dotty/tools/dotc/parsing", picklingOptions) + + compileDir("../compiler/src/dotty/tools/dotc/printing", picklingOptions) + + compileDir("../compiler/src/dotty/tools/dotc/repl", picklingOptions) + + compileDir("../compiler/src/dotty/tools/dotc/rewrite", picklingOptions) + + compileDir("../compiler/src/dotty/tools/dotc/transform", picklingOptions) + + compileDir("../compiler/src/dotty/tools/dotc/typer", picklingOptions) + + compileDir("../compiler/src/dotty/tools/dotc/util", picklingOptions) + + compileDir("../compiler/src/dotty/tools/io", picklingOptions) + + compileFile("../tests/pos/pickleinf.scala", picklingOptions) + }.limitThreads(4).pos() + + @Test def testPickling2: Unit = { + compileDir("../compiler/src/dotty/tools/dotc/core/classfile", picklingOptions) + + compileDir("../compiler/src/dotty/tools/dotc/core/tasty", picklingOptions) + + compileDir("../compiler/src/dotty/tools/dotc/core/unpickleScala2", picklingOptions) + }.limitThreads(4).pos() + + @Test def testPickling3: Unit = { + compileDir("../compiler/src/dotty/tools", picklingOptions) + }.limitThreads(4).pos() + + @Test def testPickling4: Unit = { + compileDir("../compiler/src/dotty/tools/dotc", picklingOptions) + }.limitThreads(4).pos() + + /** The purpose of this test is two-fold, being able to compile dotty + * bootstrapped, and making sure that TASTY can link against a compiled + * version of Dotty + */ @Test def tastyBootstrap: Unit = { def dotty1 = compileDir("../compiler/src/dotty", allowDeepSubtypes.and("-Ycheck-reentrant", "-strict")) diff --git a/compiler/test/dotty/tools/dotc/ParallelTesting.scala b/compiler/test/dotty/tools/dotc/ParallelTesting.scala index 62bd9fb7b..cdafed36f 100644 --- a/compiler/test/dotty/tools/dotc/ParallelTesting.scala +++ b/compiler/test/dotty/tools/dotc/ParallelTesting.scala @@ -14,15 +14,54 @@ import java.nio.file.StandardCopyOption.REPLACE_EXISTING import java.nio.file.{ Files, Path, Paths, NoSuchFileException } import java.util.concurrent.{ Executors => JExecutors, TimeUnit } import scala.util.control.NonFatal +import scala.util.Try import java.util.HashMap trait ParallelTesting { - private case class Target(files: Array[JFile], outDir: JFile) { + private sealed trait Target { self => + def outDir: JFile + def flags: Array[String] + + def withFlags(newFlags: Array[String]) = self match { + case self: ConcurrentCompilationTarget => + self.copy(flags = newFlags) + case self: SeparateCompilationTarget => + self.copy(flags = newFlags) + } + } + private final case class ConcurrentCompilationTarget( + files: Array[JFile], + flags: Array[String], + outDir: JFile + ) extends Target { override def toString() = outDir.toString } + private final case class SeparateCompilationTarget( + dir: JFile, + flags: Array[String], + outDir: JFile + ) extends Target { + + def compilationUnits: List[Array[JFile]] = + dir + .listFiles + .groupBy { file => + val name = file.getName + Try { + val potentialNumber = name + .substring(0, name.lastIndexOf('.')) + .reverse.takeWhile(_ != '_').reverse + + potentialNumber.toInt.toString + } + .toOption + .getOrElse("") + } + .toList.sortBy(_._1).map(_._2.filter(isCompilable)) + } - private abstract class CompileRun(targets: List[Target], fromDir: String, flags: Array[String], times: Int) { + private abstract class CompileRun(targets: List[Target], times: Int, threadLimit: Option[Int]) { val totalTargets = targets.length private[this] var _errors = 0 @@ -51,20 +90,20 @@ trait ParallelTesting { "[" + ("=" * (math.max(progress - 1, 0))) + (if (progress > 0) ">" else "") + (" " * (39 - progress)) + - s"] compiling ($tCompiled/$totalTargets, ${timestamp}s) in '$fromDir'\r" + s"] compiling ($tCompiled/$totalTargets, ${timestamp}s)\r" ) - Thread.sleep(50) + Thread.sleep(100) tCompiled = targetsCompiled } // println, otherwise no newline and cursor at start of line println( s"[=======================================] compiled ($totalTargets/$totalTargets, " + - s"${(System.currentTimeMillis - start) / 1000}s) in '$fromDir' errors: $errors" + s"${(System.currentTimeMillis - start) / 1000}s) " ) } } - protected def compileTry(op: => Unit) = + protected def compileTry(op: => Unit): Unit = try op catch { case NonFatal(e) => { // if an exception is thrown during compilation, the complete test @@ -80,7 +119,11 @@ trait ParallelTesting { private[ParallelTesting] def execute(): this.type = { assert(_targetsCompiled == 0, "not allowed to re-use a `CompileRun`") - val pool = JExecutors.newWorkStealingPool() + val pool = threadLimit match { + case Some(i) => JExecutors.newWorkStealingPool(i) + case None => JExecutors.newWorkStealingPool() + } + pool.submit(statusRunner) targets.foreach { target => @@ -93,19 +136,35 @@ trait ParallelTesting { } } - private final class PosCompileRun(targets: List[Target], fromDir: String, flags: Array[String], times: Int) - extends CompileRun(targets, fromDir, flags, times) { + @inline private final def isCompilable(f: JFile): Boolean = { + val name = f.getName + name.endsWith(".scala") || name.endsWith(".java") + } + + private final class PosCompileRun(targets: List[Target], times: Int, threadLimit: Option[Int]) + extends CompileRun(targets, times, threadLimit) { protected def compilationRunnable(target: Target): Runnable = new Runnable { def run(): Unit = compileTry { - val sourceFiles = target.files.filter(f => f.getName.endsWith(".scala") || f.getName.endsWith(".java")) - val reporter = compile(sourceFiles, flags, false, times, target.outDir) - completeCompilation(reporter.errorCount) + target match { + case ConcurrentCompilationTarget(files, flags, outDir) => { + val sourceFiles = files.filter(isCompilable) + val reporter = compile(sourceFiles, flags, false, times, outDir) + completeCompilation(reporter.errorCount) + } + + case target @ SeparateCompilationTarget(dir, flags, outDir) => { + val compilationUnits = target.compilationUnits + val reporters = compilationUnits.map(files => compile(files.filter(isCompilable), flags, false, times, outDir)) + completeCompilation(reporters.foldLeft(0)(_ + _.errorCount)) + } + } + } } } - private final class RunCompileRun(targets: List[Target], fromDir: String, flags: Array[String], times: Int) - extends CompileRun(targets, fromDir, flags, times) { + private final class RunCompileRun(targets: List[Target], times: Int, threadLimit: Option[Int]) + extends CompileRun(targets, times, threadLimit) { private def verifyOutput(checkFile: JFile, dir: JFile) = try { // Do classloading magic and running here: import java.net.{ URL, URLClassLoader } @@ -150,13 +209,31 @@ trait ParallelTesting { protected def compilationRunnable(target: Target): Runnable = new Runnable { def run(): Unit = compileTry { - val sourceFiles = target.files.filter(f => f.getName.endsWith(".scala") || f.getName.endsWith(".java")) - val checkFile = target.files.find(_.getName.endsWith(".check")) - val reporter = compile(sourceFiles, flags, false, times, target.outDir) - completeCompilation(reporter.errorCount) + val (errorCount, hasCheckFile, doVerify) = target match { + case ConcurrentCompilationTarget(files, flags, outDir) => { + val sourceFiles = files.filter(isCompilable) + val checkFile = files.find(_.getName.endsWith(".check")) + val reporter = compile(sourceFiles, flags, false, times, outDir) + + completeCompilation(reporter.errorCount) + (reporter.errorCount, checkFile.isDefined, () => verifyOutput(checkFile.get, outDir)) + } + + case target @ SeparateCompilationTarget(dir, flags, outDir) => { + val checkFile = new JFile(dir.getAbsolutePath.reverse.dropWhile(_ == '/').reverse + ".check") + val errorCount = + target + .compilationUnits + .map(files => compile(files.filter(isCompilable), flags, false, times, outDir)) + .foldLeft(0)(_ + _.errorCount) + + completeCompilation(errorCount) + (errorCount, checkFile.exists, () => verifyOutput(checkFile, outDir)) + } + } - if (reporter.errorCount == 0 && checkFile.isDefined) verifyOutput(checkFile.get, target.outDir) - else if (reporter.errorCount > 0) { + if (errorCount == 0 && hasCheckFile) doVerify() + else if (errorCount > 0) { System.err.println(s"\nCompilation failed for: '$target'") fail() } @@ -164,41 +241,40 @@ trait ParallelTesting { } } - private final class NegCompileRun(targets: List[Target], fromDir: String, flags: Array[String], times: Int) - extends CompileRun(targets, fromDir, flags, times) { + private final class NegCompileRun(targets: List[Target], times: Int, threadLimit: Option[Int]) + extends CompileRun(targets, times, threadLimit) { protected def compilationRunnable(target: Target): Runnable = new Runnable { def run(): Unit = compileTry { - val sourceFiles = target.files.filter(f => f.getName.endsWith(".scala") || f.getName.endsWith(".java")) - // In neg-tests we allow two types of error annotations, // "nopos-error" which doesn't care about position and "error" which // has to be annotated on the correct line number. // // We collect these in a map `"file:row" -> numberOfErrors`, for // nopos errors we save them in `"file" -> numberOfNoPosErrors` - val errorMap = new HashMap[String, Integer]() - var expectedErrors = 0 - target.files.filter(_.getName.endsWith(".scala")).foreach { file => - Source.fromFile(file).getLines.zipWithIndex.foreach { case (line, lineNbr) => - val errors = line.sliding("// error".length).count(_.mkString == "// error") - if (errors > 0) - errorMap.put(s"${file.getAbsolutePath}:${lineNbr}", errors) - - val noposErrors = line.sliding("// nopos-error".length).count(_.mkString == "// nopos-error") - if (noposErrors > 0) { - val nopos = errorMap.get("nopos") - val existing: Integer = if (nopos eq null) 0 else nopos - errorMap.put("nopos", noposErrors + existing) + def errorMapAndExpected(files: Array[JFile]): (HashMap[String, Integer], Int) = { + val errorMap = new HashMap[String, Integer]() + var expectedErrors = 0 + files.filter(_.getName.endsWith(".scala")).foreach { file => + Source.fromFile(file).getLines.zipWithIndex.foreach { case (line, lineNbr) => + val errors = line.sliding("// error".length).count(_.mkString == "// error") + if (errors > 0) + errorMap.put(s"${file.getAbsolutePath}:${lineNbr}", errors) + + val noposErrors = line.sliding("// nopos-error".length).count(_.mkString == "// nopos-error") + if (noposErrors > 0) { + val nopos = errorMap.get("nopos") + val existing: Integer = if (nopos eq null) 0 else nopos + errorMap.put("nopos", noposErrors + existing) + } + + expectedErrors += noposErrors + errors } - - expectedErrors += noposErrors + errors } - } - val reporter = compile(sourceFiles, flags, true, times, target.outDir) - val actualErrors = reporter.errorCount + (errorMap, expectedErrors) + } - def missingAnnotations = !reporter.errors.forall { error => + def getMissingAnnotations(errorMap: HashMap[String, Integer], reporterErrors: List[MessageContainer]) = !reporterErrors.forall { error => val getter = if (error.pos.exists) { val fileName = error.pos.source.file.toString s"$fileName:${error.pos.line}" @@ -220,13 +296,33 @@ trait ParallelTesting { } } + val (expectedErrors, actualErrors, hasMissingAnnotations, errorMap) = target match { + case ConcurrentCompilationTarget(files, flags, outDir) => { + val sourceFiles = files.filter(isCompilable) + val (errorMap, expectedErrors) = errorMapAndExpected(sourceFiles) + val reporter = compile(sourceFiles, flags, true, times, outDir) + val actualErrors = reporter.errorCount + + (expectedErrors, actualErrors, () => getMissingAnnotations(errorMap, reporter.errors), errorMap) + } + + case target @ SeparateCompilationTarget(dir, flags, outDir) => { + val compilationUnits = target.compilationUnits + val (errorMap, expectedErrors) = errorMapAndExpected(compilationUnits.toArray.flatten) + val reporters = compilationUnits.map(files => compile(files.filter(isCompilable), flags, true, times, outDir)) + val actualErrors = reporters.foldLeft(0)(_ + _.errorCount) + val errors = reporters.flatMap(_.errors) + (expectedErrors, actualErrors, () => getMissingAnnotations(errorMap, errors), errorMap) + } + } + if (expectedErrors != actualErrors) { System.err.println { s"\nWrong number of errors encountered when compiling $target, expected: $expectedErrors, actual: $actualErrors\n" } fail() } - else if (missingAnnotations) { + else if (hasMissingAnnotations()) { System.err.println { s"\nErrors found on incorrect row numbers when compiling $target" } @@ -289,6 +385,11 @@ trait ParallelTesting { } } + def addOutDir(xs: Array[String]): Array[String] = { + val (beforeCp, cp :: cpArg :: rest) = xs.toList.span(_ != "-classpath") + (beforeCp ++ (cp :: (cpArg + s":${targetDir.getAbsolutePath}") :: rest)).toArray + } + def compileWithJavac(fs: Array[String]) = if (fs.nonEmpty) { val scalaLib = findJarFromRuntime("scala-library") val fullArgs = Array( @@ -326,7 +427,7 @@ trait ParallelTesting { } } - driver.process(flags ++ files.map(_.getAbsolutePath), reporter = reporter) + driver.process(addOutDir(flags) ++ files.map(_.getAbsolutePath), reporter = reporter) // If the java files failed compilation before, we try again after: if (!javaCompiledBefore) @@ -336,52 +437,62 @@ trait ParallelTesting { else reporter } - class CompilationTest private ( - targets: List[Target], - fromDir: String, - flags: Array[String], - times: Int, - shouldDelete: Boolean + final class CompilationTest private ( + private[ParallelTesting] val targets: List[Target], + private[ParallelTesting] val times: Int, + private[ParallelTesting] val shouldDelete: Boolean, + private[ParallelTesting] val threadLimit: Option[Int] ) { - private[ParallelTesting] def this(target: Target, fromDir: String, flags: Array[String]) = - this(List(target), fromDir, flags, 1, true) + private[ParallelTesting] def this(target: Target) = + this(List(target), 1, true, None) - private[ParallelTesting] def this(targets: List[Target], fromDir: String, flags: Array[String]) = - this(targets, fromDir, flags, 1, true) + private[ParallelTesting] def this(targets: List[Target]) = + this(targets, 1, true, None) + + def +(other: CompilationTest) = { + require(other.times == times, "can't combine tests that are meant to be benchmark compiled") + require(other.shouldDelete == shouldDelete, "can't combine tests that differ on deleting output") + new CompilationTest(targets ++ other.targets, times, shouldDelete, threadLimit) + } - def pos: this.type = { - val run = new PosCompileRun(targets, fromDir, flags, times).execute() - assert(run.errors == 0, s"Expected no errors when compiling $fromDir") + def pos(): this.type = { + val runErrors = new PosCompileRun(targets, times, threadLimit).execute().errors + assert(runErrors == 0, s"Expected no errors when compiling") if (shouldDelete) targets.foreach(t => delete(t.outDir)) this } - def neg: this.type = { + def neg(): this.type = { assert( - !(new NegCompileRun(targets, fromDir, flags, times).execute().didFail), - s"Wrong number of errors encountered when compiling $fromDir" + !(new NegCompileRun(targets, times, threadLimit).execute().didFail), + s"Wrong number of errors encountered when compiling" ) if (shouldDelete) targets.foreach(t => delete(t.outDir)) this } - def run: this.type = { - assert( - !(new RunCompileRun(targets, fromDir, flags, times).execute().didFail), - s"Run tests failed for test $fromDir" - ) + def run(): this.type = { + val didFail = new RunCompileRun(targets, times, threadLimit).execute().didFail + assert(!didFail, s"Run tests failed") if (shouldDelete) targets.foreach(t => delete(t.outDir)) this } def times(i: Int): CompilationTest = - new CompilationTest(targets, fromDir, flags, i, shouldDelete) + new CompilationTest(targets, i, shouldDelete, threadLimit) - def verbose: CompilationTest = - new CompilationTest(targets, fromDir, flags ++ Array("-verbose", "-Ylog-classpath"), times, shouldDelete) + def verbose: CompilationTest = new CompilationTest( + targets.map(t => t.withFlags(t.flags ++ Array("-verbose", "-Ylog-classpath"))), + times, + shouldDelete, + threadLimit + ) def keepOutput: CompilationTest = - new CompilationTest(targets, fromDir, flags, times, false) + new CompilationTest(targets, times, false, threadLimit) + + def limitThreads(i: Int) = + new CompilationTest(targets, times, shouldDelete, Some(i)) def delete(): Unit = targets.foreach(t => delete(t.outDir)) @@ -441,8 +552,12 @@ trait ParallelTesting { s"Source file: $f, didn't exist" ) - val target = Target(Array(sourceFile), toCompilerDirFromFile(sourceFile, parent, outDir)) - new CompilationTest(target, f, flags) + val target = ConcurrentCompilationTarget( + Array(sourceFile), + flags, + toCompilerDirFromFile(sourceFile, parent, outDir) + ) + new CompilationTest(target) } def compileDir(f: String, flags: Array[String])(implicit outDirectory: String): CompilationTest = { @@ -461,8 +576,8 @@ trait ParallelTesting { val targetDir = new JFile(outDir) targetDir.mkdirs() - val target = Target(flatten(sourceDir), targetDir) - new CompilationTest(target, f, flags) + val target = ConcurrentCompilationTarget(flatten(sourceDir), flags, targetDir) + new CompilationTest(target) } def compileList(files: List[String], flags: Array[String])(implicit outDirectory: String): CompilationTest = { @@ -476,10 +591,10 @@ trait ParallelTesting { targetDir.mkdirs() assert(targetDir.exists, s"couldn't create target directory: $targetDir") - val target = Target(files.map(new JFile(_)).toArray, targetDir) + val target = ConcurrentCompilationTarget(files.map(new JFile(_)).toArray, flags, targetDir) // Create a CompilationTest and let the user decide whether to execute a pos or a neg test - new CompilationTest(target, outDir.toString, flags) + new CompilationTest(target) } def compileFilesInDir(f: String, flags: Array[String])(implicit outDirectory: String): CompilationTest = { @@ -493,11 +608,11 @@ trait ParallelTesting { val (dirs, files) = compilationTargets(sourceDir) val targets = - files.map(f => Target(Array(f), toCompilerDirFromFile(f, sourceDir, outDir))) ++ - dirs.map(dir => Target(dir.listFiles, toCompilerDirFromDir(dir, sourceDir, outDir))) + files.map(f => ConcurrentCompilationTarget(Array(f), flags, toCompilerDirFromFile(f, sourceDir, outDir))) ++ + dirs.map(dir => SeparateCompilationTarget(dir, flags, toCompilerDirFromDir(dir, sourceDir, outDir))) // Create a CompilationTest and let the user decide whether to execute a pos or a neg test - new CompilationTest(targets, f, flags) + new CompilationTest(targets) } def compileShallowFilesInDir(f: String, flags: Array[String])(implicit outDirectory: String): CompilationTest = { @@ -511,10 +626,10 @@ trait ParallelTesting { val (_, files) = compilationTargets(sourceDir) val targets = files.map { file => - Target(Array(file), toCompilerDirFromFile(file, sourceDir, outDir)) + ConcurrentCompilationTarget(Array(file), flags, toCompilerDirFromFile(file, sourceDir, outDir)) } // Create a CompilationTest and let the user decide whether to execute a pos or a neg test - new CompilationTest(targets, f, flags) + new CompilationTest(targets) } } -- cgit v1.2.3