Skip to content

Execute tests/run/ tests with Scala.js. #15543

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 1 commit into from
Jul 4, 2022
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
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 @@ -1228,6 +1228,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