Skip to content

Commit 45c0d82

Browse files
ligeeSpace Team
authored andcommitted
MT tests: add test for model dump and reading it back
#KT-81046
1 parent fc1c222 commit 45c0d82

File tree

4 files changed

+131
-71
lines changed

4 files changed

+131
-71
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,7 @@ tasks {
967967
dependsOn("compilerPluginTest")
968968
dependsOn(":kotlin-daemon-tests:test")
969969
dependsOn(":compiler:arguments:test")
970+
dependsOn(":compiler:fir:modularized-tests:modelDumpTest")
970971
}
971972

972973
register("miscTest") {

compiler/fir/modularized-tests/build.gradle.kts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,17 @@ sourceSets {
5050
optInToK1Deprecation()
5151

5252
projectTests {
53+
val modelDumpAndReadTest = "org.jetbrains.kotlin.fir.ModelDumpAndReadTest"
54+
5355
testTask(minHeapSizeMb = 8192, maxHeapSizeMb = 8192, reservedCodeCacheSizeMb = 512, jUnitMode = JUnitMode.JUnit4) {
5456
dependsOn(":dist", ":plugins:compose-compiler-plugin:compiler-hosted:jar")
5557
systemProperties(project.properties.filterKeys { it.startsWith("fir.") })
5658
workingDir = rootDir
5759
val composePluginClasspath = composeCompilerPlugin.asPath
5860

61+
filter {
62+
excludeTestsMatching(modelDumpAndReadTest)
63+
}
5964
run {
6065
systemProperty("fir.bench.compose.plugin.classpath", composePluginClasspath)
6166
val argsExt = project.findProperty("fir.modularized.jvm.args") as? String
@@ -65,6 +70,14 @@ projectTests {
6570
}
6671
}
6772
}
73+
74+
testTask("modelDumpTest", jUnitMode = JUnitMode.JUnit4, skipInLocalBuild = false) {
75+
dependsOn(":dist")
76+
workingDir = rootDir
77+
filter {
78+
includeTestsMatching(modelDumpAndReadTest)
79+
}
80+
}
6881
}
6982

7083
testsJar()

compiler/fir/modularized-tests/tests/org/jetbrains/kotlin/fir/AbstractModularizedTest.kt

Lines changed: 72 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -91,77 +91,6 @@ abstract class AbstractModularizedTest : KtUsefulTestCase() {
9191
AbstractTypeChecker.RUN_SLOW_ASSERTIONS = true
9292
}
9393

94-
private fun loadModule(moduleElement: Element): ModuleData {
95-
val outputDir = moduleElement.getAttribute("outputDir").value
96-
val moduleName = moduleElement.getAttribute("name").value
97-
val moduleNameQualifier = outputDir.substringAfterLast("/")
98-
val javaSourceRoots = mutableListOf<JavaSourceRootData<String>>()
99-
val classpath = mutableListOf<String>()
100-
val sources = mutableListOf<String>()
101-
val friendDirs = mutableListOf<String>()
102-
val optInAnnotations = mutableListOf<String>()
103-
val timestamp = moduleElement.getAttribute("timestamp")?.longValue ?: 0
104-
val jdkHome = moduleElement.getAttribute("jdkHome")?.value
105-
var modularJdkRoot: String? = null
106-
var isCommon = false
107-
108-
for (item in moduleElement.children) {
109-
when (item.name) {
110-
"classpath" -> {
111-
val path = item.getAttribute("path").value
112-
if (path != outputDir) {
113-
classpath += path
114-
}
115-
}
116-
"friendDir" -> {
117-
val path = item.getAttribute("path").value
118-
friendDirs += path
119-
}
120-
"javaSourceRoots" -> {
121-
javaSourceRoots +=
122-
JavaSourceRootData(
123-
item.getAttribute("path").value,
124-
item.getAttribute("packagePrefix")?.value,
125-
)
126-
}
127-
"sources" -> sources += item.getAttribute("path").value
128-
"commonSources" -> isCommon = true
129-
"modularJdkRoot" -> modularJdkRoot = item.getAttribute("path").value
130-
"useOptIn" -> optInAnnotations += item.getAttribute("annotation").value
131-
}
132-
}
133-
134-
return ModuleData(
135-
moduleName,
136-
timestamp,
137-
outputDir,
138-
moduleNameQualifier,
139-
classpath,
140-
sources,
141-
javaSourceRoots,
142-
friendDirs,
143-
optInAnnotations,
144-
modularJdkRoot,
145-
jdkHome,
146-
isCommon,
147-
)
148-
}
149-
150-
private fun loadModuleDumpFile(file: File): List<ModuleData> {
151-
val rootElement = JDOMUtil.load(file)
152-
val modules = rootElement.getChildren("module")
153-
val arguments = rootElement.getChild("compilerArguments")?.let { loadCompilerArguments(it) }
154-
return modules.map { node -> loadModule(node).also { it.arguments = arguments } }
155-
}
156-
157-
private fun loadCompilerArguments(argumentsRoot: Element): CommonCompilerArguments? {
158-
val element = argumentsRoot.children.singleOrNull() ?: return null
159-
return when (element.name) {
160-
"K2JVMCompilerArguments" -> K2JVMCompilerArguments().also { XmlSerializer.deserializeInto(it, element) }
161-
else -> null
162-
}
163-
}
164-
16594
protected abstract fun beforePass(pass: Int)
16695
protected abstract fun afterPass(pass: Int)
16796
protected open fun afterAllPasses() {}
@@ -249,3 +178,75 @@ fun substituteCompilerPluginPathForKnownPlugins(path: String): File? {
249178
else -> null
250179
}
251180
}
181+
182+
internal fun loadModuleDumpFile(file: File): List<ModuleData> {
183+
val rootElement = JDOMUtil.load(file)
184+
val modules = rootElement.getChildren("module")
185+
val arguments = rootElement.getChild("compilerArguments")?.let { loadCompilerArguments(it) }
186+
return modules.map { node -> loadModule(node).also { it.arguments = arguments } }
187+
}
188+
189+
private fun loadModule(moduleElement: Element): ModuleData {
190+
val outputDir = moduleElement.getAttribute("outputDir").value
191+
val moduleName = moduleElement.getAttribute("name").value
192+
val moduleNameQualifier = outputDir.substringAfterLast("/")
193+
val javaSourceRoots = mutableListOf<JavaSourceRootData<String>>()
194+
val classpath = mutableListOf<String>()
195+
val sources = mutableListOf<String>()
196+
val friendDirs = mutableListOf<String>()
197+
val optInAnnotations = mutableListOf<String>()
198+
val timestamp = moduleElement.getAttribute("timestamp")?.longValue ?: 0
199+
val jdkHome = moduleElement.getAttribute("jdkHome")?.value
200+
var modularJdkRoot: String? = null
201+
var isCommon = false
202+
203+
for (item in moduleElement.children) {
204+
when (item.name) {
205+
"classpath" -> {
206+
val path = item.getAttribute("path").value
207+
if (path != outputDir) {
208+
classpath += path
209+
}
210+
}
211+
"friendDir" -> {
212+
val path = item.getAttribute("path").value
213+
friendDirs += path
214+
}
215+
"javaSourceRoots" -> {
216+
javaSourceRoots +=
217+
JavaSourceRootData(
218+
item.getAttribute("path").value,
219+
item.getAttribute("packagePrefix")?.value,
220+
)
221+
}
222+
"sources" -> sources += item.getAttribute("path").value
223+
"commonSources" -> isCommon = true
224+
"modularJdkRoot" -> modularJdkRoot = item.getAttribute("path").value
225+
"useOptIn" -> optInAnnotations += item.getAttribute("annotation").value
226+
}
227+
}
228+
229+
return ModuleData(
230+
moduleName,
231+
timestamp,
232+
outputDir,
233+
moduleNameQualifier,
234+
classpath,
235+
sources,
236+
javaSourceRoots,
237+
friendDirs,
238+
optInAnnotations,
239+
modularJdkRoot,
240+
jdkHome,
241+
isCommon,
242+
)
243+
}
244+
245+
private fun loadCompilerArguments(argumentsRoot: Element): CommonCompilerArguments? {
246+
val element = argumentsRoot.children.singleOrNull() ?: return null
247+
return when (element.name) {
248+
"K2JVMCompilerArguments" -> K2JVMCompilerArguments().also { XmlSerializer.deserializeInto(it, element) }
249+
else -> null
250+
}
251+
}
252+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
4+
*/
5+
6+
package org.jetbrains.kotlin.fir
7+
8+
import com.intellij.openapi.util.SystemInfo
9+
import org.jetbrains.kotlin.cli.common.ExitCode
10+
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
11+
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
12+
import org.jetbrains.kotlin.test.CompilerTestUtil
13+
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
14+
15+
class ModelDumpAndReadTest : TestCaseWithTmpdir() {
16+
17+
fun testModelDump() {
18+
// We don't want to bother with windows specifics yet, model dumping is unix-only now anyway.
19+
if (SystemInfo.isWindows) return
20+
val mainKt = tmpdir.resolve("main.kt").apply {
21+
writeText("fun main() {}")
22+
}
23+
val jarFile = tmpdir.resolve("output.jar")
24+
val args = listOf(
25+
"-d", jarFile.absolutePath,
26+
"-XXdump-model=${tmpdir.absolutePath}",
27+
"-module-name", "testmain",
28+
mainKt.absolutePath
29+
)
30+
val res = CompilerTestUtil.executeCompiler(K2JVMCompiler(), args)
31+
assertEquals(ExitCode.OK, res.second)
32+
33+
val modelDumpFile = tmpdir.resolve("model-testmain.xml")
34+
val moduleData = loadModuleDumpFile(modelDumpFile).single()
35+
36+
val arguments = moduleData.arguments as K2JVMCompilerArguments
37+
assertEquals(jarFile.absolutePath, arguments.destination)
38+
assertEquals(mainKt.absolutePath, arguments.freeArgs.single())
39+
assertEquals("testmain", arguments.moduleName)
40+
41+
assertEquals("testmain", moduleData.name)
42+
assertEquals(listOf(mainKt), moduleData.sources.toList())
43+
assertTrue(moduleData.classpath.any { it.name == "kotlin-stdlib.jar" })
44+
}
45+
}

0 commit comments

Comments
 (0)