Skip to content

Commit

Permalink
Merge pull request #15543 from dotty-staging/sjs-vulpix-run-tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand authored Jul 4, 2022
2 parents 298ef15 + 3518226 commit 7d6d42f
Show file tree
Hide file tree
Showing 339 changed files with 920 additions and 224 deletions.
6 changes: 4 additions & 2 deletions compiler/test/dotty/tools/utils.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,16 @@ end assertThrows

/** Famous tool names in the ecosystem. Used for tool args in test files. */
enum ToolName:
case Scala, Scalac, Java, Javac, Test
case Scala, Scalac, Java, Javac, ScalaJS, Test
object ToolName:
def named(s: String): ToolName = values.find(_.toString.equalsIgnoreCase(s)).getOrElse(throw IllegalArgumentException(s))

type ToolArgs = Map[ToolName, List[String]]

/** Take a prefix of each file, extract tool args, parse, and combine.
* Arg parsing respects quotation marks. Result is a map from ToolName to the combined tokens.
*/
def toolArgsFor(files: List[JPath], charset: Charset = UTF_8): Map[ToolName, List[String]] =
def toolArgsFor(files: List[JPath], charset: Charset = UTF_8): ToolArgs =
files.foldLeft(Map.empty[ToolName, List[String]]) { (res, path) =>
val toolargs = toolArgsParse(resource(Files.lines(path, charset))(_.limit(10).toScala(List)))
toolargs.foldLeft(res) {
Expand Down
24 changes: 16 additions & 8 deletions compiler/test/dotty/tools/vulpix/ParallelTesting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ trait ParallelTesting extends RunnerOrchestration { self =>
self.copy(flags = flags.without(flags1: _*))
}

lazy val allToolArgs: ToolArgs =
toolArgsFor(sourceFiles.toList.map(_.toPath), getCharsetFromEncodingOpt(flags))

/** Generate the instructions to redo the test from the command line */
def buildInstructions(errors: Int, warnings: Int): String = {
val sb = new StringBuilder
Expand Down Expand Up @@ -199,6 +202,9 @@ trait ParallelTesting extends RunnerOrchestration { self =>
def sourceFiles = compilationGroups.map(_._2).flatten.toArray
}

protected def shouldSkipTestSource(testSource: TestSource): Boolean =
false

private trait CompilationLogic { this: Test =>
def suppressErrors = false

Expand Down Expand Up @@ -344,13 +350,15 @@ trait ParallelTesting extends RunnerOrchestration { self =>

/** All testSources left after filtering out */
private val filteredSources =
if (testFilter.isEmpty) testSources
else testSources.filter {
case JointCompilationSource(_, files, _, _, _, _) =>
testFilter.exists(filter => files.exists(file => file.getPath.contains(filter)))
case SeparateCompilationSource(_, dir, _, _) =>
testFilter.exists(dir.getPath.contains)
}
val filteredByName =
if (testFilter.isEmpty) testSources
else testSources.filter {
case JointCompilationSource(_, files, _, _, _, _) =>
testFilter.exists(filter => files.exists(file => file.getPath.contains(filter)))
case SeparateCompilationSource(_, dir, _, _) =>
testFilter.exists(dir.getPath.contains)
}
filteredByName.filterNot(shouldSkipTestSource(_))

/** Total amount of test sources being compiled by this test */
val sourceCount = filteredSources.length
Expand Down Expand Up @@ -739,7 +747,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>

private def verifyOutput(checkFile: Option[JFile], dir: JFile, testSource: TestSource, warnings: Int, reporters: Seq[TestReporter], logger: LoggedRunnable) = {
if (Properties.testsNoRun) addNoRunWarning()
else runMain(testSource.runClassPath) match {
else runMain(testSource.runClassPath, testSource.allToolArgs) match {
case Success(output) => checkFile match {
case Some(file) if file.exists => diffTest(testSource, file, output.linesIterator.toList, reporters, logger)
case _ =>
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/vulpix/RunnerOrchestration.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ trait RunnerOrchestration {
def safeMode: Boolean

/** Running a `Test` class's main method from the specified `dir` */
def runMain(classPath: String)(implicit summaryReport: SummaryReporting): Status =
def runMain(classPath: String, toolArgs: ToolArgs)(implicit summaryReport: SummaryReporting): Status =
monitor.runMain(classPath)

/** Kill all processes */
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/vulpix/TestConfiguration.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ object TestConfiguration {
lazy val withTastyInspectorOptions =
defaultOptions.withClasspath(withTastyInspectorClasspath).withRunClasspath(withTastyInspectorClasspath)
lazy val scalaJSOptions =
defaultOptions.and("-scalajs").withClasspath(scalaJSClasspath)
defaultOptions.and("-scalajs").withClasspath(scalaJSClasspath).withRunClasspath(scalaJSClasspath)
val allowDeepSubtypes = defaultOptions without "-Yno-deep-subtypes"
val allowDoubleBindings = defaultOptions without "-Yno-double-bindings"
val picklingOptions = defaultOptions and (
Expand Down
5 changes: 5 additions & 0 deletions project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1229,6 +1229,11 @@ object Build {
settings(
commonNonBootstrappedSettings,

libraryDependencies ++= Seq(
"org.scala-js" %% "scalajs-linker" % scalaJSVersion % Test cross CrossVersion.for3Use2_13,
"org.scala-js" %% "scalajs-env-nodejs" % "1.3.0" % Test cross CrossVersion.for3Use2_13,
),

// Change the baseDirectory when running the tests
Test / baseDirectory := baseDirectory.value.getParentFile,

Expand Down
70 changes: 70 additions & 0 deletions sjs-compiler-tests/test/scala/dotty/tools/dotc/JSRun.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package dotty.tools.dotc

import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext}

import java.io.InputStream
import java.nio.charset.StandardCharsets
import java.nio.file.Path

import dotty.tools.vulpix.*

import org.scalajs.jsenv.*
import org.scalajs.jsenv.nodejs.NodeJSEnv
import org.scalajs.logging.*

object JSRun:
def runJSCode(sjsCode: Path)(using ExecutionContext): Status =
val logger = new ScalaConsoleLogger(Level.Warn)

var stdoutStream: Option[InputStream] = None
var stderrStream: Option[InputStream] = None

val input = Input.Script(sjsCode) :: Nil
val config = RunConfig()
.withLogger(logger)
.withInheritOut(false)
.withInheritErr(false)
.withOnOutputStream { (out, err) =>
stdoutStream = out
stderrStream = err
}

val run = new NodeJSEnv().start(input, config)
try
val success = try {
Await.result(run.future, Duration.Inf)
true
} catch {
case _: Exception =>
false
}
val output = readStreamFully(stderrStream) + readStreamFully(stdoutStream)
if success then
Success(output)
else
Failure(output)
finally
run.close()
end runJSCode

private def readStreamFully(optStream: Option[InputStream]): String =
optStream match
case None =>
""
case Some(stream) =>
try
val result = new java.io.ByteArrayOutputStream()
val buffer = new Array[Byte](1024)
while ({
val len = stream.read(buffer)
len >= 0 && {
result.write(buffer, 0, len)
true
}
}) ()
new String(result.toByteArray(), StandardCharsets.UTF_8)
finally
stream.close()
end readStreamFully
end JSRun
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,34 @@ class ScalaJSCompilationTests extends ParallelTesting {
compileFilesInDir("tests/neg-scalajs", scalaJSOptions),
).checkExpectedErrors()
}

// Run tests -----------------------------------------------------------------

override protected def shouldSkipTestSource(testSource: TestSource): Boolean =
testSource.allToolArgs.get(ToolName.ScalaJS).exists(_.contains("--skip"))

override def runMain(classPath: String, toolArgs: ToolArgs)(implicit summaryReport: SummaryReporting): Status =
import scala.concurrent.ExecutionContext.Implicits.global

val scalaJSOptions = toolArgs.getOrElse(ToolName.ScalaJS, Nil)

try
val useCompliantSemantics = scalaJSOptions.contains("--compliant-semantics")
val sjsCode = ScalaJSLink.link(classPath, useCompliantSemantics)
JSRun.runJSCode(sjsCode)
catch
case t: Exception =>
val writer = new java.io.StringWriter()
t.printStackTrace(new java.io.PrintWriter(writer))
Failure(writer.toString())
end runMain

@Test def runScalaJS: Unit = {
implicit val testGroup: TestGroup = TestGroup("runScalaJS")
aggregateTests(
compileFilesInDir("tests/run", scalaJSOptions),
).checkRuns()
}
}

object ScalaJSCompilationTests {
Expand Down
58 changes: 58 additions & 0 deletions sjs-compiler-tests/test/scala/dotty/tools/dotc/ScalaJSLink.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package dotty.tools.dotc

import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext}

import java.io.File
import java.nio.file.{Files, Path}

import com.google.common.jimfs.Jimfs

import org.scalajs.linker.*
import org.scalajs.linker.interface.*
import org.scalajs.logging.*

object ScalaJSLink:
private val compliantSemantics: Semantics =
Semantics.Defaults
.withAsInstanceOfs(CheckedBehavior.Compliant)
.withArrayIndexOutOfBounds(CheckedBehavior.Compliant)
.withModuleInit(CheckedBehavior.Compliant)
end compliantSemantics

def link(classPath: String, useCompliantSemantics: Boolean)(using ExecutionContext): Path =
val cpEntries = classPath.split(File.pathSeparatorChar)

val logger = new ScalaConsoleLogger(Level.Warn)

val moduleInitializers = Seq(ModuleInitializer.mainMethodWithArgs(
"Test", "main", Nil))

val semantics = if useCompliantSemantics then compliantSemantics else Semantics.Defaults

val linkerConfig = StandardConfig()
.withCheckIR(true)
.withSourceMap(false)
.withBatchMode(true)
.withSemantics(semantics)

val linker = StandardImpl.linker(linkerConfig)

val dir = Jimfs.newFileSystem().getPath("tmp")
Files.createDirectory(dir)

val cache = StandardImpl.irFileCache().newCache
val result = PathIRContainer
.fromClasspath(cpEntries.toSeq.map(entry => new File(entry).toPath()))
.map(_._1)
.flatMap(cache.cached _)
.flatMap(linker.link(_, moduleInitializers, PathOutputDirectory(dir), logger))

val report = Await.result(result, Duration.Inf)

if (report.publicModules.size != 1)
throw new AssertionError(s"got other than 1 module: $report")

dir.resolve(report.publicModules.head.jsFileName)
end link
end ScalaJSLink
2 changes: 2 additions & 0 deletions tests/run/10838/Test.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --skip

object Test {
def main(args: Array[String]): Unit = {
val a = new A
Expand Down
2 changes: 2 additions & 0 deletions tests/run/Course-2002-01.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --skip

//############################################################################
// Programmation IV - 2002 - Week 01
//############################################################################
Expand Down
2 changes: 2 additions & 0 deletions tests/run/Course-2002-02.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --skip

//############################################################################
// Programmation IV - 2002 - Week 02
//############################################################################
Expand Down
2 changes: 2 additions & 0 deletions tests/run/Course-2002-03.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --skip

//############################################################################
// Programmation IV - 2002 - Week 03
//############################################################################
Expand Down
2 changes: 2 additions & 0 deletions tests/run/Course-2002-04.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --skip

//############################################################################
// Programmation IV - 2002 - Week 04
//############################################################################
Expand Down
2 changes: 2 additions & 0 deletions tests/run/Course-2002-05.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --skip

//############################################################################
// Programmation IV - 2002 - Week 05
//############################################################################
Expand Down
2 changes: 2 additions & 0 deletions tests/run/Course-2002-06.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --skip

//############################################################################
// Programmation IV - 2002 - Week 06
//############################################################################
Expand Down
2 changes: 2 additions & 0 deletions tests/run/Course-2002-07.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --skip

//############################################################################
// Programmation IV - 2002 - Week 07
//############################################################################
Expand Down
2 changes: 2 additions & 0 deletions tests/run/Course-2002-08.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --skip

//############################################################################
// Programmation IV - 2002 - Week 08
//############################################################################
Expand Down
2 changes: 2 additions & 0 deletions tests/run/Course-2002-09.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --skip

//############################################################################
// Programmation IV - 2002 - Week 09
//############################################################################
Expand Down
2 changes: 2 additions & 0 deletions tests/run/Course-2002-10.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --skip

//############################################################################
// Programmation IV - 2002 - Week 10
//############################################################################
Expand Down
2 changes: 2 additions & 0 deletions tests/run/Course-2002-13.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --skip

//############################################################################
// Programmation IV - 2002 - Week 13
//############################################################################
Expand Down
6 changes: 3 additions & 3 deletions tests/run/IArrayOps.check
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ ArraySeq(1, 2, 3)
ArraySeq((1,0), (2,1), (3,2))
List(1, 2, 3)
Vector(1, 2, 3)
ArrayBuffer(1, 2, 3)
Buffer(1, 2, 3)
ArraySeq(1, 2, 3)
ArraySeq(1, 2, 3)
List(1, 2, 3)
Expand All @@ -158,5 +158,5 @@ false
ArraySeq(a, b)
ArraySeq(1, 2, 4, 1, 2, 3, 9, 10)
List((1,5), (1,4), (1,5), (1,6), (1,5), (1,4), (1,5), (1,6), (1,5), (1,4), (1,5), (1,6))
List((1,true,1,2,3,4,5.0,6.0,a,abc,xyz,()))
ArraySeq((1,true,1,2,3,4,5.0,6.0,a,abc,xyz,()))
List((1,true,1,2,3,4,5.5,6.5,a,abc,xyz,()))
ArraySeq((1,true,1,2,3,4,5.5,6.5,a,abc,xyz,()))
Loading

0 comments on commit 7d6d42f

Please sign in to comment.