Skip to content

Commit ea70a8a

Browse files
committed
Add tests for multi module bsp
1 parent 545051f commit ea70a8a

File tree

3 files changed

+210
-6
lines changed

3 files changed

+210
-6
lines changed

build.sc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,7 @@ trait CliIntegration extends SbtModule with ScalaCliPublishModule with HasTests
10371037
)}"
10381038
| def cs = "${settings.cs().replace("\\", "\\\\")}"
10391039
| def workspaceDirName = "$workspaceDirName"
1040+
| def moduleConfigFileName = "$moduleConfigFileName"
10401041
| def libsodiumVersion = "${deps.libsodiumVersion}"
10411042
| def dockerArchLinuxImage = "${TestDeps.archLinuxImage}"
10421043
|

modules/integration/src/test/scala/scala/cli/integration/BspTestDefinitions.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@ import com.google.gson.{Gson, JsonElement}
88
import java.net.URI
99
import java.nio.file.Paths
1010
import scala.async.Async.{async, await}
11+
import scala.cli.integration.compose.ComposeBspTestDefinitions
1112
import scala.concurrent.ExecutionContext.Implicits.global
1213
import scala.concurrent.Future
1314
import scala.concurrent.duration.*
1415
import scala.jdk.CollectionConverters.*
1516
import scala.util.Properties
1617

