Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
17 changes: 16 additions & 1 deletion compiler/test/dotty/tools/TestSources.scala
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@ import dotty.Properties

object TestSources {

private val isWorkingDirectoryInsideCompiler = Paths.get(".").toAbsolutePath.normalize.endsWith("compiler")

def rootPath(): Path =
if isWorkingDirectoryInsideCompiler
then Paths.get("..")
else Paths.get(".")

def getPath(relative: String): Path =
if isWorkingDirectoryInsideCompiler
then Paths.get("..", relative)
// important to not do `get(".", relative)` (or equivalently `rootPath().resolve(relative)`),
// the rest of the testing framework depends on exact paths,
// so "error in ./x.scala" and "error in x.scala" aren't considered equivalent.
else Paths.get(relative)

// pos tests lists

def posFromTastyExcludelistFile: String = "compiler/test/dotc/pos-from-tasty.excludelist"
Expand Down Expand Up @@ -85,7 +100,7 @@ object TestSources {
// load lists

private def loadList(path: String): List[String] = {
val list = Files.readAllLines(Paths.get(path))
val list = Files.readAllLines(getPath(path))
.iterator()
.asScala
.map(_.trim) // allow indentation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ class BootstrappedOnlyCompilationTests {
// 1. hack with absolute path for -Xplugin
// 2. copy `pluginFile` to destination
def compileFilesInDir(dir: String, run: Boolean = false): CompilationTest = {
val outDir = defaultOutputDir + "testPlugins/"
val outDir = new java.io.File(defaultOutputDir, "testPlugins")
val sourceDir = new java.io.File(dir)

val dirs = sourceDir.listFiles.toList.filter(_.isDirectory)
Expand Down
53 changes: 22 additions & 31 deletions compiler/test/dotty/tools/dotc/CompilationTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,26 @@ package dotc

import scala.language.unsafeNulls

import org.junit.{ Test, BeforeClass, AfterClass, Ignore }
import org.junit.Assert._
import org.junit.Assume._
import org.junit.experimental.categories.Category

import java.io.File
import java.nio.file._
import java.util.stream.{ Stream => JStream }
import scala.jdk.CollectionConverters._
import scala.util.matching.Regex
import scala.concurrent.duration._
import TestSources.sources
import TestSources.scoverageIgnoreExcludelisted
import reporting.TestReporter
import vulpix._
import dotty.tools.dotc.config.ScalaSettings
import dotty.tools.dotc.coverage.Serializer
import org.junit.{ Test, AfterClass }
import org.junit.Assume.*

import java.nio.file.*
import scala.concurrent.duration.*

import dotty.tools.dotc.reporting.TestReporter
import dotty.tools.vulpix.*

class CompilationTests {
import ParallelTesting._
import TestConfiguration._
import CompilationTests._
import ParallelTesting.*
import TestConfiguration.*
import CompilationTests.*
import CompilationTest.aggregateTests

// Positive tests ------------------------------------------------------------

@Test def pos: Unit = {
implicit val testGroup: TestGroup = TestGroup("compilePos")
var tests = List(
val tests = List(
compileFilesInDir("tests/pos", defaultOptions.and("-Wsafe-init", "-Wunused:all", "-Wshadow:private-shadow", "-Wshadow:type-parameter-shadow"), FileFilter.include(TestSources.posLintingAllowlist)),
compileFilesInDir("tests/pos", defaultOptions.and("-Wsafe-init"), FileFilter.exclude(TestSources.posLintingAllowlist)),
compileFilesInDir("tests/pos-deep-subtype", allowDeepSubtypes),
Expand Down Expand Up @@ -279,7 +270,7 @@ class CompilationTests {
locally {
val group = TestGroup("checkInitGlobal/tastySource")
val tastSourceOptions = defaultOptions.and("-Ysafe-init-global")
val outDirLib = defaultOutputDir + group + "/A/tastySource/A"
val outDirLib = Paths.get(defaultOutputDir.getAbsolutePath, group.name,"A", "tastySource", "A").toString

// Set -sourceroot such that the source code cannot be found by the compiler
val libOptions = tastSourceOptions.and("-sourceroot", "tests/init-global/special")
Expand Down Expand Up @@ -311,8 +302,8 @@ class CompilationTests {
locally {
val i12128Group = TestGroup("checkInit/i12128")
val i12128Options = options.without("-Werror")
val outDir1 = defaultOutputDir + i12128Group + "/Reflect_1/i12128/Reflect_1"
val outDir2 = defaultOutputDir + i12128Group + "/Macro_2/i12128/Macro_2"
val outDir1 = Paths.get(defaultOutputDir.getAbsolutePath, i12128Group.name, "Reflect_1", "i12128", "Reflect_1").toString
val outDir2 = Paths.get(defaultOutputDir.getAbsolutePath, i12128Group.name, "Macro_2", "i12128", "Macro_2").toString

val tests = List(
withCoverage(compileFile("tests/init/special/i12128/Reflect_1.scala", i12128Options)(using i12128Group).keepOutput),
Expand All @@ -331,9 +322,9 @@ class CompilationTests {
val tastyErrorGroup = TestGroup("checkInit/tasty-error/val-or-defdef")
val tastyErrorOptions = options.without("-Werror")

val classA0 = defaultOutputDir + tastyErrorGroup + "/A/v0/A"
val classA1 = defaultOutputDir + tastyErrorGroup + "/A/v1/A"
val classB1 = defaultOutputDir + tastyErrorGroup + "/B/v1/B"
val classA0 = Paths.get(defaultOutputDir.getAbsolutePath, tastyErrorGroup.name, "A", "v0", "A").toString
val classA1 = Paths.get(defaultOutputDir.getAbsolutePath, tastyErrorGroup.name, "A", "v1", "A").toString
val classB1 = Paths.get(defaultOutputDir.getAbsolutePath, tastyErrorGroup.name, "B", "v1", "B").toString

val tests = List(
withCoverage(compileFile("tests/init/tasty-error/val-or-defdef/v1/A.scala", tastyErrorOptions)(using tastyErrorGroup).keepOutput),
Expand All @@ -355,10 +346,10 @@ class CompilationTests {
val tastyErrorGroup = TestGroup("checkInit/tasty-error/typedef")
val tastyErrorOptions = options.without("-Werror").without("-Ycheck:all")

val classC = defaultOutputDir + tastyErrorGroup + "/C/typedef/C"
val classA0 = defaultOutputDir + tastyErrorGroup + "/A/v0/A"
val classA1 = defaultOutputDir + tastyErrorGroup + "/A/v1/A"
val classB1 = defaultOutputDir + tastyErrorGroup + "/B/v1/B"
val classC = Paths.get(defaultOutputDir.getAbsolutePath, tastyErrorGroup.name, "C", "typedef", "C").toString
val classA0 = Paths.get(defaultOutputDir.getAbsolutePath, tastyErrorGroup.name, "A", "v0", "A").toString
val classA1 = Paths.get(defaultOutputDir.getAbsolutePath, tastyErrorGroup.name, "A", "v1", "A").toString
val classB1 = Paths.get(defaultOutputDir.getAbsolutePath, tastyErrorGroup.name, "B", "v1", "B").toString

val tests = List(
withCoverage(compileFile("tests/init/tasty-error/typedef/C.scala", tastyErrorOptions)(using tastyErrorGroup).keepOutput),
Expand Down
20 changes: 15 additions & 5 deletions compiler/test/dotty/tools/dotc/Playground.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
package dotty.tools.dotc

import dotty.tools.vulpix._
import dotty.tools.vulpix.*
import org.junit.Test
import org.junit.Ignore

// For ease of debugging individual tests
@Ignore class Playground:
import TestConfiguration._
import CompilationTests._
import TestConfiguration.*
import CompilationTests.*
import CompilationTest.aggregateTests

@Test def example: Unit =
implicit val testGroup: TestGroup = TestGroup("playground")
compileFile("tests/playground/example.scala", defaultOptions).checkCompile()
implicit val testGroup: TestGroup = TestGroup("single-test")
// can add, e.g., .and("-some-option")
val options = defaultOptions
// can also use `compileDir` (single test as a dir), `compileFilesInDir` (all tests within a dir)
val test = compileFile("tests/pos/tuple-filter.scala", options)
// or `RunTestWithCoverage` for "run" tests with output, or `WarnTestWithCoverage` for "warn" tests with warnings
type TestKind = PosTestWithCoverage
val compilationTest = withCoverage(aggregateTests(test))
runWithCoverageOrFallback[TestKind](compilationTest, testGroup.name)

8 changes: 4 additions & 4 deletions compiler/test/dotty/tools/dotc/TastyBootstrapTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,16 @@ class TastyBootstrapTests {
val dotty2Group = TestGroup("tastyBootstrap/dotty2")

// Make sure that the directory is clean
dotty.tools.io.Directory(defaultOutputDir + "tastyBootstrap").deleteRecursively()
dotty.tools.io.Directory(new java.io.File(defaultOutputDir, "tastyBootstrap").getAbsolutePath).deleteRecursively()

val opt = TestFlags(
List(
// compile with bootstrapped library on cp:
defaultOutputDir + libGroup + "/lib/",
Paths.get(defaultOutputDir.getAbsolutePath, libGroup.name, "lib").toString,
// and bootstrapped tasty-core:
defaultOutputDir + tastyCoreGroup + "/tastyCore/",
Paths.get(defaultOutputDir.getAbsolutePath, tastyCoreGroup.name, "tastyCore").toString,
// as well as bootstrapped compiler:
defaultOutputDir + dotty1Group + "/dotty1/",
Paths.get(defaultOutputDir.getAbsolutePath, dotty1Group.name, "dotty1").toString,
// and the other compiler dependencies:
Properties.compilerInterface, Properties.scalaLibrary, Properties.scalaAsm,
Properties.dottyInterfaces, Properties.jlineTerminal, Properties.jlineReader,
Expand Down
2 changes: 0 additions & 2 deletions compiler/test/dotty/tools/dotc/coverage/CoverageTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ import org.junit.experimental.categories.Category
import dotty.{BootstrappedOnlyTests, Properties}
import dotty.tools.vulpix.*
import dotty.tools.vulpix.TestConfiguration.*
import dotty.tools.dotc.Main
import dotty.tools.dotc.reporting.TestReporter

import java.nio.file.{FileSystems, Files, Path, Paths, StandardCopyOption}
import scala.jdk.CollectionConverters.*
import scala.util.Properties.userDir
import scala.language.unsafeNulls
import scala.collection.mutable.Buffer
import dotty.tools.dotc.util.DiffUtil

import java.nio.charset.StandardCharsets
import java.util.stream.Collectors
Expand Down
6 changes: 3 additions & 3 deletions compiler/test/dotty/tools/dotc/printing/PrintingTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ import java.io.File
class PrintingTest {

def options(phase: String, flags: List[String]) =
val outDir = ParallelTesting.defaultOutputDir + "printing" + File.pathSeparator
File(outDir).mkdirs()
List(s"-Vprint:$phase", "-color:never", "-nowarn", "-d", outDir, "-classpath", TestConfiguration.basicClasspath) ::: flags
val outDir = new File(ParallelTesting.defaultOutputDir, "printing")
outDir.mkdirs()
List(s"-Vprint:$phase", "-color:never", "-nowarn", "-d", outDir.getAbsolutePath, "-classpath", TestConfiguration.basicClasspath) ::: flags

private def compileFile(path: JPath, phase: String): Boolean = {
val baseFilePath = path.toString.stripSuffix(".scala").stripSuffix(".java")
Expand Down
53 changes: 27 additions & 26 deletions compiler/test/dotty/tools/vulpix/ParallelTesting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:

final override def toString: String = sourceFiles match {
case Array(f) => f.getPath
case _ => outDir.getPath.stripPrefix(defaultOutputDir).stripPrefix(name).stripPrefix("/")
case _ => outDir.getPath.stripPrefix(defaultOutputDirName).stripPrefix(name).stripPrefix("/")
}
}

Expand Down Expand Up @@ -507,11 +507,16 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
def scalacOptions = toolArgs.getOrElse(ToolName.Scalac, Nil)
def javacOptions = toolArgs.getOrElse(ToolName.Javac, Nil)

val flags = flags0
var flags = flags0
.and(scalacOptions*)
.and("-d", targetDir.getPath)
.withClasspath(targetDir.getPath)

// We must set -sourceroot for SemanticDB extraction to work properly inside an IDE,
// but we have many existing coverage tests that assume it is not set, so as a workaround:
if !flags.all.contains("-coverage-out") then
flags = flags.and("-sourceroot", TestSources.rootPath().toAbsolutePath.toString)

def compileWithJavac(fs: Array[String]) = if (fs.nonEmpty) {
val fullArgs = Array(
"-encoding", StandardCharsets.UTF_8.name,
Expand Down Expand Up @@ -1409,24 +1414,23 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
end CompilationTest

/** Create out directory for directory `d` */
def createOutputDirsForDir(d: JFile, sourceDir: JFile, outDir: String): JFile = {
val targetDir = new JFile(outDir + s"${sourceDir.getName}/${d.getName}")
def createOutputDirsForDir(d: JFile, sourceDir: JFile, outDir: JFile): JFile = {
val targetDir = new JFile(outDir, s"${sourceDir.getName}/${d.getName}")
targetDir.mkdirs()
targetDir
}

/** Create out directory for `file` */
private def createOutputDirsForFile(file: JFile, sourceDir: JFile, outDir: String): JFile = {
private def createOutputDirsForFile(file: JFile, sourceDir: JFile, outDir: JFile): JFile = {
val uniqueSubdir = file.getName.substring(0, file.getName.lastIndexOf('.'))
val targetDir = new JFile(outDir + s"${sourceDir.getName}${JFile.separatorChar}$uniqueSubdir")
val targetDir = new JFile(outDir, s"${sourceDir.getName}${JFile.separatorChar}$uniqueSubdir")
targetDir.mkdirs()
targetDir
}

/** Make sure that directory string is as expected */
private def checkRequirements(f: String, sourceDir: JFile, outDir: String): Unit = {
private def checkRequirements(f: String, sourceDir: JFile, outDir: JFile): Unit = {
require(sourceDir.isDirectory && sourceDir.exists, "passed non-directory to `compileFilesInDir`: " + sourceDir)
require(outDir.last == JFile.separatorChar, "please specify an `outDir` with a trailing file separator")
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

good example of an assertion that should never need to exist if you use the right data structures

}

/** Separates directories from files and returns them as `(dirs, files)` */
Expand All @@ -1440,11 +1444,10 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:

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

require(
sourceFile.exists && !sourceFile.isDirectory &&
Expand All @@ -1469,8 +1472,8 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
* can be used for randomization.
*/
def compileDir(f: String, flags: TestFlags, randomOrder: Option[Int] = None, recursive: Boolean = true)(using testGroup: TestGroup): CompilationTest = {
val outDir = defaultOutputDir + testGroup + JFile.separator
val sourceDir = new JFile(f)
val outDir = new JFile(defaultOutputDir, testGroup.name)
val sourceDir = TestSources.getPath(f).toFile
checkRequirements(f, sourceDir, outDir)

def flatten(f: JFile): Array[JFile] =
Expand All @@ -1488,7 +1491,7 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
}

// Directories in which to compile all containing files with `flags`:
val targetDir = new JFile(outDir + JFile.separator + sourceDir.getName + JFile.separator)
val targetDir = new JFile(outDir, sourceDir.getName)
targetDir.mkdirs()

val target = JointCompilationSource(s"compiling '$f' in test '$testGroup'", randomized, flags, targetDir)
Expand All @@ -1500,10 +1503,8 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
* dissociated
*/
def compileList(testName: String, files: List[String], flags: TestFlags)(implicit testGroup: TestGroup): CompilationTest = {
val outDir = defaultOutputDir + testGroup + JFile.separator + testName + JFile.separator

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

Expand Down Expand Up @@ -1531,8 +1532,8 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
* the same name as the directory (with the file extension `.check`)
*/
def compileFilesInDir(f: String, flags: TestFlags, fileFilter: FileFilter = FileFilter.NoFilter)(implicit testGroup: TestGroup): CompilationTest = {
val outDir = defaultOutputDir + testGroup + JFile.separator
val sourceDir = new JFile(f)
val outDir = new JFile(defaultOutputDir, testGroup.name)
val sourceDir = TestSources.getPath(f).toFile
checkRequirements(f, sourceDir, outDir)

val (dirs, files) = compilationTargets(sourceDir, fileFilter)
Expand Down Expand Up @@ -1571,9 +1572,8 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
* Tests in the first part of the tuple must be executed before the second.
* Both testsRequires explicit delete().
*/
def compileTastyInDir(f: String, flags0: TestFlags, fromTastyFilter: FileFilter)(
implicit testGroup: TestGroup): TastyCompilationTest = {
val outDir = defaultOutputDir + testGroup + JFile.separator
def compileTastyInDir(f: String, flags0: TestFlags, fromTastyFilter: FileFilter)(implicit testGroup: TestGroup): TastyCompilationTest = {
val outDir = new JFile(defaultOutputDir, testGroup.name)
val flags = flags0 `and` "-Yretain-trees"
val sourceDir = new JFile(f)
checkRequirements(f, sourceDir, outDir)
Expand Down Expand Up @@ -1636,7 +1636,7 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
val semanticDbFlag = "-Xsemanticdb"
assert(!flags.options.contains(bestEffortFlag), "Best effort compilation flag should not be added manually")

val outDir = defaultOutputDir + testGroup + JFile.separator
val outDir = new JFile(defaultOutputDir, testGroup.name)
val sourceDir = new JFile(f)
checkRequirements(f, sourceDir, outDir)

Expand Down Expand Up @@ -1739,7 +1739,7 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
val step1SourceFiles = step1SourceDir.listFiles
val step2SourceFiles = step2SourceDir.listFiles

val outDir = defaultOutputDir + testGroup + JFile.separator + dir.getName().toString + JFile.separator
val outDir = new JFile(new JFile(defaultOutputDir, testGroup.name), dir.getName)

val step1OutDir = createOutputDirsForDir(step1SourceDir, step1SourceDir, outDir)
val step2OutDir = createOutputDirsForDir(step2SourceDir, step2SourceDir, outDir)
Expand Down Expand Up @@ -1825,7 +1825,7 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:
* tests.
*/
def compileShallowFilesInDir(f: String, flags: TestFlags)(implicit testGroup: TestGroup): CompilationTest = {
val outDir = defaultOutputDir + testGroup + JFile.separator
val outDir = new JFile(defaultOutputDir, testGroup.name)
val sourceDir = new JFile(f)
checkRequirements(f, sourceDir, outDir)

Expand All @@ -1851,7 +1851,8 @@ trait ParallelTesting extends RunnerOrchestration with CoverageSupport:

object ParallelTesting:

def defaultOutputDir: String = "out"+JFile.separator
def defaultOutputDirName: String = "out" + JFile.separator
def defaultOutputDir: JFile = TestSources.getPath(defaultOutputDirName).toFile

def isSourceFile(f: JFile): Boolean = {
val name = f.getName
Expand Down
6 changes: 4 additions & 2 deletions tests/init-global/special/tastySource/B.check
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
|Reading mutable state of other static objects is forbidden as it breaks initialization-time irrelevance. Calling trace:
|├── object B: [ B.scala:1 ]
|│ ^
|├── (no source) [ tastySource/A.scala:2 ]
|├── (no source) [ tastySource/A.scala:4 ]
|├── def foo(fn: => Int) = bar(fn) [ A.scala:2 ]
|│ ^^^^^^^
|├── def bar(fn: => Int) = fn [ A.scala:4 ]
|│ ^^
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

idk which change caused this but it seems "better" now since we go from no source to a source, so I didn't look further

|├── var y = A.foo(bar) * 2 [ B.scala:2 ]
|│ ^^^
|└── def bar = C.n * 3 // warn [ B.scala:4 ]
Expand Down
Loading