Skip to content

Remove vulpix reflective nightmare #3445

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/test/dotc/comptest.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package dotc

import dotty.tools.vulpix.{ParallelTesting, TestFlags}
import dotty.tools.vulpix.{ParallelTesting, TestFlags, TestGroup}

import scala.concurrent.duration._

Expand All @@ -26,5 +26,5 @@ object comptest extends ParallelTesting {
),
TestFlags("", Array("-Ylog:frontend", "-Xprompt")),
outDirectory = "."
)
)(TestGroup("comptest"))
}
14 changes: 12 additions & 2 deletions compiler/test/dotty/tools/dotc/CompilationTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ class CompilationTests extends ParallelTesting {

// @Test // enable to test compileStdLib separately with detailed stats
def compileStdLib: Unit = {
implicit val testGroup: TestGroup = TestGroup("compileStdLib")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need to give an explicit type signature here because the implicit val is in a def.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want me to remove them? I added them to avoid warnings from the IDE.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your call.

compileList("compileStdLib", StdLibSources.whitelisted, scala2Mode.and("-migration", "-Yno-inline", "-Ydetailed-stats"))
}.checkCompile()

@Test def compilePos: Unit = {
implicit val testGroup: TestGroup = TestGroup("compilePos")
compileList("compileStdLib", StdLibSources.whitelisted, scala2Mode.and("-migration", "-Yno-inline")) +
compileDir("../compiler/src/dotty/tools/dotc/ast", defaultOptions) +
compileDir("../compiler/src/dotty/tools/dotc/config", defaultOptions) +
Expand Down Expand Up @@ -102,6 +104,7 @@ class CompilationTests extends ParallelTesting {
}.checkCompile()

@Test def posTwice: Unit = {
implicit val testGroup: TestGroup = TestGroup("posTwice")
compileFile("../tests/pos/Labels.scala", defaultOptions) +
compileFilesInDir("../tests/pos-java-interop", defaultOptions) +
compileFile("../tests/pos/t2168.scala", defaultOptions) +
Expand Down Expand Up @@ -160,6 +163,7 @@ class CompilationTests extends ParallelTesting {
// Negative tests ------------------------------------------------------------

@Test def compileNeg: Unit = {
implicit val testGroup: TestGroup = TestGroup("compileNeg")
compileShallowFilesInDir("../tests/neg", defaultOptions) +
compileShallowFilesInDir("../tests/neg/no-optimise", defaultOptions) +
compileFile("../tests/neg/customArgs/typers.scala", allowDoubleBindings) +
Expand Down Expand Up @@ -189,13 +193,15 @@ class CompilationTests extends ParallelTesting {
// Run tests -----------------------------------------------------------------

@Test def runAll: Unit = {
implicit val testGroup: TestGroup = TestGroup("runAll")
compileFilesInDir("../tests/run", defaultOptions) +
compileFilesInDir("../tests/run-no-optimise", defaultOptions)
}.checkRuns()

// Generic java signatures tests ---------------------------------------------

@Test def genericJavaSignatures: Unit = {
implicit val testGroup: TestGroup = TestGroup("genericJavaSignatures")
compileFilesInDir("../tests/generic-java-signatures", defaultOptions)
}.checkRuns()

Expand All @@ -205,6 +211,7 @@ class CompilationTests extends ParallelTesting {
// lower level of concurrency as to not kill their running VMs

@Test def testPickling: Unit = {
implicit val testGroup: TestGroup = TestGroup("testPickling")
compileDir("../compiler/src/dotty/tools", picklingOptions) +
compileDir("../compiler/src/dotty/tools/dotc", picklingOptions) +
compileFilesInDir("../tests/new", picklingOptions) +
Expand Down Expand Up @@ -233,6 +240,8 @@ class CompilationTests extends ParallelTesting {
* version of Dotty
*/
@Test def tastyBootstrap: Unit = {
implicit val testGroup: TestGroup = TestGroup("tastyBootstrap")

val opt = TestFlags(
// compile with bootstrapped library on cp:
defaultOutputDir + "lib/src/:" +
Expand Down Expand Up @@ -267,14 +276,14 @@ class CompilationTests extends ParallelTesting {
compileList(
"dotty",
compilerSources ++ backendSources ++ backendJvmSources,
opt)
opt)(TestGroup("dotty1"))
}

def dotty2 = {
compileList(
"dotty",
compilerSources ++ backendSources ++ backendJvmSources,
opt)
opt)(TestGroup("dotty2"))
}

val tests = {
Expand Down Expand Up @@ -305,6 +314,7 @@ class CompilationTests extends ParallelTesting {

@Category(Array(classOf[SlowTests]))
@Test def testOptimised: Unit = {
implicit val testGroup: TestGroup = TestGroup("testOptimised")
val outputDir = defaultOutputDir + "optimised/"
compileFilesInDir("../tests/pos", defaultOptimised, outputDir).checkCompile()
compileFilesInDir("../tests/run", defaultOptimised, outputDir).checkRuns()
Expand Down
15 changes: 7 additions & 8 deletions compiler/test/dotty/tools/dotc/IdempotencyTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import org.junit.{AfterClass, Test}
import org.junit.experimental.categories.Category

import scala.concurrent.duration._
import vulpix.{ParallelTesting, SummaryReport, SummaryReporting, TestConfiguration}
import vulpix._


class IdempotencyTests extends ParallelTesting {
Expand All @@ -27,7 +27,7 @@ class IdempotencyTests extends ParallelTesting {

@Category(Array(classOf[SlowTests]))
@Test def idempotency: Unit = {

implicit val testGroup: TestGroup = TestGroup("idempotency")
val opt = defaultOptions.and("-YemitTasty")

def sourcesFrom(dir: Path) = CompilationTests.sources(Files.walk(dir))
Expand All @@ -37,18 +37,17 @@ class IdempotencyTests extends ParallelTesting {
val strawmanSourcesRevSorted = strawmanSourcesSorted.reverse

val posIdempotency = {
def posIdempotency1 = compileFilesInDir("../tests/pos", opt)
def posIdempotency2 = compileFilesInDir("../tests/pos", opt)
posIdempotency1 + posIdempotency2
compileFilesInDir("../tests/pos", opt)(TestGroup("posIdempotency1")) +
compileFilesInDir("../tests/pos", opt)(TestGroup("posIdempotency2"))
}

val orderIdempotency = {
(for {
testDir <- new JFile("../tests/order-idempotency").listFiles() if testDir.isDirectory
} yield {
val sources = sourcesFrom(testDir.toPath)
def orderIdempotency1 = compileList(testDir.getName, sources, opt)
def orderIdempotency2 = compileList(testDir.getName, sources.reverse, opt)
def orderIdempotency1 = compileList(testDir.getName, sources, opt)(TestGroup("orderIdempotency1"))
def orderIdempotency2 = compileList(testDir.getName, sources.reverse, opt)(TestGroup("orderIdempotency2"))
orderIdempotency1 + orderIdempotency2
}).reduce(_ + _)
}
Expand All @@ -62,7 +61,7 @@ class IdempotencyTests extends ParallelTesting {

def check(name: String) = {
val files = List(s"../tests/idempotency/$name.scala", "../tests/idempotency/IdempotencyCheck.scala")
compileList(name, files, defaultOptions)
compileList(name, files, defaultOptions)(TestGroup("check"))
}
val allChecks = {
check("CheckOrderIdempotency") +
Expand Down
8 changes: 4 additions & 4 deletions compiler/test/dotty/tools/dotc/LinkOptimiseTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ class LinkOptimiseTests extends ParallelTesting {
@Test def linkOptimise: Unit = {
// Setup and compile libraries
def strawmanLibrary =
compileDir("../collection-strawman/collections/src/main", defaultOptions)
compileDir("../collection-strawman/collections/src/main", defaultOptions)(TestGroup("strawmanLibrary"))
def linkCustomLib =
compileDir("../tests/link/custom-lib", defaultOptions)
compileDir("../tests/link/custom-lib", defaultOptions)(TestGroup("linkCustomLib"))

val libraries = {
strawmanLibrary +
Expand All @@ -48,8 +48,8 @@ class LinkOptimiseTests extends ParallelTesting {
val linkDir = "../tests/link"
val linkStramanDir = linkDir + "/strawman"
val linkCustomLibDir = linkDir + "/on-custom-lib"
def linkStrawmanTest = compileFilesInDir(linkStramanDir, strawmanClassPath)
def linkCustomLibTest = compileFilesInDir(linkCustomLibDir, customLibClassFlags)
def linkStrawmanTest = compileFilesInDir(linkStramanDir, strawmanClassPath)(TestGroup("linkStrawmanTest"))
def linkCustomLibTest = compileFilesInDir(linkCustomLibDir, customLibClassFlags)(TestGroup("linkCustomLibTest"))

def classFileChecks(sourceDir: String, testName: String) = {
val checkExt = ".classcheck"
Expand Down
62 changes: 16 additions & 46 deletions compiler/test/dotty/tools/vulpix/ParallelTesting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1033,39 +1033,12 @@ trait ParallelTesting extends RunnerOrchestration { self =>
else (dirs, files)
}

/** Gets the name of the calling method via reflection.
*
* It does this in a way that needs to work both with the bootstrapped dotty
* and the non-bootstrapped version. Since the two compilers generate
* different bridges, we first need to filter out methods with the same name
* (bridges) - and then find the `@Test` method in our extending class
*/
private def getCallingMethod(): String = {
val seen = mutable.Set.empty[String]
Thread.currentThread.getStackTrace
.filter { elem =>
if (seen.contains(elem.getMethodName)) false
else { seen += elem.getMethodName; true }
}
.find { elem =>
val callingClass = Class.forName(elem.getClassName)
classOf[ParallelTesting].isAssignableFrom(callingClass) &&
elem.getFileName != "ParallelTesting.scala"
}
.map(_.getMethodName)
.getOrElse {
throw new IllegalStateException("Unable to reflectively find calling method")
}
.takeWhile(_ != '$')
}

/** Compiles a single file from the string path `f` using the supplied flags */
def compileFile(f: String, flags: TestFlags, outDirectory: String = defaultOutputDir): CompilationTest = {
val callingMethod = getCallingMethod()
def compileFile(f: String, flags: TestFlags, outDirectory: String = defaultOutputDir)(implicit testGroup: TestGroup): CompilationTest = {
val sourceFile = new JFile(f)
val parent = sourceFile.getParentFile
val outDir =
outDirectory + callingMethod + "/" +
outDirectory + testGroup.name + "/" +
sourceFile.getName.substring(0, sourceFile.getName.lastIndexOf('.')) + "/"

require(
Expand All @@ -1075,7 +1048,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
)

val target = JointCompilationSource(
callingMethod,
testGroup.name,
Array(sourceFile),
flags,
createOutputDirsForFile(sourceFile, parent, outDir)
Expand All @@ -1090,9 +1063,8 @@ trait ParallelTesting extends RunnerOrchestration { self =>
* By default, files are compiled in alphabetical order. An optional seed
* can be used for randomization.
*/
def compileDir(f: String, flags: TestFlags, randomOrder: Option[Int] = None, outDirectory: String = defaultOutputDir): CompilationTest = {
val callingMethod = getCallingMethod()
val outDir = outDirectory + callingMethod + "/"
def compileDir(f: String, flags: TestFlags, randomOrder: Option[Int] = None, outDirectory: String = defaultOutputDir)(implicit testGroup: TestGroup): CompilationTest = {
val outDir = outDirectory + testGroup.name + "/"
val sourceDir = new JFile(f)
checkRequirements(f, sourceDir, outDir)

Expand All @@ -1111,23 +1083,23 @@ trait ParallelTesting extends RunnerOrchestration { self =>
val targetDir = new JFile(outDir + "/" + sourceDir.getName + "/")
targetDir.mkdirs()

val target = JointCompilationSource(s"compiling '$f' in test '$callingMethod'", randomized, flags, targetDir)
val target = JointCompilationSource(s"compiling '$f' in test '${testGroup.name}'", randomized, flags, targetDir)
new CompilationTest(target)
}

/** Compiles all `files` together as a single compilation run. It is given a
* `testName` since files can be in separate directories and or be otherwise
* dissociated
*/
def compileList(testName: String, files: List[String], flags: TestFlags, callingMethod: String = getCallingMethod(), outDirectory: String = defaultOutputDir): CompilationTest = {
val outDir = outDirectory + callingMethod + "/" + testName + "/"
def compileList(testName: String, files: List[String], flags: TestFlags, outDirectory: String = defaultOutputDir)(implicit testGroup: TestGroup): CompilationTest = {
val outDir = outDirectory + testGroup.name + "/" + testName + "/"

// Directories in which to compile all containing files with `flags`:
val targetDir = new JFile(outDir)
targetDir.mkdirs()
assert(targetDir.exists, s"couldn't create target directory: $targetDir")

val target = JointCompilationSource(s"$testName from $callingMethod", files.map(new JFile(_)).toArray, flags, targetDir)
val target = JointCompilationSource(s"$testName from ${testGroup.name}", 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)
Expand All @@ -1150,17 +1122,16 @@ trait ParallelTesting extends RunnerOrchestration { self =>
* - Directories can have an associated check-file, where the check file has
* the same name as the directory (with the file extension `.check`)
*/
def compileFilesInDir(f: String, flags: TestFlags, outDirectory: String = defaultOutputDir): CompilationTest = {
val callingMethod = getCallingMethod()
val outDir = outDirectory + callingMethod + "/"
def compileFilesInDir(f: String, flags: TestFlags, outDirectory: String = defaultOutputDir)(implicit testGroup: TestGroup): CompilationTest = {
val outDir = outDirectory + testGroup.name + "/"
val sourceDir = new JFile(f)
checkRequirements(f, sourceDir, outDir)

val (dirs, files) = compilationTargets(sourceDir)

val targets =
files.map(f => JointCompilationSource(callingMethod, Array(f), flags, createOutputDirsForFile(f, sourceDir, outDir))) ++
dirs.map(dir => SeparateCompilationSource(callingMethod, dir, flags, createOutputDirsForDir(dir, sourceDir, outDir)))
files.map(f => JointCompilationSource(testGroup.name, Array(f), flags, createOutputDirsForFile(f, sourceDir, outDir))) ++
dirs.map(dir => SeparateCompilationSource(testGroup.name, dir, flags, createOutputDirsForDir(dir, sourceDir, outDir)))

// Create a CompilationTest and let the user decide whether to execute a pos or a neg test
new CompilationTest(targets)
Expand All @@ -1170,16 +1141,15 @@ trait ParallelTesting extends RunnerOrchestration { self =>
* sub-directories and as such, does **not** perform separate compilation
* tests.
*/
def compileShallowFilesInDir(f: String, flags: TestFlags, outDirectory: String = defaultOutputDir): CompilationTest = {
val callingMethod = getCallingMethod()
val outDir = outDirectory + callingMethod + "/"
def compileShallowFilesInDir(f: String, flags: TestFlags, outDirectory: String = defaultOutputDir)(implicit testGroup: TestGroup): CompilationTest = {
val outDir = outDirectory + testGroup.name + "/"
val sourceDir = new JFile(f)
checkRequirements(f, sourceDir, outDir)

val (_, files) = compilationTargets(sourceDir)

val targets = files.map { file =>
JointCompilationSource(callingMethod, Array(file), flags, createOutputDirsForFile(file, sourceDir, outDir))
JointCompilationSource(testGroup.name, Array(file), flags, createOutputDirsForFile(file, sourceDir, outDir))
}

// Create a CompilationTest and let the user decide whether to execute a pos or a neg test
Expand Down
3 changes: 3 additions & 0 deletions compiler/test/dotty/tools/vulpix/TestGroup.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package dotty.tools.vulpix

case class TestGroup(name: String) extends AnyVal
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please document what a TestGroup is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

2 changes: 2 additions & 0 deletions compiler/test/dotty/tools/vulpix/VulpixTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class VulpixTests extends ParallelTesting {

implicit val _: SummaryReporting = new NoSummaryReport

implicit def testGroup: TestGroup = TestGroup("VulpixTests")

def maxDuration = 3.seconds
def numberOfSlaves = 5
def safeMode = sys.env.get("SAFEMODE").isDefined
Expand Down