1718
abstract class BspTestDefinitions extends ScalaCliSuite with TestScalaVersionArgs
18-
with BspSuite with ScriptWrapperTestDefinitions {
19+
with BspSuite with ScriptWrapperTestDefinitions
20+
with ComposeBspTestDefinitions {
1921
_: TestScalaVersion =>
2022
protected lazy val extraOptions: Seq[String] = scalaVersionArgs ++ TestUtil.extraOptions
2123

Lines changed: 206 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,208 @@
1-
//package scala.cli.integration.compose
1+
package scala.cli.integration.compose
2+
3+
import ch.epfl.scala.bsp4j as b
4+
import ch.epfl.scala.bsp4j.BuildTargetIdentifier
5+
import com.eed3si9n.expecty.Expecty.expect
6+
7+
import java.net.URI
8+
import java.nio.file.Paths
9+
import scala.async.Async.{async, await}
10+
import scala.cli.integration.*
11+
import scala.concurrent.ExecutionContext.Implicits.global
12+
import scala.jdk.CollectionConverters.*
13+
14+
trait ComposeBspTestDefinitions extends ScalaCliSuite { _: BspTestDefinitions =>
15+
test(
16+
"composed setup-ide should write the .bsp file in the directory where module config file was found"
17+
) {
18+
val testInputs = TestInputs(
19+
os.rel / Constants.moduleConfigFileName ->
20+
"""[modules.webpage]
21+
|dependsOn = ["core"]
22+
|
23+
|[modules.core]
24+
|roots = ["Core.scala", "Utils.scala"]
25+
|""".stripMargin,
26+
os.rel / "webpage" / "Website.scala" -> "",
27+
os.rel / "Core.scala" -> "",
28+
os.rel / "Utils.scala" -> ""
29+
)
30+
31+
testInputs.fromRoot { root =>
32+
os.proc(TestUtil.cli, "--power", "setup-ide", ".", extraOptions).call(
33+
cwd = root,
34+
stdout = os.Inherit
35+
)
36+
val details = readBspConfig(root)
37+
val expectedIdeOptionsFile = root / Constants.workspaceDirName / "ide-options-v2.json"
38+
val expectedIdeLaunchFile = root / Constants.workspaceDirName / "ide-launcher-options.json"
39+
val expectedIdeInputsFile = root / Constants.workspaceDirName / "ide-inputs.json"
40+
val expectedIdeEnvsFile = root / Constants.workspaceDirName / "ide-envs.json"
41+
val expectedArgv = Seq(
42+
TestUtil.cliPath,
43+
"--power",
44+
"bsp",
45+
"--json-options",
46+
expectedIdeOptionsFile.toString,
47+
"--json-launcher-options",
48+
expectedIdeLaunchFile.toString,
49+
"--envs-file",
50+
expectedIdeEnvsFile.toString,
51+
(root / Constants.moduleConfigFileName).toString
52+
)
53+
expect(details.argv == expectedArgv)
54+
expect(os.isFile(expectedIdeOptionsFile))
55+
expect(os.isFile(expectedIdeInputsFile))
56+
}
57+
}
58+
59+
test("composed bsp should have build targets for all modules") {
60+
val testInputs = TestInputs(
61+
os.rel / Constants.moduleConfigFileName ->
62+
"""[modules.core]
63+
|dependsOn = ["utils"]
64+
|
65+
|[modules.utils]
66+
|roots = ["Utils.scala", "Utils2.scala"]
67+
|""".stripMargin,
68+
os.rel / "core" / "Core.scala" ->
69+
"""object Core extends App {
70+
| println(Utils.util)
71+
| println(Utils2.util)
72+
|}
73+
|""".stripMargin,
74+
os.rel / "Utils.scala" -> "object Utils { def util: String = \"util\"}",
75+
os.rel / "Utils2.scala" -> "object Utils2 { def util: String = \"util2\"}"
76+
)
77+
78+
withBsp(testInputs, Seq("--power", ".")) { (root, _, remoteServer) =>
79+
async {
80+
val buildTargetsResp = await(remoteServer.workspaceBuildTargets().asScala)
81+
val target = {
82+
val targets = buildTargetsResp.getTargets.asScala.map(_.getId).toSeq
83+
expect(targets.length == 4)
84+
expect(extractMainTargetsOfModules(targets).size == 2)
85+
expect(extractTestTargetsOfModules(targets).size == 2)
86+
extractMainTargets(targets.filter(_.getUri.contains("core")))
87+
}
88+
89+
val targetUri = TestUtil.normalizeUri(target.getUri)
90+
checkTargetUri(root, targetUri)
91+
92+
val targets = List(target).asJava
93+
94+
{
95+
val resp = await {
96+
remoteServer
97+
.buildTargetDependencySources(new b.DependencySourcesParams(targets))
98+
.asScala
99+
}
100+
val foundTargets = resp.getItems.asScala.map(_.getTarget.getUri).toSeq
101+
expect(foundTargets == Seq(targetUri))
102+
val foundDepSources = resp.getItems.asScala
103+
.flatMap(_.getSources.asScala)
104+
.toSeq
105+
.map { uri =>
106+
val idx = uri.lastIndexOf('/')
107+
uri.drop(idx + 1)
108+
}
109+
if (actualScalaVersion.startsWith("2.")) {
110+
expect(foundDepSources.length == 1)
111+
expect(foundDepSources.forall(_.startsWith("scala-library-")))
112+
}
113+
else {
114+
expect(foundDepSources.length == 2)
115+
expect(foundDepSources.exists(_.startsWith("scala-library-")))
116+
expect(foundDepSources.exists(_.startsWith("scala3-library_3-3")))
117+
}
118+
expect(foundDepSources.forall(_.endsWith("-sources.jar")))
119+
}
120+
121+
{
122+
val resp = await(remoteServer.buildTargetSources(new b.SourcesParams(targets)).asScala)
123+
val foundTargets = resp.getItems.asScala.map(_.getTarget.getUri).toSeq
124+
expect(foundTargets == Seq(targetUri))
125+
val foundSources = resp.getItems.asScala
126+
.map(_.getSources.asScala.map(_.getUri).toSeq)
127+
.toSeq
128+
.map(_.map(TestUtil.normalizeUri))
129+
val expectedSources = Seq(
130+
Seq(
131+
TestUtil.normalizeUri((root / "core" / "Core.scala").toNIO.toUri.toASCIIString)
132+
)
133+
)
134+
expect(foundSources == expectedSources)
135+
}
136+
137+
val scalacOptionsResp = {
138+
val resp = await {
139+
remoteServer
140+
.buildTargetScalacOptions(new b.ScalacOptionsParams(targets))
141+
.asScala
142+
}
143+
val foundTargets = resp
144+
.getItems
145+
.asScala
146+
.map(_.getTarget.getUri)
147+
.map(TestUtil.normalizeUri)
148+
expect(foundTargets == Seq(targetUri))
149+
val foundOptions = resp.getItems.asScala.flatMap(_.getOptions.asScala).toSeq
150+
if (actualScalaVersion.startsWith("2."))
151+
expect(foundOptions.exists { opt =>
152+
opt.startsWith("-Xplugin:") && opt.contains("semanticdb-scalac")
153+
})
154+
else
155+
expect(foundOptions.contains("-Xsemanticdb"))
156+
resp
157+
}
158+
159+
{
160+
val resp = await {
161+
remoteServer.buildTargetJavacOptions(new b.JavacOptionsParams(targets)).asScala
162+
}
163+
val foundTargets = resp
164+
.getItems
165+
.asScala
166+
.map(_.getTarget.getUri)
167+
.map(TestUtil.normalizeUri)
168+
expect(foundTargets == Seq(targetUri))
169+
}
170+
171+
val classDir = os.Path(
172+
Paths.get(new URI(scalacOptionsResp.getItems.asScala.head.getClassDirectory))
173+
)
174+
175+
{
176+
val resp = await(remoteServer.buildTargetCompile(new b.CompileParams(targets)).asScala)
177+
expect(resp.getStatusCode == b.StatusCode.OK)
178+
}
179+
180+
val compileProducts = os.walk(classDir).filter(os.isFile(_)).map(_.relativeTo(classDir))
181+
182+
// if (actualScalaVersion.startsWith("3."))
183+
// expect(compileProducts.contains(os.rel / "simple$_.class"))
184+
// else
185+
// expect(compileProducts.contains(os.rel / "simple$.class"))
2186
//
3-
//import scala.cli.integration.{BspTestDefinitions, ScalaCliSuite}
187+
188+
// Thread.sleep(60*1000)
4189
//
5-
//trait ComposeBspTestDefinitions extends ScalaCliSuite { _: BspTestDefinitions =>
6-
// test()
7-
//}
190+
// expect(
191+
// compileProducts.contains(os.rel / "META-INF" / "semanticdb" / "simple.sc.semanticdb")
192+
// )
193+
}
194+
}
195+
}
196+
197+
private def extractMainTargetsOfModules(targets: Seq[BuildTargetIdentifier])
198+
: Seq[BuildTargetIdentifier] =
199+
targets.collect {
200+
case t if !t.getUri.contains("-test") => t
201+
}
202+
203+
private def extractTestTargetsOfModules(targets: Seq[BuildTargetIdentifier])
204+
: Seq[BuildTargetIdentifier] =
205+
targets.collect {
206+
case t if t.getUri.contains("-test") => t
207+
}
208+
}

0 commit comments

Comments
 (0)