Skip to content

Commit a9762a9

Browse files
committed
add MappingsMergerTest
1 parent 481ad6d commit a9762a9

File tree

3 files changed

+314
-2
lines changed

3 files changed

+314
-2
lines changed

src/main/java/net/fabricmc/loom/configuration/providers/mappings/tiny/MappingsMerger.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.util.regex.Pattern;
3535

3636
import com.google.common.base.Stopwatch;
37+
import org.jetbrains.annotations.VisibleForTesting;
3738
import org.slf4j.Logger;
3839
import org.slf4j.LoggerFactory;
3940

@@ -62,7 +63,8 @@ public static void mergeAndSaveMappings(Path from, Path out, MinecraftProvider m
6263
LOGGER.info(":merged mappings in " + stopwatch.stop());
6364
}
6465

65-
private static void mergeAndSaveMappings(Path from, Path out, IntermediateMappingsService intermediateMappingsService) throws IOException {
66+
@VisibleForTesting
67+
public static void mergeAndSaveMappings(Path from, Path out, IntermediateMappingsService intermediateMappingsService) throws IOException {
6668
MemoryMappingTree intermediaryTree = new MemoryMappingTree();
6769
intermediateMappingsService.getMemoryMappingTree().accept(new MappingSourceNsSwitch(intermediaryTree, MappingsNamespace.INTERMEDIARY.toString()));
6870

@@ -82,7 +84,8 @@ private static void mergeAndSaveMappings(Path from, Path out, IntermediateMappin
8284
}
8385
}
8486

85-
private static void legacyMergeAndSaveMappings(Path from, Path out, IntermediateMappingsService intermediateMappingsService) throws IOException {
87+
@VisibleForTesting
88+
public static void legacyMergeAndSaveMappings(Path from, Path out, IntermediateMappingsService intermediateMappingsService) throws IOException {
8689
MemoryMappingTree intermediaryTree = new MemoryMappingTree();
8790
intermediateMappingsService.getMemoryMappingTree().accept(intermediaryTree);
8891

src/test/groovy/net/fabricmc/loom/test/unit/LoomMocks.groovy

+18
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424

2525
package net.fabricmc.loom.test.unit
2626

27+
import java.nio.file.Path
2728
import java.util.function.Function
2829

2930
import net.fabricmc.loom.configuration.providers.mappings.IntermediaryMappingsProvider
31+
import net.fabricmc.loom.configuration.providers.mappings.IntermediateMappingsService
3032
import net.fabricmc.loom.test.util.GradleTestUtil
3133
import net.fabricmc.loom.util.download.Download
3234

@@ -49,4 +51,20 @@ class LoomMocks {
4951
when(mock.getRefreshDeps()).thenReturn(refreshDeps)
5052
return mock
5153
}
54+
55+
static IntermediateMappingsService.Options intermediateMappingsServiceOptionsMock(Path intermediaryTiny, String expectedSrcNs) {
56+
def intermediaryTinyProperty = GradleTestUtil.mockProperty(intermediaryTiny)
57+
def expectedSrcNsProperty = GradleTestUtil.mockProperty(expectedSrcNs)
58+
59+
def mock = spy(IntermediateMappingsService.Options.class)
60+
when(mock.getIntermediaryTiny()).thenReturn(intermediaryTinyProperty)
61+
when(mock.getExpectedSrcNs()).thenReturn(expectedSrcNsProperty)
62+
return mock
63+
}
64+
65+
static IntermediateMappingsService intermediateMappingsServiceMock(IntermediateMappingsService.Options options) {
66+
def mock = spy(IntermediateMappingsService.class)
67+
when(mock.getOptions()).thenReturn(options)
68+
return mock
69+
}
5270
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
/*
2+
* This file is part of fabric-loom, licensed under the MIT License (MIT).
3+
*
4+
* Copyright (c) 2024 FabricMC
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
package net.fabricmc.loom.test.unit
26+
27+
import java.nio.file.Files
28+
import java.nio.file.Path
29+
30+
import spock.lang.TempDir
31+
32+
import net.fabricmc.loom.api.mappings.layered.MappingsNamespace
33+
import net.fabricmc.loom.configuration.providers.mappings.IntermediateMappingsService
34+
import net.fabricmc.loom.configuration.providers.mappings.tiny.MappingsMerger
35+
import net.fabricmc.mappingio.MappingReader
36+
import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch
37+
import net.fabricmc.mappingio.tree.MemoryMappingTree
38+
39+
import static org.junit.jupiter.api.Assertions.*
40+
41+
class MappingsMergerTest {
42+
@TempDir
43+
Path tempDir
44+
45+
def "mappings merger"() {
46+
given:
47+
Path intermediaryTiny = tempDir.resolve("intermediary.tiny")
48+
Path mappingsTiny = tempDir.resolve("mappings.tiny")
49+
Path mergedMappingsTiny = tempDir.resolve("merged_mappings.tiny")
50+
51+
Files.writeString(intermediaryTiny, INTERMEDIARY_MAPPINGS)
52+
Files.writeString(mappingsTiny, NAMED_MAPPINGS)
53+
54+
IntermediateMappingsService.Options intermediateMappingsServiceOptions = LoomMocks.intermediateMappingsServiceOptionsMock(intermediaryTiny, OFFICIAL)
55+
IntermediateMappingsService intermediateMappingsService = LoomMocks.intermediateMappingsServiceMock(intermediateMappingsServiceOptions)
56+
57+
when:
58+
MappingsMerger.mergeAndSaveMappings(mappingsTiny, mergedMappingsTiny, intermediateMappingsService)
59+
60+
def mappings = new MemoryMappingTree()
61+
MappingReader.read(mergedMappingsTiny, mappings)
62+
63+
then:
64+
mappings.srcNamespace == OFFICIAL
65+
mappings.dstNamespaces == [INTERMEDIARY, NAMED]
66+
def namedNs = mappings.getNamespaceId(NAMED)
67+
mappings.classes.size() == 2
68+
mappings.classes[0].srcName == "a"
69+
mappings.classes[0].getDstName(namedNs) == "net/fabricmc/loom/test/unit/ObfuscatedClass"
70+
mappings.classes[0].comment == "class comment"
71+
mappings.classes[0].fields.size() == 1
72+
mappings.classes[0].fields[0].srcName == "a"
73+
mappings.classes[0].fields[0].getDstDesc(namedNs) == "obfuscatedField"
74+
mappings.classes[0].fields[0].comment == "field comment"
75+
mappings.classes[0].methods.size() == 1
76+
mappings.classes[0].methods[0].srcName == "a"
77+
mappings.classes[0].methods[0].getDstDesc(namedNs) == "obfuscatedMethod"
78+
mappings.classes[0].methods[0].comment == "method comment"
79+
mappings.classes[0].methods[0].args.size() == 1
80+
mappings.classes[0].methods[1].args[0].getDstName(namedNs) == "obfuscatedMethodParameter"
81+
mappings.classes[1].srcName == "net/fabricmc/loom/test/unit/UnobfuscatedClass"
82+
mappings.classes[1].getDstName(namedNs) == "net/fabricmc/loom/test/unit/UnobfuscatedClass"
83+
mappings.classes[1].comment == "class comment"
84+
mappings.classes[1].fields.size() == 1
85+
mappings.classes[1].fields[0].srcName == "unobfuscatedField"
86+
mappings.classes[1].fields[0].getDstDesc(namedNs) == "unobfuscatedField"
87+
mappings.classes[1].fields[0].comment == "field comment"
88+
mappings.classes[1].methods.size() == 1
89+
mappings.classes[1].methods[0].srcName == "unobfuscatedMethod"
90+
mappings.classes[1].methods[0].getDstDesc(namedNs) == "unobfuscatedMethod"
91+
mappings.classes[1].methods[0].comment == "method comment"
92+
mappings.classes[1].methods[0].args.size() == 1
93+
mappings.classes[1].methods[1].args[0].getDstName(namedNs) == "unobfuscatedMethodParameter"
94+
}
95+
96+
def "mappings merger legacy"() {
97+
given:
98+
Path intermediaryTiny = tempDir.resolve("intermediary.tiny")
99+
Path mappingsTiny = tempDir.resolve("mappings.tiny")
100+
Path mergedMappingsTiny = tempDir.resolve("merged_mappings.tiny")
101+
102+
Files.writeString(intermediaryTiny, LEGACY_INTERMEDIARY_MAPPINGS)
103+
Files.writeString(mappingsTiny, LEGACY_NAMED_MAPPINGS)
104+
105+
IntermediateMappingsService.Options intermediateMappingsServiceOptions = LoomMocks.intermediateMappingsServiceOptionsMock(intermediaryTiny, INTERMEDIARY)
106+
IntermediateMappingsService intermediateMappingsService = LoomMocks.intermediateMappingsServiceMock(intermediateMappingsServiceOptions)
107+
108+
when:
109+
MappingsMerger.mergeAndSaveMappings(mappingsTiny, mergedMappingsTiny, intermediateMappingsService)
110+
111+
def mappings = new MemoryMappingTree()
112+
MappingReader.read(mergedMappingsTiny, mappings)
113+
114+
def clientMappings = new MemoryMappingTree()
115+
def serverMappings = new MemoryMappingTree()
116+
117+
mappings.accept(new MappingSourceNsSwitch(clientMappings, CLIENT_OFFICIAL, true))
118+
mappings.accept(new MappingSourceNsSwitch(serverMappings, SERVER_OFFICIAL, true))
119+
120+
then:
121+
clientMappings.srcNamespace == CLIENT_OFFICIAL
122+
clientMappings.dstNamespaces == [
123+
INTERMEDIARY,
124+
SERVER_OFFICIAL,
125+
NAMED
126+
]
127+
def clientNamedNs = clientMappings.getNamespaceId(NAMED)
128+
clientMappings.classes.size() == 3
129+
clientMappings.classes[0].srcName == "a"
130+
clientMappings.classes[0].getDstName(namedNs) == "net/fabricmc/loom/test/unit/CommonObfuscatedClass"
131+
clientMappings.classes[0].comment == "class comment"
132+
clientMappings.classes[0].fields.size() == 1
133+
clientMappings.classes[0].fields[0].srcName == "a"
134+
clientMappings.classes[0].fields[0].getDstDesc(namedNs) == "commonObfuscatedField"
135+
clientMappings.classes[0].fields[0].comment == "field comment"
136+
clientMappings.classes[0].methods.size() == 1
137+
clientMappings.classes[0].methods[0].srcName == "a"
138+
clientMappings.classes[0].methods[0].getDstDesc(namedNs) == "commonObfuscatedMethod"
139+
clientMappings.classes[0].methods[0].comment == "method comment"
140+
clientMappings.classes[0].methods[0].args.size() == 1
141+
clientMappings.classes[0].methods[1].args[0].getDstName(namedNs) == "commonObfuscatedMethodParameter"
142+
clientMappings.classes[1].srcName == "b"
143+
clientMappings.classes[1].getDstName(namedNs) == "net/fabricmc/loom/test/unit/ClientObfuscatedClass"
144+
clientMappings.classes[1].comment == "class comment"
145+
clientMappings.classes[1].fields.size() == 1
146+
clientMappings.classes[1].fields[0].srcName == "a"
147+
clientMappings.classes[1].fields[0].getDstDesc(namedNs) == "clientObfuscatedField"
148+
clientMappings.classes[1].fields[0].comment == "field comment"
149+
clientMappings.classes[1].methods.size() == 1
150+
clientMappings.classes[1].methods[0].srcName == "a"
151+
clientMappings.classes[1].methods[0].getDstDesc(namedNs) == "clientObfuscatedMethod"
152+
clientMappings.classes[1].methods[0].comment == "method comment"
153+
clientMappings.classes[1].methods[0].args.size() == 1
154+
clientMappings.classes[1].methods[1].args[0].getDstName(namedNs) == "clientObfuscatedMethodParameter"
155+
clientMappings.classes[2].srcName == "net/fabricmc/loom/test/unit/UnobfuscatedClass"
156+
clientMappings.classes[2].getDstName(namedNs) == "net/fabricmc/loom/test/unit/UnobfuscatedClass"
157+
clientMappings.classes[2].comment == "class comment"
158+
clientMappings.classes[2].fields.size() == 1
159+
clientMappings.classes[2].fields[0].srcName == "unobfuscatedField"
160+
clientMappings.classes[2].fields[0].getDstDesc(namedNs) == "unobfuscatedField"
161+
clientMappings.classes[2].fields[0].comment == "field comment"
162+
clientMappings.classes[2].methods.size() == 1
163+
clientMappings.classes[2].methods[0].srcName == "unobfuscatedMethod"
164+
clientMappings.classes[2].methods[0].getDstDesc(namedNs) == "unobfuscatedMethod"
165+
clientMappings.classes[2].methods[0].comment == "method comment"
166+
clientMappings.classes[2].methods[0].args.size() == 1
167+
clientMappings.classes[2].methods[1].args[0].getDstName(namedNs) == "unobfuscatedMethodParameter"
168+
169+
serverMappings.srcNamespace == SERVER_OFFICIAL
170+
serverMappings.dstNamespaces == [
171+
INTERMEDIARY,
172+
CLIENT_OFFICIAL,
173+
NAMED
174+
]
175+
def serverNamedNs = serverMappings.getNamespaceId(NAMED)
176+
serverMappings.classes.size() == 3
177+
serverMappings.classes[0].srcName == "a"
178+
serverMappings.classes[0].getDstName(namedNs) == "net/fabricmc/loom/test/unit/CommonObfuscatedClass"
179+
serverMappings.classes[0].comment == "class comment"
180+
serverMappings.classes[0].fields.size() == 1
181+
serverMappings.classes[0].fields[0].srcName == "a"
182+
serverMappings.classes[0].fields[0].getDstDesc(namedNs) == "commonObfuscatedField"
183+
serverMappings.classes[0].fields[0].comment == "field comment"
184+
serverMappings.classes[0].methods.size() == 1
185+
serverMappings.classes[0].methods[0].srcName == "a"
186+
serverMappings.classes[0].methods[0].getDstDesc(namedNs) == "commonObfuscatedMethod"
187+
serverMappings.classes[0].methods[0].comment == "method comment"
188+
serverMappings.classes[0].methods[0].args.size() == 1
189+
serverMappings.classes[0].methods[1].args[0].getDstName(namedNs) == "commonObfuscatedMethodParameter"
190+
serverMappings.classes[1].srcName == "b"
191+
serverMappings.classes[1].getDstName(namedNs) == "net/fabricmc/loom/test/unit/ClientObfuscatedClass"
192+
serverMappings.classes[1].comment == "class comment"
193+
serverMappings.classes[1].fields.size() == 1
194+
serverMappings.classes[1].fields[0].srcName == "a"
195+
serverMappings.classes[1].fields[0].getDstDesc(namedNs) == "clientObfuscatedField"
196+
serverMappings.classes[1].fields[0].comment == "field comment"
197+
serverMappings.classes[1].methods.size() == 1
198+
serverMappings.classes[1].methods[0].srcName == "a"
199+
serverMappings.classes[1].methods[0].getDstDesc(namedNs) == "clientObfuscatedMethod"
200+
serverMappings.classes[1].methods[0].comment == "method comment"
201+
serverMappings.classes[1].methods[0].args.size() == 1
202+
serverMappings.classes[1].methods[1].args[0].getDstName(namedNs) == "clientObfuscatedMethodParameter"
203+
serverMappings.classes[2].srcName == "net/fabricmc/loom/test/unit/UnobfuscatedClass"
204+
serverMappings.classes[2].getDstName(namedNs) == "net/fabricmc/loom/test/unit/UnobfuscatedClass"
205+
serverMappings.classes[2].comment == "class comment"
206+
serverMappings.classes[2].fields.size() == 1
207+
serverMappings.classes[2].fields[0].srcName == "unobfuscatedField"
208+
serverMappings.classes[2].fields[0].getDstDesc(namedNs) == "unobfuscatedField"
209+
serverMappings.classes[2].fields[0].comment == "field comment"
210+
serverMappings.classes[2].methods.size() == 1
211+
serverMappings.classes[2].methods[0].srcName == "unobfuscatedMethod"
212+
serverMappings.classes[2].methods[0].getDstDesc(namedNs) == "unobfuscatedMethod"
213+
serverMappings.classes[2].methods[0].comment == "method comment"
214+
serverMappings.classes[2].methods[0].args.size() == 1
215+
serverMappings.classes[2].methods[1].args[0].getDstName(namedNs) == "unobfuscatedMethodParameter"
216+
}
217+
218+
private static final String OFFICIAL = MappingsNamespace.OFFICIAL.toString()
219+
private static final String CLIENT_OFFICIAL = MappingsNamespace.CLIENT_OFFICIAL.toString()
220+
private static final String SERVER_OFFICIAL = MappingsNamespace.SERVER_OFFICIAL.toString()
221+
private static final String INTERMEDIARY = MappingsNamespace.INTERMEDIARY.toString()
222+
private static final String NAMED = MappingsNamespace.NAMED.toString()
223+
224+
private static final String INTERMEDIARY_MAPPINGS = """
225+
tiny\t2\t0\tofficial\tintermediary
226+
c\ta\tclass_1
227+
\tf\tZ\ta\tfield_1
228+
\tm\t(Z)V\ta\tmethod_1
229+
""".trim()
230+
private static final String NAMED_MAPPINGS = """
231+
tiny\t2\t0\tintermediary\tnamed
232+
c\tclass_1\tnet/fabricmc/loom/test/unit/ObfuscatedClass
233+
\tc\tclass comment
234+
\tf\tZ\tfield_1\tobfuscatedField
235+
\t\tc\tfield comment
236+
\tm\t(Z)V\tmethod_1\tobfuscatedMethod
237+
\t\tc\tmethod comment
238+
\t\tp\t0\t\t\tobfuscatedMethodParameter
239+
c\tnet/fabricmc/loom/test/unit/UnobfuscatedClass\tnet/fabricmc/loom/test/unit/UnobfuscatedClass
240+
\tc\tclass comment
241+
\tf\tZ\tunobfuscatedField\tunobfuscatedField
242+
\t\tc\tfield comment
243+
\tm\t(Z)V\tunobfuscatedMethod\tunobfuscatedMethod
244+
\t\tc\tmethod comment
245+
\t\tp\t0\t\t\tunobfuscatedMethodParameter
246+
""".trim()
247+
248+
private static final String LEGACY_INTERMEDIARY_MAPPINGS = """
249+
tiny\t2\t0\tintermediary\tclientOfficial\tserverOfficial
250+
c\tclass_1\ta\ta
251+
\tf\tZ\tfield_1\ta\ta
252+
\tm\t(Z)V\tmethod_1\ta\ta
253+
c\tclass_2\tc\t
254+
\tf\tZ\tfield_2\ta\t
255+
\tm\t(Z)V\tmethod_2\ta\t
256+
c\tclass_3\t\tc
257+
\tf\tZ\tfield_3\t\ta
258+
\tm\t(Z)V\tmethod_3\t\ta
259+
""".trim()
260+
private static final String LEGACY_NAMED_MAPPINGS = """
261+
tiny\t2\t0\tintermediary\tnamed
262+
c\tclass_1\tnet/fabricmc/loom/test/unit/CommonObfuscatedClass
263+
\tc\tclass comment
264+
\tf\tZ\tfield_1\tcommonObfuscatedField
265+
\t\tc\tfield comment
266+
\tm\t(Z)V\tmethod_1\tcommonObfuscatedMethod
267+
\t\tc\tmethod comment
268+
\t\tp\t0\t\t\tcommonObfuscatedMethodParameter
269+
c\tclass_2\tnet/fabricmc/loom/test/unit/ClientObfuscatedClass
270+
\tc\tclass comment
271+
\tf\tZ\tfield_2\tclientObfuscatedField
272+
\t\tc\tfield comment
273+
\tm\t(Z)V\tmethod_2\tclientObfuscatedMethod
274+
\t\tc\tmethod comment
275+
\t\tp\t0\t\t\tclientObfuscatedMethodParameter
276+
c\tclass_3\tnet/fabricmc/loom/test/unit/ServerObfuscatedClass
277+
\tc\tclass comment
278+
\tf\tZ\tfield_3\tserverObfuscatedField
279+
\t\tc\tfield comment
280+
\tm\t(Z)V\tmethod_3\tserverObfuscatedMethod
281+
\t\tc\tmethod comment
282+
\t\tp\t0\t\t\tserverObfuscatedMethodParameter
283+
c\tnet/fabricmc/loom/test/unit/UnobfuscatedClass\tnet/fabricmc/loom/test/unit/UnobfuscatedClass
284+
\tc\tclass comment
285+
\tf\tZ\tunobfuscatedField\tunobfuscatedField
286+
\t\tc\tfield comment
287+
\tm\t(Z)V\tunobfuscatedMethod\tunobfuscatedMethod
288+
\t\tc\tmethod comment
289+
\t\tp\t0\t\t\tunobfuscatedMethodParameter
290+
""".trim()
291+
}

0 commit comments

Comments
 (0)