Skip to content

Commit d3eb5e0

Browse files
authored
Merge pull request #497 from modelix/fix/bulk-sync-cross-module-references
MODELIX-756 bulk-model-sync does not import cross-module-references into MPS
2 parents 3c161d3 + 3fbf248 commit d3eb5e0

File tree

21 files changed

+296
-85
lines changed

21 files changed

+296
-85
lines changed

bulk-model-sync-gradle-test/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ mpsBuild {
8585
modelSync {
8686
dependsOn(copyTestRepo)
8787
direction("testPush") {
88-
includeModule("GraphSolution")
88+
includeModulesByPrefix("GraphSolution")
8989
fromLocal {
9090
mpsHeapSize = "2g"
9191
repositoryDir = repoDir
@@ -99,7 +99,7 @@ modelSync {
9999
}
100100
}
101101
direction("testPull") {
102-
includeModule("GraphSolution")
102+
includeModulesByPrefix("GraphSolution")
103103
fromModelServer {
104104
url = "http://localhost:28309/v2"
105105
repositoryId = "ci-test"

bulk-model-sync-gradle-test/src/test/kotlin/org/modelix/model/sync/bulk/gradle/test/ChangeApplier.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@ package org.modelix.model.sync.bulk.gradle.test
1818

1919
import GraphLang.L_GraphLang
2020
import GraphLang.N_Edge
21+
import GraphLang.N_Graph
2122
import GraphLang.N_Node
2223
import GraphLang._C_UntypedImpl_Edge
24+
import GraphLang._C_UntypedImpl_Graph
2325
import GraphLang._C_UntypedImpl_Node
2426
import jetbrains.mps.lang.core.L_jetbrains_mps_lang_core
2527
import kotlinx.coroutines.runBlocking
2628
import org.modelix.metamodel.TypedLanguagesRegistry
2729
import org.modelix.metamodel.typed
2830
import org.modelix.model.ModelFacade
31+
import org.modelix.model.api.BuiltinLanguages
2932
import org.modelix.model.api.ConceptReference
3033
import org.modelix.model.api.getDescendants
3134
import org.modelix.model.client2.ModelClientV2PlatformSpecificBuilder
@@ -68,6 +71,20 @@ class ChangeApplier {
6871

6972
edges[0].source = graphNodes[1]
7073
edges[0].target = graphNodes[3]
74+
75+
val solution1Graph = rootNode.allChildren
76+
.find { it.getPropertyValue(BuiltinLanguages.jetbrains_mps_lang_core.INamedConcept.name) == "GraphSolution" }
77+
?.getDescendants(false)
78+
?.find { it.getConceptReference() == ConceptReference(_C_UntypedImpl_Graph.getUID()) }
79+
?.typed<N_Graph>()
80+
81+
val solution2Graph = rootNode.allChildren
82+
.find { it.getPropertyValue(BuiltinLanguages.jetbrains_mps_lang_core.INamedConcept.name) == "GraphSolution2" }
83+
?.getDescendants(false)
84+
?.find { it.getConceptReference() == ConceptReference(_C_UntypedImpl_Graph.getUID()) }
85+
?.typed<N_Graph>()
86+
87+
solution1Graph?.relatedGraph = solution2Graph
7188
}
7289
}
7390
}

bulk-model-sync-gradle-test/src/test/kotlin/org/modelix/model/sync/bulk/gradle/test/PullTest.kt

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,28 @@ import org.xmlunit.builder.Input
2222
import org.xmlunit.xpath.JAXPXPathEngine
2323
import java.io.File
2424
import kotlin.test.assertContentEquals
25+
import kotlin.test.assertEquals
2526

2627
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
2728
class PullTest {
2829

29-
private val localModel = File("build/test-repo/solutions/GraphSolution/models/GraphSolution.example.mps").readText()
30-
private val source = Input.fromString(localModel).build()
30+
private val solutionsBaseDir = File("build/test-repo/solutions")
31+
private val solution1Xml = Input.fromString(
32+
solutionsBaseDir
33+
.resolve("GraphSolution/models/GraphSolution.example.mps")
34+
.readText(),
35+
).build()
36+
37+
private val solution2Xml = Input.fromString(
38+
solutionsBaseDir
39+
.resolve("GraphSolution2/models/GraphSolution2.example.mps")
40+
.readText(),
41+
).build()
3142

3243
@Test
3344
fun `properties were synced to local`() {
3445
val properties = JAXPXPathEngine()
35-
.selectNodes("model/node/node[@concept='1DmExO']/property", source)
46+
.selectNodes("model/node/node[@concept='1DmExO']/property", solution1Xml)
3647

3748
val actual = properties.map { it.attributes.getNamedItem("value").nodeValue }
3849
val expected = listOf("X", "Y", "Z", "D", "E")
@@ -43,11 +54,33 @@ class PullTest {
4354
@Test
4455
fun `references were synced to local`() {
4556
val references = JAXPXPathEngine()
46-
.selectNodes("model/node/node[@id='pSCM1J8Fg1']/ref", source)
57+
.selectNodes("model/node/node[@id='pSCM1J8Fg1']/ref", solution1Xml)
4758

4859
val actual = references.map { it.attributes.getNamedItem("node").nodeValue }
4960
val expected = listOf("pSCM1J8FfX", "pSCM1J8FfZ")
5061

5162
assertContentEquals(expected, actual)
5263
}
64+
65+
@Test
66+
fun `existing cross-module references are intact`() {
67+
val reference = JAXPXPathEngine()
68+
.selectNodes("model/node[@id='27XSKLmUrj6']/ref", solution2Xml)
69+
70+
val actual = reference.map { it.attributes.getNamedItem("to").nodeValue }
71+
val expected = listOf("c5sg:pSCM1J8y9y")
72+
73+
assertEquals(expected, actual)
74+
}
75+
76+
@Test
77+
fun `newly created cross-module references are synced`() {
78+
val reference = JAXPXPathEngine()
79+
.selectNodes("model/node[@id='pSCM1J8y9y']/ref", solution1Xml)
80+
81+
val actual = reference.map { it.attributes.getNamedItem("to").nodeValue }
82+
val expected = listOf("gywm:27XSKLmUrj6")
83+
84+
assertEquals(expected, actual)
85+
}
5386
}
Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
11
package org.modelix.model.sync.bulk.gradle.test
22

3+
import GraphLang.C_Graph
4+
import GraphLang._C_UntypedImpl_Graph
35
import kotlinx.coroutines.runBlocking
46
import org.junit.jupiter.api.Test
57
import org.junit.jupiter.api.TestInstance
68
import org.modelix.model.ModelFacade
9+
import org.modelix.model.api.BuiltinLanguages
10+
import org.modelix.model.api.ConceptReference
11+
import org.modelix.model.api.INode
712
import org.modelix.model.api.IProperty
13+
import org.modelix.model.api.PBranch
14+
import org.modelix.model.api.getDescendants
815
import org.modelix.model.api.getRootNode
916
import org.modelix.model.client2.ModelClientV2PlatformSpecificBuilder
10-
import org.modelix.model.client2.getReplicatedModel
1117
import org.modelix.model.data.ModelData
1218
import org.modelix.model.data.NodeData
1319
import org.modelix.model.lazy.RepositoryId
1420
import org.modelix.model.sync.bulk.asExported
21+
import org.modelix.model.withAutoTransactions
1522
import java.io.File
1623
import kotlin.test.assertContentEquals
1724
import kotlin.test.assertEquals
@@ -22,34 +29,47 @@ class PushTest {
2229
private val branchRef = ModelFacade.createBranchReference(RepositoryId("ci-test"), "master")
2330
private val client = ModelClientV2PlatformSpecificBuilder().url(url).build().apply { runBlocking { init() } }
2431

32+
private fun runTest(body: (INode) -> Unit) {
33+
val baseVersion = runBlocking { client.pullIfExists(branchRef)!! }
34+
val branch = PBranch(baseVersion.getTree(), client.getIdGenerator()).withAutoTransactions()
35+
body(branch.getRootNode())
36+
}
37+
2538
@Test
26-
fun `nodes were synced to server`() {
39+
fun `nodes were synced to server`() = runTest { root ->
2740
val inputDir = File("build/model-sync/testPush")
2841
val files = inputDir.listFiles()?.filter { it.extension == "json" } ?: error("no json files found in ${inputDir.absolutePath}")
2942

3043
val modules = files.map { ModelData.fromJson(it.readText()) }
3144
val inputModel = ModelData(root = NodeData(children = modules.map { it.root }))
3245

33-
val replicatedModel = client.getReplicatedModel(branchRef)
34-
val branch = runBlocking { replicatedModel.start() }
46+
assertContentEquals(inputModel.root.children, root.allChildren.map { it.asExported() })
47+
}
48+
49+
@Test
50+
fun `meta properties were applied to root node`() = runTest { root ->
51+
val actual1 = root.getPropertyValue(IProperty.fromName("metaKey1"))
52+
val actual2 = root.getPropertyValue(IProperty.fromName("metaKey2"))
3553

36-
branch.runRead {
37-
assertContentEquals(inputModel.root.children, branch.getRootNode().allChildren.map { it.asExported() })
38-
}
39-
replicatedModel.dispose()
54+
assertEquals("metaValue1", actual1)
55+
assertEquals("metaValue2", actual2)
4056
}
4157

4258
@Test
43-
fun `meta properties were applied to root node`() {
44-
val replicatedModel = client.getReplicatedModel(branchRef)
45-
val branch = runBlocking { replicatedModel.start() }
46-
branch.runRead {
47-
val actual1 = branch.getRootNode().getPropertyValue(IProperty.fromName("metaKey1"))
48-
val actual2 = branch.getRootNode().getPropertyValue(IProperty.fromName("metaKey2"))
49-
50-
assertEquals("metaValue1", actual1)
51-
assertEquals("metaValue2", actual2)
52-
}
53-
replicatedModel.dispose()
59+
fun `cross module references were synced`() = runTest { root ->
60+
val solution1Graph = checkNotNull(
61+
root.allChildren
62+
.find { it.getPropertyValue(BuiltinLanguages.jetbrains_mps_lang_core.INamedConcept.name) == "GraphSolution" }
63+
?.getDescendants(false)
64+
?.find { it.getConceptReference() == ConceptReference(_C_UntypedImpl_Graph.getUID()) },
65+
)
66+
67+
val solution2Graph = checkNotNull(
68+
root.allChildren
69+
.find { it.getPropertyValue(BuiltinLanguages.jetbrains_mps_lang_core.INamedConcept.name) == "GraphSolution2" }
70+
?.getDescendants(false)
71+
?.find { it.getConceptReference() == ConceptReference(_C_UntypedImpl_Graph.getUID()) },
72+
)
73+
assertEquals(solution1Graph, solution2Graph.getReferenceTarget(C_Graph.relatedGraph))
5474
}
5575
}

bulk-model-sync-gradle-test/test-repo/.mps/modules.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
<projectModules>
55
<modulePath path="$PROJECT_DIR$/languages/GraphLang/GraphLang.mpl" folder="" />
66
<modulePath path="$PROJECT_DIR$/solutions/GraphSolution/GraphSolution.msd" folder="" />
7+
<modulePath path="$PROJECT_DIR$/solutions/GraphSolution2/GraphSolution2.msd" folder="my.virtual.folder" />
78
</projectModules>
89
</component>
910
</project>

bulk-model-sync-gradle-test/test-repo/languages/GraphLang/GraphLang.mpl

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,7 @@
2424
</facet>
2525
</facets>
2626
<external-templates />
27-
<languageVersions>
28-
<language slang="l:f3061a53-9226-4cc5-a443-f952ceaf5816:jetbrains.mps.baseLanguage" version="11" />
29-
<language slang="l:fd392034-7849-419d-9071-12563d152375:jetbrains.mps.baseLanguage.closures" version="0" />
30-
<language slang="l:83888646-71ce-4f1c-9c53-c54016f6ad4f:jetbrains.mps.baseLanguage.collections" version="1" />
31-
<language slang="l:f2801650-65d5-424e-bb1b-463a8781b786:jetbrains.mps.baseLanguage.javadoc" version="2" />
32-
<language slang="l:760a0a8c-eabb-4521-8bfd-65db761a9ba3:jetbrains.mps.baseLanguage.logging" version="0" />
33-
<language slang="l:a247e09e-2435-45ba-b8d2-07e93feba96a:jetbrains.mps.baseLanguage.tuples" version="0" />
34-
<language slang="l:ceab5195-25ea-4f22-9b92-103b95ca8c0c:jetbrains.mps.lang.core" version="2" />
35-
<language slang="l:b401a680-8325-4110-8fd3-84331ff25bef:jetbrains.mps.lang.generator" version="4" />
36-
<language slang="l:d7706f63-9be2-479c-a3da-ae92af1e64d5:jetbrains.mps.lang.generator.generationContext" version="2" />
37-
<language slang="l:289fcc83-6543-41e8-a5ca-768235715ce4:jetbrains.mps.lang.generator.generationParameters" version="0" />
38-
<language slang="l:446c26eb-2b7b-4bf0-9b35-f83fa582753e:jetbrains.mps.lang.modelapi" version="0" />
39-
<language slang="l:3a13115c-633c-4c5c-bbcc-75c4219e9555:jetbrains.mps.lang.quotation" version="5" />
40-
<language slang="l:13744753-c81f-424a-9c1b-cf8943bf4e86:jetbrains.mps.lang.sharedConcepts" version="0" />
41-
<language slang="l:7866978e-a0f0-4cc7-81bc-4d213d9375e1:jetbrains.mps.lang.smodel" version="19" />
42-
<language slang="l:c7fb639f-be78-4307-89b0-b5959c3fa8c8:jetbrains.mps.lang.text" version="0" />
43-
<language slang="l:9ded098b-ad6a-4657-bfd9-48636cfe8bc3:jetbrains.mps.lang.traceable" version="0" />
44-
</languageVersions>
27+
<languageVersions />
4528
<dependencyVersions>
4629
<module reference="3f233e7f-b8a6-46d2-a57f-795d56775243(Annotations)" version="0" />
4730
<module reference="d5dabe27-fe41-4a5d-92bb-aede71707287(GraphLang)" version="0" />

bulk-model-sync-gradle-test/test-repo/languages/GraphLang/models/GraphLang.editor.mps

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@
8585
<node concept="3F0ifn" id="pSCM1J8BUq" role="3EZMnx">
8686
<property role="3F0ifm" value="graph:" />
8787
</node>
88+
<node concept="3F0A7n" id="27XSKLmUjrz" role="3EZMnx">
89+
<ref role="1NtTu8" to="tpck:h0TrG11" resolve="name" />
90+
</node>
8891
<node concept="3F0ifn" id="pSCM1J8CVd" role="3EZMnx">
8992
<property role="3F0ifm" value="nodes:" />
9093
<node concept="pVoyu" id="pSCM1J8CVg" role="3F10Kt">
@@ -121,6 +124,21 @@
121124
<property role="VOm3f" value="true" />
122125
</node>
123126
</node>
127+
<node concept="3F0ifn" id="27XSKLmUmXu" role="3EZMnx">
128+
<property role="3F0ifm" value="related graph:" />
129+
<node concept="pVoyu" id="27XSKLmUmXK" role="3F10Kt">
130+
<property role="VOm3f" value="true" />
131+
</node>
132+
</node>
133+
<node concept="1iCGBv" id="27XSKLmUmYZ" role="3EZMnx">
134+
<ref role="1NtTu8" to="7quj:27XSKLmUjrO" resolve="relatedGraph" />
135+
<node concept="1sVBvm" id="27XSKLmUmZ1" role="1sWHZn">
136+
<node concept="3F0A7n" id="27XSKLmUmZp" role="2wV5jI">
137+
<property role="1Intyy" value="true" />
138+
<ref role="1NtTu8" to="tpck:h0TrG11" resolve="name" />
139+
</node>
140+
</node>
141+
</node>
124142
</node>
125143
</node>
126144
<node concept="24kQdi" id="pSCM1J8zlz">

bulk-model-sync-gradle-test/test-repo/languages/GraphLang/models/GraphLang.structure.mps

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@
5555
<property role="20lbJX" value="fLJekj5/_0__n" />
5656
<ref role="20lvS9" node="pSCM1J8wHk" resolve="Node" />
5757
</node>
58+
<node concept="PrWs8" id="27XSKLmUjrh" role="PzmwI">
59+
<ref role="PrY4T" to="tpck:h0TrEE$" resolve="INamedConcept" />
60+
</node>
61+
<node concept="1TJgyj" id="27XSKLmUjrO" role="1TKVEi">
62+
<property role="IQ2ns" value="2449363414496655092" />
63+
<property role="20kJfa" value="relatedGraph" />
64+
<ref role="20lvS9" node="pSCM1J8wHi" resolve="Graph" />
65+
</node>
5866
</node>
5967
<node concept="1TIwiD" id="pSCM1J8wHk">
6068
<property role="EcuMT" value="466301921131629396" />

bulk-model-sync-gradle-test/test-repo/solutions/GraphSolution/models/GraphSolution.example.mps

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
</language>
2525
</registry>
2626
<node concept="1DmExM" id="pSCM1J8y9y">
27+
<property role="TrG5h" value="GraphFromSolution1" />
2728
<node concept="1DmExR" id="pSCM1J8Fg1" role="1DmEKd">
2829
<ref role="1DmyQl" node="pSCM1J8FfW" resolve="A" />
2930
<ref role="1DmyQm" node="pSCM1J8FfX" resolve="B" />
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<solution name="GraphSolution2" uuid="b7c9b13c-dc94-4376-b1eb-5e1ceb88f2ba" moduleVersion="0" compileInMPS="true">
3+
<models>
4+
<modelRoot contentPath="${module}" type="default">
5+
<sourceRoot location="models" />
6+
</modelRoot>
7+
</models>
8+
<facets>
9+
<facet type="java">
10+
<classes generated="true" path="${module}/classes_gen" />
11+
</facet>
12+
</facets>
13+
<sourcePath />
14+
<dependencies>
15+
<dependency reexport="false">e2eb2820-068e-4954-826e-d3a02c70ecc5(GraphSolution)</dependency>
16+
<dependency reexport="false">d5dabe27-fe41-4a5d-92bb-aede71707287(GraphLang)</dependency>
17+
</dependencies>
18+
<languageVersions>
19+
<language slang="l:d5dabe27-fe41-4a5d-92bb-aede71707287:GraphLang" version="0" />
20+
<language slang="l:f3061a53-9226-4cc5-a443-f952ceaf5816:jetbrains.mps.baseLanguage" version="11" />
21+
<language slang="l:443f4c36-fcf5-4eb6-9500-8d06ed259e3e:jetbrains.mps.baseLanguage.classifiers" version="0" />
22+
<language slang="l:fd392034-7849-419d-9071-12563d152375:jetbrains.mps.baseLanguage.closures" version="0" />
23+
<language slang="l:83888646-71ce-4f1c-9c53-c54016f6ad4f:jetbrains.mps.baseLanguage.collections" version="1" />
24+
<language slang="l:f3347d8a-0e79-4f35-8ac9-1574f25c986f:jetbrains.mps.execution.commands" version="0" />
25+
<language slang="l:73c1a490-99fa-4d0d-8292-b8985697c74b:jetbrains.mps.execution.common" version="0" />
26+
<language slang="l:22e72e4c-0f69-46ce-8403-6750153aa615:jetbrains.mps.execution.configurations" version="2" />
27+
<language slang="l:756e911c-3f1f-4a48-bdf5-a2ceb91b723c:jetbrains.mps.execution.settings" version="0" />
28+
<language slang="l:4caf0310-491e-41f5-8a9b-2006b3a94898:jetbrains.mps.execution.util" version="0" />
29+
<language slang="l:ceab5195-25ea-4f22-9b92-103b95ca8c0c:jetbrains.mps.lang.core" version="2" />
30+
<language slang="l:c72da2b9-7cce-4447-8389-f407dc1158b7:jetbrains.mps.lang.structure" version="9" />
31+
<language slang="l:9ded098b-ad6a-4657-bfd9-48636cfe8bc3:jetbrains.mps.lang.traceable" version="0" />
32+
</languageVersions>
33+
<dependencyVersions>
34+
<module reference="3f233e7f-b8a6-46d2-a57f-795d56775243(Annotations)" version="0" />
35+
<module reference="d5dabe27-fe41-4a5d-92bb-aede71707287(GraphLang)" version="0" />
36+
<module reference="e2eb2820-068e-4954-826e-d3a02c70ecc5(GraphSolution)" version="0" />
37+
<module reference="b7c9b13c-dc94-4376-b1eb-5e1ceb88f2ba(GraphSolution2)" version="0" />
38+
<module reference="6354ebe7-c22a-4a0f-ac54-50b52ab9b065(JDK)" version="0" />
39+
<module reference="6ed54515-acc8-4d1e-a16c-9fd6cfe951ea(MPS.Core)" version="0" />
40+
<module reference="8865b7a8-5271-43d3-884c-6fd1d9cfdd34(MPS.OpenAPI)" version="0" />
41+
<module reference="04b376d5-fc16-403b-a344-c68b30193c6a(jetbrains.mps.execution.library)" version="0" />
42+
<module reference="ceab5195-25ea-4f22-9b92-103b95ca8c0c(jetbrains.mps.lang.core)" version="0" />
43+
</dependencyVersions>
44+
</solution>

0 commit comments

Comments
 (0)