Skip to content

Commit 51f1429

Browse files
authored
Break up HelloJSWorldTests and HelloNativeWorldTests to take advantage of testForkGrouping (#3654)
These targets previously took 5+ minutes to run in a single task, now they split up into 3-4 tasks each taking 1-2 min. Won't reduce the total CPU time taken but will likely reduce the wall clock time by taking advantage of parallelism
1 parent 2e7a6ca commit 51f1429

File tree

8 files changed

+491
-423
lines changed

8 files changed

+491
-423
lines changed
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
package mill.scalajslib
2+
3+
import mill._
4+
import mill.define.Discover
5+
import mill.scalalib.{DepSyntax, PublishModule, ScalaModule, TestModule}
6+
import mill.scalalib.publish.{Developer, License, PomSettings, VersionControl}
7+
import mill.testkit.UnitTester
8+
import mill.testkit.TestBaseModule
9+
import utest._
10+
11+
import mill.scalalib.api.ZincWorkerUtil
12+
13+
object CompileLinkTests extends TestSuite {
14+
trait HelloJSWorldModule
15+
extends ScalaModule with ScalaJSModule with PublishModule
16+
with Cross.Module2[String, String] {
17+
val (crossScalaVersion, sjsVersion0) = (crossValue, crossValue2)
18+
def scalaVersion = crossScalaVersion
19+
def publishVersion = "0.0.1-SNAPSHOT"
20+
override def mainClass = Some("Main")
21+
}
22+
23+
object HelloJSWorld extends TestBaseModule {
24+
val scalaVersions = Seq("2.13.3", "3.0.0-RC1", "2.12.12")
25+
val scalaJSVersions = Seq("1.8.0", "1.0.1")
26+
val matrix = for {
27+
scala <- scalaVersions
28+
scalaJS <- scalaJSVersions
29+
if !(ZincWorkerUtil.isScala3(scala) && scalaJS != scalaJSVersions.head)
30+
} yield (scala, scalaJS)
31+
32+
object build extends Cross[RootModule](matrix)
33+
trait RootModule extends HelloJSWorldModule {
34+
override def artifactName = "hello-js-world"
35+
def scalaJSVersion = sjsVersion0
36+
def pomSettings = PomSettings(
37+
organization = "com.lihaoyi",
38+
description = "hello js world ready for real world publishing",
39+
url = "https://github.com/lihaoyi/hello-world-publish",
40+
licenses = Seq(License.Common.Apache2),
41+
versionControl = VersionControl.github("lihaoyi", "hello-world-publish"),
42+
developers =
43+
Seq(Developer("lihaoyi", "Li Haoyi", "https://github.com/lihaoyi"))
44+
)
45+
46+
object `test-utest` extends ScalaJSTests with TestModule.Utest {
47+
override def sources = Task.Sources { millSourcePath / "src/utest" }
48+
val utestVersion = if (ZincWorkerUtil.isScala3(crossScalaVersion)) "0.7.7" else "0.7.5"
49+
override def ivyDeps = Agg(
50+
ivy"com.lihaoyi::utest::$utestVersion"
51+
)
52+
}
53+
54+
object `test-scalatest` extends ScalaJSTests with TestModule.ScalaTest {
55+
override def sources = Task.Sources { millSourcePath / "src/scalatest" }
56+
override def ivyDeps = Agg(
57+
ivy"org.scalatest::scalatest::3.1.2"
58+
)
59+
}
60+
61+
}
62+
object inherited extends ScalaJSModule {
63+
val (scala, scalaJS) = matrix.head
64+
def scalacOptions = Seq("-deprecation")
65+
def scalaOrganization = "org.example"
66+
def scalaVersion = scala
67+
def scalaJSVersion = scalaJS
68+
object test extends ScalaJSTests with TestModule.Utest
69+
}
70+
71+
override lazy val millDiscover = Discover[this.type]
72+
}
73+
74+
val millSourcePath = os.Path(sys.env("MILL_TEST_RESOURCE_DIR")) / "hello-js-world"
75+
76+
def testRun(
77+
scalaVersion: String,
78+
scalaJSVersion: String,
79+
optimize: Boolean,
80+
legacy: Boolean
81+
): Unit = UnitTester(HelloJSWorld, millSourcePath).scoped { eval =>
82+
val module = HelloJSWorld.build(scalaVersion, scalaJSVersion)
83+
val jsFile =
84+
if (legacy) {
85+
val task = if (optimize) module.fullOpt else module.fastOpt
86+
val Right(result) = eval(task)
87+
result.value.path
88+
} else {
89+
val task = if (optimize) module.fullLinkJS else module.fastLinkJS
90+
val Right(result) = eval(task)
91+
result.value.dest.path / result.value.publicModules.head.jsFileName
92+
}
93+
val output = ScalaJsUtils.runJS(jsFile)
94+
assert(output == "Hello Scala.js\n")
95+
val sourceMap = jsFile / os.up / (jsFile.last + ".map")
96+
assert(sourceMap.toIO.exists()) // sourceMap file was generated
97+
assert(
98+
os.read(jsFile).contains(s"//# sourceMappingURL=${sourceMap.toNIO.getFileName}")
99+
) // jsFile references sourceMap
100+
assert(ujson.read(sourceMap.toIO).obj.get("file").exists(
101+
_.str == jsFile.toNIO.getFileName.toString
102+
)) // sourceMap references jsFile
103+
}
104+
105+
def tests: Tests = Tests {
106+
test("compile") - UnitTester(HelloJSWorld, millSourcePath).scoped { eval =>
107+
def testCompileFromScratch(scalaVersion: String, scalaJSVersion: String): Unit = {
108+
val Right(result) =
109+
eval(HelloJSWorld.build(scalaVersion, scalaJSVersion).compile)
110+
111+
val outPath = result.value.classes.path
112+
val outputFiles = os.walk(outPath)
113+
val expectedClassfiles = compileClassfiles(outPath, scalaVersion, scalaJSVersion)
114+
assert(
115+
outputFiles.toSet == expectedClassfiles,
116+
result.evalCount > 0
117+
)
118+
119+
// don't recompile if nothing changed
120+
val Right(result2) =
121+
eval(HelloJSWorld.build(scalaVersion, scalaJSVersion).compile)
122+
assert(result2.evalCount == 0)
123+
}
124+
125+
testAllMatrix((scala, scalaJS) => testCompileFromScratch(scala, scalaJS))
126+
}
127+
128+
test("fastLinkJS") {
129+
testAllMatrix((scala, scalaJS) =>
130+
testRun(scala, scalaJS, optimize = true, legacy = false)
131+
)
132+
}
133+
test("fullLinkJS") {
134+
testAllMatrix((scala, scalaJS) =>
135+
testRun(scala, scalaJS, optimize = true, legacy = false)
136+
)
137+
}
138+
}
139+
140+
def compileClassfiles(parentDir: os.Path, scalaVersion: String, scalaJSVersion: String) = {
141+
val inAllVersions = Set(
142+
parentDir / "ArgsParser$.class",
143+
parentDir / "ArgsParser$.sjsir",
144+
parentDir / "ArgsParser.class",
145+
parentDir / "Main.class",
146+
parentDir / "Main$.class",
147+
parentDir / "Main$.sjsir"
148+
)
149+
val scalaJSVersionSpecific =
150+
if (scalaJSVersion.startsWith("1.")) Set(
151+
parentDir / "ArgsParser.sjsir",
152+
parentDir / "Main.sjsir"
153+
)
154+
else Set.empty
155+
val scalaVersionSpecific =
156+
if (ZincWorkerUtil.isScala3(scalaVersion)) Set(
157+
parentDir / "ArgsParser.tasty",
158+
parentDir / "Main.tasty"
159+
)
160+
else Set(
161+
parentDir / "Main$delayedInit$body.class",
162+
parentDir / "Main$delayedInit$body.sjsir"
163+
)
164+
165+
inAllVersions ++ scalaJSVersionSpecific ++ scalaVersionSpecific
166+
}
167+
168+
def testAllMatrix(
169+
f: (String, String) => Unit,
170+
skipScala: String => Boolean = _ => false,
171+
skipScalaJS: String => Boolean = _ => false
172+
): Unit = {
173+
for {
174+
(scala, scalaJS) <- HelloJSWorld.matrix
175+
if !skipScala(scala)
176+
if !skipScalaJS(scalaJS)
177+
} {
178+
f(scala, scalaJS)
179+
}
180+
}
181+
182+
}

0 commit comments

Comments
 (0)