Skip to content

Commit 7d6d42f

Browse files
authored
Merge pull request #15543 from dotty-staging/sjs-vulpix-run-tests
2 parents 298ef15 + 3518226 commit 7d6d42f

File tree

339 files changed

+920
-224
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

339 files changed

+920
-224
lines changed

compiler/test/dotty/tools/utils.scala

+4-2
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,16 @@ end assertThrows
5252

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

59+
type ToolArgs = Map[ToolName, List[String]]
60+
5961
/** Take a prefix of each file, extract tool args, parse, and combine.
6062
* Arg parsing respects quotation marks. Result is a map from ToolName to the combined tokens.
6163
*/
62-
def toolArgsFor(files: List[JPath], charset: Charset = UTF_8): Map[ToolName, List[String]] =
64+
def toolArgsFor(files: List[JPath], charset: Charset = UTF_8): ToolArgs =
6365
files.foldLeft(Map.empty[ToolName, List[String]]) { (res, path) =>
6466
val toolargs = toolArgsParse(resource(Files.lines(path, charset))(_.limit(10).toScala(List)))
6567
toolargs.foldLeft(res) {

compiler/test/dotty/tools/vulpix/ParallelTesting.scala

+16-8
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ trait ParallelTesting extends RunnerOrchestration { self =>
9696
self.copy(flags = flags.without(flags1: _*))
9797
}
9898

99+
lazy val allToolArgs: ToolArgs =
100+
toolArgsFor(sourceFiles.toList.map(_.toPath), getCharsetFromEncodingOpt(flags))
101+
99102
/** Generate the instructions to redo the test from the command line */
100103
def buildInstructions(errors: Int, warnings: Int): String = {
101104
val sb = new StringBuilder
@@ -199,6 +202,9 @@ trait ParallelTesting extends RunnerOrchestration { self =>
199202
def sourceFiles = compilationGroups.map(_._2).flatten.toArray
200203
}
201204

205+
protected def shouldSkipTestSource(testSource: TestSource): Boolean =
206+
false
207+
202208
private trait CompilationLogic { this: Test =>
203209
def suppressErrors = false
204210

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

345351
/** All testSources left after filtering out */
346352
private val filteredSources =
347-
if (testFilter.isEmpty) testSources
348-
else testSources.filter {
349-
case JointCompilationSource(_, files, _, _, _, _) =>
350-
testFilter.exists(filter => files.exists(file => file.getPath.contains(filter)))
351-
case SeparateCompilationSource(_, dir, _, _) =>
352-
testFilter.exists(dir.getPath.contains)
353-
}
353+
val filteredByName =
354+
if (testFilter.isEmpty) testSources
355+
else testSources.filter {
356+
case JointCompilationSource(_, files, _, _, _, _) =>
357+
testFilter.exists(filter => files.exists(file => file.getPath.contains(filter)))
358+
case SeparateCompilationSource(_, dir, _, _) =>
359+
testFilter.exists(dir.getPath.contains)
360+
}
361+
filteredByName.filterNot(shouldSkipTestSource(_))
354362

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

740748
private def verifyOutput(checkFile: Option[JFile], dir: JFile, testSource: TestSource, warnings: Int, reporters: Seq[TestReporter], logger: LoggedRunnable) = {
741749
if (Properties.testsNoRun) addNoRunWarning()
742-
else runMain(testSource.runClassPath) match {
750+
else runMain(testSource.runClassPath, testSource.allToolArgs) match {
743751
case Success(output) => checkFile match {
744752
case Some(file) if file.exists => diffTest(testSource, file, output.linesIterator.toList, reporters, logger)
745753
case _ =>

compiler/test/dotty/tools/vulpix/RunnerOrchestration.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ trait RunnerOrchestration {
4848
def safeMode: Boolean
4949

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

5454
/** Kill all processes */

compiler/test/dotty/tools/vulpix/TestConfiguration.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ object TestConfiguration {
7272
lazy val withTastyInspectorOptions =
7373
defaultOptions.withClasspath(withTastyInspectorClasspath).withRunClasspath(withTastyInspectorClasspath)
7474
lazy val scalaJSOptions =
75-
defaultOptions.and("-scalajs").withClasspath(scalaJSClasspath)
75+
defaultOptions.and("-scalajs").withClasspath(scalaJSClasspath).withRunClasspath(scalaJSClasspath)
7676
val allowDeepSubtypes = defaultOptions without "-Yno-deep-subtypes"
7777
val allowDoubleBindings = defaultOptions without "-Yno-double-bindings"
7878
val picklingOptions = defaultOptions and (

project/Build.scala

+5
Original file line numberDiff line numberDiff line change
@@ -1229,6 +1229,11 @@ object Build {
12291229
settings(
12301230
commonNonBootstrappedSettings,
12311231

1232+
libraryDependencies ++= Seq(
1233+
"org.scala-js" %% "scalajs-linker" % scalaJSVersion % Test cross CrossVersion.for3Use2_13,
1234+
"org.scala-js" %% "scalajs-env-nodejs" % "1.3.0" % Test cross CrossVersion.for3Use2_13,
1235+
),
1236+
12321237
// Change the baseDirectory when running the tests
12331238
Test / baseDirectory := baseDirectory.value.getParentFile,
12341239

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package dotty.tools.dotc
2+
3+
import scala.concurrent.duration.Duration
4+
import scala.concurrent.{Await, ExecutionContext}
5+
6+
import java.io.InputStream
7+
import java.nio.charset.StandardCharsets
8+
import java.nio.file.Path
9+
10+
import dotty.tools.vulpix.*
11+
12+
import org.scalajs.jsenv.*
13+
import org.scalajs.jsenv.nodejs.NodeJSEnv
14+
import org.scalajs.logging.*
15+
16+
object JSRun:
17+
def runJSCode(sjsCode: Path)(using ExecutionContext): Status =
18+
val logger = new ScalaConsoleLogger(Level.Warn)
19+
20+
var stdoutStream: Option[InputStream] = None
21+
var stderrStream: Option[InputStream] = None
22+
23+
val input = Input.Script(sjsCode) :: Nil
24+
val config = RunConfig()
25+
.withLogger(logger)
26+
.withInheritOut(false)
27+
.withInheritErr(false)
28+
.withOnOutputStream { (out, err) =>
29+
stdoutStream = out
30+
stderrStream = err
31+
}
32+
33+
val run = new NodeJSEnv().start(input, config)
34+
try
35+
val success = try {
36+
Await.result(run.future, Duration.Inf)
37+
true
38+
} catch {
39+
case _: Exception =>
40+
false
41+
}
42+
val output = readStreamFully(stderrStream) + readStreamFully(stdoutStream)
43+
if success then
44+
Success(output)
45+
else
46+
Failure(output)
47+
finally
48+
run.close()
49+
end runJSCode
50+
51+
private def readStreamFully(optStream: Option[InputStream]): String =
52+
optStream match
53+
case None =>
54+
""
55+
case Some(stream) =>
56+
try
57+
val result = new java.io.ByteArrayOutputStream()
58+
val buffer = new Array[Byte](1024)
59+
while ({
60+
val len = stream.read(buffer)
61+
len >= 0 && {
62+
result.write(buffer, 0, len)
63+
true
64+
}
65+
}) ()
66+
new String(result.toByteArray(), StandardCharsets.UTF_8)
67+
finally
68+
stream.close()
69+
end readStreamFully
70+
end JSRun

sjs-compiler-tests/test/scala/dotty/tools/dotc/ScalaJSCompilationTests.scala

+28
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,34 @@ class ScalaJSCompilationTests extends ParallelTesting {
3232
compileFilesInDir("tests/neg-scalajs", scalaJSOptions),
3333
).checkExpectedErrors()
3434
}
35+
36+
// Run tests -----------------------------------------------------------------
37+
38+
override protected def shouldSkipTestSource(testSource: TestSource): Boolean =
39+
testSource.allToolArgs.get(ToolName.ScalaJS).exists(_.contains("--skip"))
40+
41+
override def runMain(classPath: String, toolArgs: ToolArgs)(implicit summaryReport: SummaryReporting): Status =
42+
import scala.concurrent.ExecutionContext.Implicits.global
43+
44+
val scalaJSOptions = toolArgs.getOrElse(ToolName.ScalaJS, Nil)
45+
46+
try
47+
val useCompliantSemantics = scalaJSOptions.contains("--compliant-semantics")
48+
val sjsCode = ScalaJSLink.link(classPath, useCompliantSemantics)
49+
JSRun.runJSCode(sjsCode)
50+
catch
51+
case t: Exception =>
52+
val writer = new java.io.StringWriter()
53+
t.printStackTrace(new java.io.PrintWriter(writer))
54+
Failure(writer.toString())
55+
end runMain
56+
57+
@Test def runScalaJS: Unit = {
58+
implicit val testGroup: TestGroup = TestGroup("runScalaJS")
59+
aggregateTests(
60+
compileFilesInDir("tests/run", scalaJSOptions),
61+
).checkRuns()
62+
}
3563
}
3664

3765
object ScalaJSCompilationTests {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package dotty.tools.dotc
2+
3+
import scala.concurrent.duration.Duration
4+
import scala.concurrent.{Await, ExecutionContext}
5+
6+
import java.io.File
7+
import java.nio.file.{Files, Path}
8+
9+
import com.google.common.jimfs.Jimfs
10+
11+
import org.scalajs.linker.*
12+
import org.scalajs.linker.interface.*
13+
import org.scalajs.logging.*
14+
15+
object ScalaJSLink:
16+
private val compliantSemantics: Semantics =
17+
Semantics.Defaults
18+
.withAsInstanceOfs(CheckedBehavior.Compliant)
19+
.withArrayIndexOutOfBounds(CheckedBehavior.Compliant)
20+
.withModuleInit(CheckedBehavior.Compliant)
21+
end compliantSemantics
22+
23+
def link(classPath: String, useCompliantSemantics: Boolean)(using ExecutionContext): Path =
24+
val cpEntries = classPath.split(File.pathSeparatorChar)
25+
26+
val logger = new ScalaConsoleLogger(Level.Warn)
27+
28+
val moduleInitializers = Seq(ModuleInitializer.mainMethodWithArgs(
29+
"Test", "main", Nil))
30+
31+
val semantics = if useCompliantSemantics then compliantSemantics else Semantics.Defaults
32+
33+
val linkerConfig = StandardConfig()
34+
.withCheckIR(true)
35+
.withSourceMap(false)
36+
.withBatchMode(true)
37+
.withSemantics(semantics)
38+
39+
val linker = StandardImpl.linker(linkerConfig)
40+
41+
val dir = Jimfs.newFileSystem().getPath("tmp")
42+
Files.createDirectory(dir)
43+
44+
val cache = StandardImpl.irFileCache().newCache
45+
val result = PathIRContainer
46+
.fromClasspath(cpEntries.toSeq.map(entry => new File(entry).toPath()))
47+
.map(_._1)
48+
.flatMap(cache.cached _)
49+
.flatMap(linker.link(_, moduleInitializers, PathOutputDirectory(dir), logger))
50+
51+
val report = Await.result(result, Duration.Inf)
52+
53+
if (report.publicModules.size != 1)
54+
throw new AssertionError(s"got other than 1 module: $report")
55+
56+
dir.resolve(report.publicModules.head.jsFileName)
57+
end link
58+
end ScalaJSLink

tests/run/10838/Test.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalajs: --skip
2+
13
object Test {
24
def main(args: Array[String]): Unit = {
35
val a = new A

tests/run/Course-2002-01.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalajs: --skip
2+
13
//############################################################################
24
// Programmation IV - 2002 - Week 01
35
//############################################################################

tests/run/Course-2002-02.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalajs: --skip
2+
13
//############################################################################
24
// Programmation IV - 2002 - Week 02
35
//############################################################################

tests/run/Course-2002-03.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalajs: --skip
2+
13
//############################################################################
24
// Programmation IV - 2002 - Week 03
35
//############################################################################

tests/run/Course-2002-04.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalajs: --skip
2+
13
//############################################################################
24
// Programmation IV - 2002 - Week 04
35
//############################################################################

tests/run/Course-2002-05.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalajs: --skip
2+
13
//############################################################################
24
// Programmation IV - 2002 - Week 05
35
//############################################################################

tests/run/Course-2002-06.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalajs: --skip
2+
13
//############################################################################
24
// Programmation IV - 2002 - Week 06
35
//############################################################################

tests/run/Course-2002-07.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalajs: --skip
2+
13
//############################################################################
24
// Programmation IV - 2002 - Week 07
35
//############################################################################

tests/run/Course-2002-08.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalajs: --skip
2+
13
//############################################################################
24
// Programmation IV - 2002 - Week 08
35
//############################################################################

tests/run/Course-2002-09.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalajs: --skip
2+
13
//############################################################################
24
// Programmation IV - 2002 - Week 09
35
//############################################################################

tests/run/Course-2002-10.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalajs: --skip
2+
13
//############################################################################
24
// Programmation IV - 2002 - Week 10
35
//############################################################################

tests/run/Course-2002-13.scala

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// scalajs: --skip
2+
13
//############################################################################
24
// Programmation IV - 2002 - Week 13
35
//############################################################################

tests/run/IArrayOps.check

+3-3
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ ArraySeq(1, 2, 3)
131131
ArraySeq((1,0), (2,1), (3,2))
132132
List(1, 2, 3)
133133
Vector(1, 2, 3)
134-
ArrayBuffer(1, 2, 3)
134+
Buffer(1, 2, 3)
135135
ArraySeq(1, 2, 3)
136136
ArraySeq(1, 2, 3)
137137
List(1, 2, 3)
@@ -158,5 +158,5 @@ false
158158
ArraySeq(a, b)
159159
ArraySeq(1, 2, 4, 1, 2, 3, 9, 10)
160160
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))
161-
List((1,true,1,2,3,4,5.0,6.0,a,abc,xyz,()))
162-
ArraySeq((1,true,1,2,3,4,5.0,6.0,a,abc,xyz,()))
161+
List((1,true,1,2,3,4,5.5,6.5,a,abc,xyz,()))
162+
ArraySeq((1,true,1,2,3,4,5.5,6.5,a,abc,xyz,()))

0 commit comments

Comments
 (0)