From 9913123843ed44b3e8178eb567a9874d648edc81 Mon Sep 17 00:00:00 2001 From: Julian Burner <48808497+NebelNidas@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:24:24 +0100 Subject: [PATCH] Make `OuterClassNamePropagator` configurable, refactor tests (#119) --- CHANGELOG.md | 4 +- build.gradle | 7 +- .../extras/MappingTreeRemapperTest.java | 4 +- .../mappingio/adapter/MappingNsCompleter.java | 26 +- .../adapter/OuterClassNamePropagator.java | 118 ++++- .../mappingio/format/MappingFormat.java | 42 +- .../mappingio/test/TestFileUpdater.java | 60 ++- .../fabricmc/mappingio/test/TestMappings.java | 466 ++++++++++++++++++ .../net/fabricmc/mappingio/test/TestUtil.java | 287 +---------- .../mappingio/test/lib/jool/Unchecked.java | 44 ++ .../fi/util/function/CheckedConsumer.java | 34 ++ ...ava => OuterClassNamePropagationTest.java} | 182 ++++--- .../test/tests/reading/DetectionTest.java | 96 +--- .../tests/reading/EmptyContentReadTest.java | 14 +- .../tests/reading/ValidContentReadTest.java | 210 ++------ .../mappingio/test/tests/tree/MergeTest.java | 4 +- .../test/tests/tree/MetadataTest.java | 4 +- .../test/tests/tree/SetNamespacesTest.java | 5 +- .../test/tests/visiting/VisitEndTest.java | 138 ++---- .../test/tests/writing/WriteTest.java | 153 ++---- .../test/visitors/SubsetAssertingVisitor.java | 15 +- .../propagated-except-remapped-dst/csrg.csrg | 6 + .../enigma-dir/class1Ns0Rename.mapping | 6 + .../enigma.mappings | 6 + .../propagated-except-remapped-dst/jam.jam | 6 + .../propagated-except-remapped-dst/jobf.jobf | 6 + .../migration-map.xml | 8 + .../proguard.txt | 6 + .../recaf-simple.txt | 6 + .../propagated-except-remapped-dst/srg.srg | 6 + .../propagated-except-remapped-dst/tiny.tiny | 4 + .../tinyV2.tiny | 7 + .../propagated-except-remapped-dst/tsrg.tsrg | 6 + .../tsrgV2.tsrg | 4 + .../propagated-except-remapped-dst/xsrg.xsrg | 6 + .../propagated/csrg.csrg | 6 + .../enigma-dir/class1Ns0Rename.mapping | 6 + .../propagated/enigma.mappings | 6 + .../propagated/jam.jam | 6 + .../propagated/jobf.jobf | 6 + .../propagated/migration-map.xml | 8 + .../propagated/proguard.txt | 6 + .../propagated/recaf-simple.txt | 6 + .../propagated/srg.srg | 6 + .../propagated/tiny.tiny | 4 + .../propagated/tinyV2.tiny | 7 + .../propagated/tsrg.tsrg | 6 + .../propagated/tsrgV2.tsrg | 4 + .../propagated/xsrg.xsrg | 6 + .../unpropagated/csrg.csrg | 6 + .../enigma-dir/class1Ns0Rename.mapping | 2 + .../unpropagated/enigma-dir/class_1.mapping | 5 + .../unpropagated/enigma.mappings | 6 + .../unpropagated/jam.jam | 6 + .../unpropagated/jobf.jobf | 6 + .../unpropagated/migration-map.xml | 8 + .../unpropagated/proguard.txt | 6 + .../unpropagated/recaf-simple.txt | 6 + .../unpropagated/srg.srg | 6 + .../unpropagated/tiny.tiny | 4 + .../unpropagated/tinyV2.tiny | 7 + .../unpropagated/tsrg.tsrg | 6 + .../unpropagated/tsrgV2.tsrg | 4 + .../unpropagated/xsrg.xsrg | 6 + .../enigma-dir/class1Ns0Rename.mapping | 11 + .../package_3/class3Ns0Rename.mapping | 1 + 66 files changed, 1279 insertions(+), 896 deletions(-) create mode 100644 src/test/java/net/fabricmc/mappingio/test/TestMappings.java create mode 100644 src/test/java/net/fabricmc/mappingio/test/lib/jool/fi/util/function/CheckedConsumer.java rename src/test/java/net/fabricmc/mappingio/test/tests/{adapter/OuterClassNamePropagatorTest.java => OuterClassNamePropagationTest.java} (51%) create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/csrg.csrg create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/enigma-dir/class1Ns0Rename.mapping create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/enigma.mappings create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/jam.jam create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/jobf.jobf create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/migration-map.xml create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/proguard.txt create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/recaf-simple.txt create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/srg.srg create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tiny.tiny create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tinyV2.tiny create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tsrg.tsrg create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tsrgV2.tsrg create mode 100644 src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/xsrg.xsrg create mode 100644 src/test/resources/outer-class-name-propagation/propagated/csrg.csrg create mode 100644 src/test/resources/outer-class-name-propagation/propagated/enigma-dir/class1Ns0Rename.mapping create mode 100644 src/test/resources/outer-class-name-propagation/propagated/enigma.mappings create mode 100644 src/test/resources/outer-class-name-propagation/propagated/jam.jam create mode 100644 src/test/resources/outer-class-name-propagation/propagated/jobf.jobf create mode 100644 src/test/resources/outer-class-name-propagation/propagated/migration-map.xml create mode 100644 src/test/resources/outer-class-name-propagation/propagated/proguard.txt create mode 100644 src/test/resources/outer-class-name-propagation/propagated/recaf-simple.txt create mode 100644 src/test/resources/outer-class-name-propagation/propagated/srg.srg create mode 100644 src/test/resources/outer-class-name-propagation/propagated/tiny.tiny create mode 100644 src/test/resources/outer-class-name-propagation/propagated/tinyV2.tiny create mode 100644 src/test/resources/outer-class-name-propagation/propagated/tsrg.tsrg create mode 100644 src/test/resources/outer-class-name-propagation/propagated/tsrgV2.tsrg create mode 100644 src/test/resources/outer-class-name-propagation/propagated/xsrg.xsrg create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/csrg.csrg create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/enigma-dir/class1Ns0Rename.mapping create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/enigma-dir/class_1.mapping create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/enigma.mappings create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/jam.jam create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/jobf.jobf create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/migration-map.xml create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/proguard.txt create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/recaf-simple.txt create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/srg.srg create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/tiny.tiny create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/tinyV2.tiny create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/tsrg.tsrg create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/tsrgV2.tsrg create mode 100644 src/test/resources/outer-class-name-propagation/unpropagated/xsrg.xsrg create mode 100644 src/test/resources/reading/repeated-elements/enigma-dir/class1Ns0Rename.mapping create mode 100644 src/test/resources/reading/repeated-elements/enigma-dir/package_3/class3Ns0Rename.mapping diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e65c482..6561443c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,9 +4,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +- Made `OuterClassNamePropagator` configurable +- Added a simplified `MappingNsCompleter` constructor for completing all destination names with the source names ## [0.7.1] - 2025-01-07 -- Restore the ability to read source-namespace-only mapping files, even if not spec-compliant +- Restored the ability to read source-namespace-only mapping files, even if not spec-compliant ## [0.7.0] - 2025-01-01 - Added IntelliJ IDEA migration map reader and writer diff --git a/build.gradle b/build.gradle index 05faff47..f80599e5 100644 --- a/build.gradle +++ b/build.gradle @@ -202,12 +202,7 @@ tasks.register("generateTestMappings", JavaExec) { dependsOn("testClasses") classpath = sourceSets.test.runtimeClasspath mainClass = 'net.fabricmc.mappingio.test.TestFileUpdater' -} - -tasks.register("updateTestMappings", Copy) { - dependsOn("generateTestMappings") - from 'build/resources/test/' - into 'src/test/resources/' + args = [file('src/test/resources/').getAbsolutePath()] } // A task to ensure that the version being released has not already been released. diff --git a/mapping-io-extras/src/test/java/net/fabricmc/mappingio/extras/MappingTreeRemapperTest.java b/mapping-io-extras/src/test/java/net/fabricmc/mappingio/extras/MappingTreeRemapperTest.java index 587fb8e6..90213e1f 100644 --- a/mapping-io-extras/src/test/java/net/fabricmc/mappingio/extras/MappingTreeRemapperTest.java +++ b/mapping-io-extras/src/test/java/net/fabricmc/mappingio/extras/MappingTreeRemapperTest.java @@ -25,7 +25,7 @@ import org.junit.jupiter.api.Test; import org.objectweb.asm.Type; -import net.fabricmc.mappingio.test.TestUtil; +import net.fabricmc.mappingio.test.TestMappings; import net.fabricmc.mappingio.tree.MappingTree; import net.fabricmc.mappingio.tree.MappingTree.ClassMapping; import net.fabricmc.mappingio.tree.MappingTree.FieldMapping; @@ -50,7 +50,7 @@ public class MappingTreeRemapperTest { @BeforeAll public static void setup() throws IOException { - mappingTree = TestUtil.acceptTestMappings(new MemoryMappingTree()); + mappingTree = TestMappings.generateValid(new MemoryMappingTree()); srcNs = mappingTree.getSrcNamespace(); dstNs = mappingTree.getDstNamespaces().get(0); diff --git a/src/main/java/net/fabricmc/mappingio/adapter/MappingNsCompleter.java b/src/main/java/net/fabricmc/mappingio/adapter/MappingNsCompleter.java index 275ab9ef..294721a7 100644 --- a/src/main/java/net/fabricmc/mappingio/adapter/MappingNsCompleter.java +++ b/src/main/java/net/fabricmc/mappingio/adapter/MappingNsCompleter.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -34,20 +35,31 @@ * This visitor fills in these "holes" by copying names from another namespace. */ public final class MappingNsCompleter extends ForwardingMappingVisitor { + /** + * Constructs a new {@link MappingNsCompleter} which completes all destination namespaces. + * + * @param next The next visitor to forward the data to. + */ + public MappingNsCompleter(MappingVisitor next) { + this(next, null, false); + } + /** * @param next The next visitor to forward the data to. * @param alternatives A map of which namespaces should copy from which others. + * Passing {@code null} causes all destination namespaces to be completed. */ - public MappingNsCompleter(MappingVisitor next, Map alternatives) { + public MappingNsCompleter(MappingVisitor next, @Nullable Map alternatives) { this(next, alternatives, false); } /** * @param next The next visitor to forward the data to. * @param alternatives A map of which namespaces should copy from which others. + * Passing {@code null} causes all destination namespaces to be completed. * @param addMissingNs Whether to copy namespaces from the alternatives key set if not already present. */ - public MappingNsCompleter(MappingVisitor next, Map alternatives, boolean addMissingNs) { + public MappingNsCompleter(MappingVisitor next, @Nullable Map alternatives, boolean addMissingNs) { super(next); this.alternatives = alternatives; @@ -63,6 +75,14 @@ public boolean visitHeader() throws IOException { @Override public void visitNamespaces(String srcNamespace, List dstNamespaces) throws IOException { + if (alternatives == null) { + alternatives = new HashMap<>(dstNamespaces.size()); + + for (String ns : dstNamespaces) { + alternatives.put(ns, srcNamespace); + } + } + if (addMissingNs) { boolean copied = false; @@ -192,8 +212,8 @@ public boolean visitElementContent(MappedElementKind targetKind) throws IOExcept return next.visitElementContent(targetKind); } - private final Map alternatives; private final boolean addMissingNs; + private Map alternatives; private int[] alternativesMapping; private String srcName; diff --git a/src/main/java/net/fabricmc/mappingio/adapter/OuterClassNamePropagator.java b/src/main/java/net/fabricmc/mappingio/adapter/OuterClassNamePropagator.java index 7e17807c..2ee89027 100644 --- a/src/main/java/net/fabricmc/mappingio/adapter/OuterClassNamePropagator.java +++ b/src/main/java/net/fabricmc/mappingio/adapter/OuterClassNamePropagator.java @@ -17,7 +17,9 @@ package net.fabricmc.mappingio.adapter; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; @@ -34,8 +36,9 @@ import net.fabricmc.mappingio.MappingVisitor; /** - * Searches for inner classes with no mapped name, whose enclosing classes do have mapped names, - * and applies those to the outer part of the inner classes' fully qualified name. + * Searches for inner classes whose effective destination name contains outer classes referenced via their source name, + * waits for mappings for these enclosing classes, and applies the latters' destination names + * to the formers' fully qualified name. * *

For example, it takes a class {@code class_1$class_2} that doesn't have a mapping, * tries to find {@code class_1}, which let's say has the mapping {@code SomeClass}, @@ -45,8 +48,24 @@ * the other to actually apply the outer names. The third pass onwards will then emit the final mappings. */ public class OuterClassNamePropagator extends ForwardingMappingVisitor { + /** + * Constructs a new {@link OuterClassNamePropagator} which processes all destination namespaces, + * including already remapped class destination names therein. + */ public OuterClassNamePropagator(MappingVisitor next) { + this(next, null, true); + } + + /** + * Constructs a new {@link OuterClassNamePropagator} which processes the selected destination namespaces. + * + * @param namespaces The destination namespaces where outer class names shall be propagated. Pass {@code null} to process all destination namespaces. + * @param processRemappedDstNames Whether already remapped destination names should also get their unmapped outer classes replaced. + */ + public OuterClassNamePropagator(MappingVisitor next, @Nullable Collection namespaces, boolean processRemappedDstNames) { super(next); + this.dstNamespacesToProcess = namespaces; + this.processRemappedDstNames = processRemappedDstNames; } @Override @@ -60,7 +79,7 @@ public Set getFlags() { @Override public boolean visitHeader() throws IOException { - if (pass < firstEmitPass) return true; + if (pass < FIST_EMIT_PASS) return true; return super.visitHeader(); } @@ -68,26 +87,53 @@ public boolean visitHeader() throws IOException { @Override @SuppressWarnings("unchecked") public void visitNamespaces(String srcNamespace, List dstNamespaces) throws IOException { - dstNsCount = dstNamespaces.size(); + if (pass == COLLECT_CLASSES_PASS) { + if (dstNamespacesToProcess == null) { + dstNamespacesToProcess = dstNamespaces; + } else { + if (dstNamespacesToProcess.contains(srcNamespace)) { + throw new UnsupportedOperationException(srcNamespace + " was passed as a destination namespace" + + " to propagate outer class names in, but has been visited as the source namespace."); + } + + for (String ns : dstNamespacesToProcess) { + if (!dstNamespaces.contains(ns)) { + throw new IllegalArgumentException(ns + " was passed as a destination namespace to propagate outer class names in," + + " but is not present in the namespaces of the current visitation pass."); + } + } + } + + this.dstNamespaces = dstNamespaces; + this.dstNsCount = dstNamespaces.size(); + + if (dstNamespaceIndicesToProcess == null) { + dstNamespaceIndicesToProcess = new ArrayList<>(); + + for (int i = 0; i < dstNsCount; i++) { + if (dstNamespacesToProcess.contains(dstNamespaces.get(i))) { + dstNamespaceIndicesToProcess.add(i); + } + } + } - if (pass == collectClassesPass) { visitedDstName = new boolean[dstNsCount]; dstNameBySrcNameByNamespace = new HashMap[dstNsCount]; - } else if (pass >= firstEmitPass) { + } else if (pass >= FIST_EMIT_PASS) { super.visitNamespaces(srcNamespace, dstNamespaces); } } @Override public void visitMetadata(String key, @Nullable String value) throws IOException { - if (pass < firstEmitPass) return; + if (pass < FIST_EMIT_PASS) return; super.visitMetadata(key, value); } @Override public boolean visitContent() throws IOException { - if (pass < firstEmitPass) return true; + if (pass < FIST_EMIT_PASS) return true; return super.visitContent(); } @@ -96,9 +142,9 @@ public boolean visitContent() throws IOException { public boolean visitClass(String srcName) throws IOException { this.srcName = srcName; - if (pass == collectClassesPass) { + if (pass == COLLECT_CLASSES_PASS) { dstNamesBySrcName.putIfAbsent(srcName, new String[dstNsCount]); - } else if (pass >= firstEmitPass) { + } else if (pass >= FIST_EMIT_PASS) { super.visitClass(srcName); } @@ -107,11 +153,11 @@ public boolean visitClass(String srcName) throws IOException { @Override public void visitDstName(MappedElementKind targetKind, int namespace, String name) throws IOException { - if (pass == collectClassesPass) { + if (pass == COLLECT_CLASSES_PASS) { if (targetKind != MappedElementKind.CLASS) return; dstNamesBySrcName.get(srcName)[namespace] = name; - } else if (pass >= firstEmitPass) { + } else if (pass >= FIST_EMIT_PASS) { if (targetKind == MappedElementKind.CLASS) { visitedDstName[namespace] = true; name = dstNamesBySrcName.get(srcName)[namespace]; @@ -123,7 +169,7 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam @Override public void visitDstDesc(MappedElementKind targetKind, int namespace, String desc) throws IOException { - if (pass < firstEmitPass) return; + if (pass < FIST_EMIT_PASS) return; if (modifiedClasses.contains(srcName)) { Map nsDstNameBySrcName = dstNameBySrcNameByNamespace[namespace]; @@ -143,23 +189,37 @@ public void visitDstDesc(MappedElementKind targetKind, int namespace, String des @Override public boolean visitElementContent(MappedElementKind targetKind) throws IOException { - if (targetKind == MappedElementKind.CLASS && pass > collectClassesPass) { + if (targetKind == MappedElementKind.CLASS && pass > COLLECT_CLASSES_PASS) { String[] dstNames = dstNamesBySrcName.get(srcName); for (int ns = 0; ns < dstNames.length; ns++) { + if (!dstNamespacesToProcess.contains(dstNamespaces.get(ns))) { + continue; + } + String dstName = dstNames[ns]; - if (pass == fixOuterClassesPass) { - if (dstName != null) continue; // skip if already mapped + if (pass == FIX_OUTER_CLASSES_PASS) { + if (!processRemappedDstNames && dstName != null && !dstName.equals(srcName)) { + continue; + } + + String[] srcParts = srcName.split(Pattern.quote("$")); + String[] dstParts = dstName == null ? srcParts : dstName.split(Pattern.quote("$")); + assert dstParts.length == srcParts.length; - String[] parts = srcName.split(Pattern.quote("$")); + for (int pos = srcParts.length - 2; pos >= 0; pos--) { + String outerSrcName = String.join("$", Arrays.copyOfRange(srcParts, 0, pos + 1)); + + if (dstName != null && !dstParts[pos].equals(srcParts[pos])) { + // That part already has a different mapping + continue; + } - for (int pos = parts.length - 2; pos >= 0; pos--) { - String outerSrcName = String.join("$", Arrays.copyOfRange(parts, 0, pos + 1)); String outerDstName = dstNamesBySrcName.get(outerSrcName)[ns]; - if (outerDstName != null) { - dstName = outerDstName + "$" + String.join("$", Arrays.copyOfRange(parts, pos + 1, parts.length)); + if (outerDstName != null && !outerDstName.equals(outerSrcName)) { + dstName = outerDstName + "$" + String.join("$", Arrays.copyOfRange(dstParts, pos + 1, dstParts.length)); dstNames[ns] = dstName; modifiedClasses.add(srcName); @@ -176,7 +236,7 @@ public boolean visitElementContent(MappedElementKind targetKind) throws IOExcept } } - if (pass < firstEmitPass) { + if (pass < FIST_EMIT_PASS) { return false; // prevent other element visits, we only care about classes here } @@ -186,18 +246,24 @@ public boolean visitElementContent(MappedElementKind targetKind) throws IOExcept @Override public boolean visitEnd() throws IOException { - if (pass++ < firstEmitPass) { + if (pass++ < FIST_EMIT_PASS) { return false; } return super.visitEnd(); } - private static final int collectClassesPass = 1; - private static final int fixOuterClassesPass = 2; - private static final int firstEmitPass = 3; + private static final int COLLECT_CLASSES_PASS = 1; + private static final int FIX_OUTER_CLASSES_PASS = 2; + private static final int FIST_EMIT_PASS = 3; + private final boolean processRemappedDstNames; private final Map dstNamesBySrcName = new HashMap<>(); private final Set modifiedClasses = new HashSet<>(); + private String srcNamespaceToProcess; + private int srcNsId; + private List dstNamespaces; + private Collection dstNamespacesToProcess; + private Collection dstNamespaceIndicesToProcess; private int pass = 1; private int dstNsCount = -1; private String srcName; diff --git a/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java b/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java index 6f8e8416..b281ce36 100644 --- a/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java +++ b/src/main/java/net/fabricmc/mappingio/format/MappingFormat.java @@ -114,6 +114,27 @@ public enum MappingFormat { */ ENIGMA_DIR("Enigma directory", null, true, FeatureSetBuilder.createFrom(ENIGMA_FILE.features)), + /** + * ProGuard's mapping format, as specified here. + * + * @implNote Line numbers are currently not supported. + */ + PROGUARD_FILE("ProGuard file", "txt", true, FeatureSetBuilder.create() + .withElementMetadata(MetadataSupport.FIXED) // line numbers + .withClasses(c -> c + .withSrcNames(FeaturePresence.REQUIRED) + .withDstNames(FeaturePresence.REQUIRED) + .withRepackaging(true)) + .withFields(f -> f + .withSrcNames(FeaturePresence.REQUIRED) + .withDstNames(FeaturePresence.REQUIRED) + .withSrcDescs(FeaturePresence.REQUIRED)) + .withMethods(m -> m + .withSrcNames(FeaturePresence.REQUIRED) + .withDstNames(FeaturePresence.REQUIRED) + .withSrcDescs(FeaturePresence.REQUIRED)) + .withFileComments(true)), + /** * The {@code SRG} ("Searge RetroGuard") mapping format, as specified here. * @@ -198,27 +219,6 @@ public enum MappingFormat { .withSrcNames(FeaturePresence.REQUIRED) .withDstNames(FeaturePresence.REQUIRED))), - /** - * ProGuard's mapping format, as specified here. - * - * @implNote Line numbers are currently not supported. - */ - PROGUARD_FILE("ProGuard file", "txt", true, FeatureSetBuilder.create() - .withElementMetadata(MetadataSupport.FIXED) // line numbers - .withClasses(c -> c - .withSrcNames(FeaturePresence.REQUIRED) - .withDstNames(FeaturePresence.REQUIRED) - .withRepackaging(true)) - .withFields(f -> f - .withSrcNames(FeaturePresence.REQUIRED) - .withDstNames(FeaturePresence.REQUIRED) - .withSrcDescs(FeaturePresence.REQUIRED)) - .withMethods(m -> m - .withSrcNames(FeaturePresence.REQUIRED) - .withDstNames(FeaturePresence.REQUIRED) - .withSrcDescs(FeaturePresence.REQUIRED)) - .withFileComments(true)), - /** * The IntelliJ IDEA migration map format, as implemented here. * diff --git a/src/test/java/net/fabricmc/mappingio/test/TestFileUpdater.java b/src/test/java/net/fabricmc/mappingio/test/TestFileUpdater.java index b3e7597d..6da855c1 100644 --- a/src/test/java/net/fabricmc/mappingio/test/TestFileUpdater.java +++ b/src/test/java/net/fabricmc/mappingio/test/TestFileUpdater.java @@ -17,31 +17,67 @@ package net.fabricmc.mappingio.test; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Comparator; +import java.util.stream.Stream; +import net.fabricmc.mappingio.MappingVisitor; import net.fabricmc.mappingio.MappingWriter; +import net.fabricmc.mappingio.adapter.MappingNsCompleter; import net.fabricmc.mappingio.format.MappingFormat; +import net.fabricmc.mappingio.test.TestMappings.MappingDir; +import net.fabricmc.mappingio.test.lib.jool.Unchecked; public class TestFileUpdater { public static void main(String[] args) throws IOException { - for (MappingFormat format : MappingFormat.values()) { - if (!format.hasWriter) { + if (args.length == 1) { + TestUtil.setResourceRoot(mkDir(Paths.get(args[0]))); + } + + for (MappingDir dir : TestMappings.values()) { + if (!dir.supportsGeneration()) { continue; } - Path defaultPath = TestUtil.MappingDirs.VALID.resolve(TestUtil.getFileName(format)); - Path holesPath = TestUtil.MappingDirs.HOLES.resolve(TestUtil.getFileName(format)); - Path repeatPath = TestUtil.MappingDirs.REPEATED_ELEMENTS.resolve(TestUtil.getFileName(format)); + rmDir(dir.path()); + mkDir(dir.path()); + + for (MappingFormat format : MappingFormat.values()) { + if (!format.hasWriter) { + continue; + } + + MappingVisitor target = MappingWriter.create(dir.pathFor(format), format); - TestUtil.acceptTestMappings(MappingWriter.create(defaultPath, format)); - TestUtil.acceptTestMappingsWithHoles(MappingWriter.create(holesPath, format)); + if (dir == TestMappings.READING.REPEATED_ELEMENTS) { + boolean isEnigma = format == MappingFormat.ENIGMA_FILE || format == MappingFormat.ENIGMA_DIR; - if (format != MappingFormat.ENIGMA_DIR) { - TestUtil.acceptTestMappingsWithRepeats( - MappingWriter.create(repeatPath, format), - format != MappingFormat.ENIGMA_FILE, - format != MappingFormat.ENIGMA_FILE); + TestMappings.generateRepeatedElements(target, !isEnigma, !isEnigma); + continue; + } + + if (dir.isIn(TestMappings.PROPAGATION.BASE_DIR) && !format.features().hasNamespaces()) { + target = new MappingNsCompleter(target); + } + + dir.generate(target); } } } + + private static Path mkDir(Path path) throws IOException { + if (!Files.exists(path)) { + Files.createDirectories(path); + } + + return path; + } + + private static void rmDir(Path path) throws IOException { + try (Stream paths = Files.walk(path)) { + paths.sorted(Comparator.reverseOrder()).forEach(Unchecked.consumer(Files::deleteIfExists)); + } + } } diff --git a/src/test/java/net/fabricmc/mappingio/test/TestMappings.java b/src/test/java/net/fabricmc/mappingio/test/TestMappings.java new file mode 100644 index 00000000..d15c1964 --- /dev/null +++ b/src/test/java/net/fabricmc/mappingio/test/TestMappings.java @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2025 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.mappingio.test; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.jetbrains.annotations.Nullable; + +import net.fabricmc.mappingio.MappedElementKind; +import net.fabricmc.mappingio.MappingReader; +import net.fabricmc.mappingio.MappingUtil; +import net.fabricmc.mappingio.MappingVisitor; +import net.fabricmc.mappingio.adapter.ForwardingMappingVisitor; +import net.fabricmc.mappingio.adapter.OuterClassNamePropagator; +import net.fabricmc.mappingio.format.MappingFormat; +import net.fabricmc.mappingio.format.intellij.MigrationMapConstants; +import net.fabricmc.mappingio.test.lib.jool.Unchecked; +import net.fabricmc.mappingio.test.visitors.NopMappingVisitor; +import net.fabricmc.mappingio.test.visitors.VisitOrderVerifyingVisitor; + +/* + * After any changes to the "generate" methods, run the "generateTestMappings" Gradle task + * to update the mapping files located in the resources folder accordingly. + * + * Make sure to keep the manual Enigma and SRG changes in the "repeated-elements" directory. + */ +public class TestMappings { + public static T generateValid(T target) throws IOException { + MappingVisitor delegate = target instanceof VisitOrderVerifyingVisitor ? target : new VisitOrderVerifyingVisitor(target); + + if (delegate.visitHeader()) { + delegate.visitNamespaces(MappingUtil.NS_SOURCE_FALLBACK, Arrays.asList(MappingUtil.NS_TARGET_FALLBACK, MappingUtil.NS_TARGET_FALLBACK + "2")); + delegate.visitMetadata("name", "valid"); + delegate.visitMetadata(MigrationMapConstants.ORDER_KEY, "0"); + } + + if (delegate.visitContent()) { + int[] dstNs = new int[] { 0, 1 }; + NameGen nameGen = new NameGen(); + + if (nameGen.visitClass(delegate, dstNs)) { + nameGen.visitField(delegate, dstNs); + + if (nameGen.visitMethod(delegate, dstNs)) { + nameGen.visitMethodArg(delegate, dstNs); + nameGen.visitMethodVar(delegate, dstNs); + } + } + + if (nameGen.visitInnerClass(delegate, 1, dstNs)) { + nameGen.visitComment(delegate); + nameGen.visitField(delegate, dstNs); + } + + nameGen.visitClass(delegate, dstNs); + } + + if (!delegate.visitEnd()) { + generateValid(delegate); + } + + return target; + } + + public static T generateRepeatedElements(T target, boolean repeatComments, boolean repeatClasses) throws IOException { + generateValid(new ForwardingMappingVisitor(new VisitOrderVerifyingVisitor(target, true)) { + private final List replayQueue = new ArrayList<>(); + + @Override + public void visitMetadata(String key, @Nullable String value) throws IOException { + super.visitMetadata(key, key.equals("name") ? "repeated-elements" : value); + } + + @Override + public boolean visitClass(String srcName) throws IOException { + replayQueue.clear(); + + if (repeatClasses) { + replayQueue.add(Unchecked.runnable(() -> super.visitClass(srcName))); + } + + return super.visitClass(srcName); + } + + @Override + public boolean visitField(String srcName, @Nullable String srcDesc) throws IOException { + replayQueue.clear(); + replayQueue.add(Unchecked.runnable(() -> super.visitField(srcName, srcDesc))); + return super.visitField(srcName, srcDesc); + } + + @Override + public boolean visitMethod(String srcName, @Nullable String srcDesc) throws IOException { + replayQueue.clear(); + replayQueue.add(Unchecked.runnable(() -> super.visitMethod(srcName, srcDesc))); + return super.visitMethod(srcName, srcDesc); + } + + @Override + public boolean visitMethodArg(int lvIndex, int argIndex, String srcName) throws IOException { + replayQueue.clear(); + replayQueue.add(Unchecked.runnable(() -> super.visitMethodArg(lvIndex, argIndex, srcName))); + return super.visitMethodArg(lvIndex, argIndex, srcName); + } + + @Override + public boolean visitMethodVar(int lvIndex, int varIndex, int startOpIdx, int endOpIdx, String srcName) throws IOException { + replayQueue.clear(); + replayQueue.add(Unchecked.runnable(() -> super.visitMethodVar(lvIndex, varIndex, startOpIdx, endOpIdx, srcName))); + return super.visitMethodVar(lvIndex, varIndex, startOpIdx, endOpIdx, srcName); + } + + @Override + public void visitDstName(MappedElementKind targetKind, int namespace, String name) throws IOException { + if (targetKind == MappedElementKind.CLASS && !repeatClasses) { + super.visitDstName(targetKind, namespace, name); + } else { + replayQueue.add(Unchecked.runnable(() -> super.visitDstName(targetKind, namespace, name))); + super.visitDstName(targetKind, namespace, name + "0"); + } + } + + @Override + public void visitDstDesc(MappedElementKind targetKind, int namespace, String desc) throws IOException { + replayQueue.add(Unchecked.runnable(() -> super.visitDstDesc(targetKind, namespace, desc))); + super.visitDstDesc(targetKind, namespace, desc); + } + + @Override + public boolean visitElementContent(MappedElementKind targetKind) throws IOException { + boolean ret = super.visitElementContent(targetKind); + + if (!replayQueue.isEmpty()) { + replayQueue.forEach(Runnable::run); + + ret = super.visitElementContent(targetKind); + } + + return ret; + } + + @Override + public void visitComment(MappedElementKind targetKind, String comment) throws IOException { + if (repeatComments) { + super.visitComment(targetKind, comment + "."); + } + + super.visitComment(targetKind, comment); + } + }); + + return target; + } + + public static T generateHoles(T target) throws IOException { + MappingVisitor delegate = target instanceof VisitOrderVerifyingVisitor ? target : new VisitOrderVerifyingVisitor(target); + + if (delegate.visitHeader()) { + delegate.visitNamespaces(MappingUtil.NS_SOURCE_FALLBACK, Arrays.asList(MappingUtil.NS_TARGET_FALLBACK, MappingUtil.NS_TARGET_FALLBACK + "2")); + } + + if (delegate.visitContent()) { + NameGen nameGen = new NameGen(); + + // (Inner) Classes + for (int nestLevel = 0; nestLevel <= 2; nestLevel++) { + nameGen.visitClass(delegate); + nameGen.visitClass(delegate); + nameGen.visitInnerClass(delegate, nestLevel, 0); + nameGen.visitInnerClass(delegate, nestLevel, 1); + + if (nameGen.visitInnerClass(delegate, nestLevel)) { + nameGen.visitComment(delegate); + } + + if (nameGen.visitInnerClass(delegate, nestLevel, 0)) { + nameGen.visitComment(delegate); + } + + if (nameGen.visitInnerClass(delegate, nestLevel, 1)) { + nameGen.visitComment(delegate); + } + } + + if (nameGen.visitClass(delegate)) { + // Fields + nameGen.visitField(delegate); + nameGen.visitField(delegate, 0); + nameGen.visitField(delegate, 1); + + if (nameGen.visitField(delegate)) { + nameGen.visitComment(delegate); + } + + if (nameGen.visitField(delegate, 0)) { + nameGen.visitComment(delegate); + } + + if (nameGen.visitField(delegate, 1)) { + nameGen.visitComment(delegate); + } + + // Methods + nameGen.visitMethod(delegate); + nameGen.visitMethod(delegate, 0); + nameGen.visitMethod(delegate, 1); + + if (nameGen.visitMethod(delegate)) { + nameGen.visitComment(delegate); + } + + if (nameGen.visitMethod(delegate, 0)) { + nameGen.visitComment(delegate); + } + + if (nameGen.visitMethod(delegate, 1)) { + nameGen.visitComment(delegate); + } + + // Method args + if (nameGen.visitMethod(delegate)) { + nameGen.visitMethodArg(delegate); + nameGen.visitMethodArg(delegate, 1); + nameGen.visitMethodArg(delegate, 0); + + if (nameGen.visitMethodArg(delegate)) { + nameGen.visitComment(delegate); + } + + if (nameGen.visitMethodArg(delegate, 0)) { + nameGen.visitComment(delegate); + } + + if (nameGen.visitMethodArg(delegate, 1)) { + nameGen.visitComment(delegate); + } + } + + // Method vars + if (nameGen.visitMethod(delegate)) { + nameGen.visitMethodVar(delegate); + nameGen.visitMethodVar(delegate, 1); + nameGen.visitMethodVar(delegate, 0); + + if (nameGen.visitMethodVar(delegate)) { + nameGen.visitComment(delegate); + } + + if (nameGen.visitMethodVar(delegate, 0)) { + nameGen.visitComment(delegate); + } + + if (nameGen.visitMethodVar(delegate, 1)) { + nameGen.visitComment(delegate); + } + } + } + } + + if (!delegate.visitEnd()) { + generateHoles(delegate); + } + + return target; + } + + public static T generateOuterClassNamePropagation(T target) throws IOException { + MappingVisitor delegate = target instanceof VisitOrderVerifyingVisitor ? target : new VisitOrderVerifyingVisitor(target); + String srcNs = MappingUtil.NS_SOURCE_FALLBACK; + List dstNamespaces = Arrays.asList("dstNs0", "dstNs1", "dstNs2", "dstNs3", "dstNs4", "dstNs5", "dstNs6"); + + if (delegate.visitHeader()) { + delegate.visitNamespaces(srcNs, dstNamespaces); + } + + if (delegate.visitContent()) { + if (delegate.visitClass("class_1")) { + delegate.visitDstName(MappedElementKind.CLASS, 0, "class1Ns0Rename"); + delegate.visitDstName(MappedElementKind.CLASS, 1, "class1Ns1Rename"); + delegate.visitDstName(MappedElementKind.CLASS, 2, "class1Ns2Rename"); + delegate.visitDstName(MappedElementKind.CLASS, 4, "class1Ns4Rename"); + + if (delegate.visitElementContent(MappedElementKind.CLASS)) { + if (delegate.visitField("field_1", "Lclass_1;")) { + for (int i = 0; i <= 6; i++) { + delegate.visitDstDesc(MappedElementKind.FIELD, i, "Lclass_1;"); + } + + delegate.visitElementContent(MappedElementKind.FIELD); + } + } + } + + if (delegate.visitClass("class_1$class_2")) { + delegate.visitDstName(MappedElementKind.CLASS, 2, "class1Ns2Rename$class2Ns2Rename"); + delegate.visitDstName(MappedElementKind.CLASS, 3, "class_1$class2Ns3Rename"); + delegate.visitDstName(MappedElementKind.CLASS, 4, "class_1$class_2"); + delegate.visitDstName(MappedElementKind.CLASS, 5, "class_1$class2Ns5Rename"); + + if (delegate.visitElementContent(MappedElementKind.CLASS)) { + if (delegate.visitField("field_2", "Lclass_1$class_2;")) { + for (int i = 0; i <= 6; i++) { + delegate.visitDstDesc(MappedElementKind.FIELD, i, "Lclass_1$class_2;"); + } + + delegate.visitElementContent(MappedElementKind.FIELD); + } + } + } + + if (delegate.visitClass("class_1$class_2$class_3")) { + delegate.visitDstName(MappedElementKind.CLASS, 5, "class_1$class_2$class3Ns5Rename"); + delegate.visitDstName(MappedElementKind.CLASS, 6, "class_1$class_2$class3Ns6Rename"); + + if (delegate.visitElementContent(MappedElementKind.CLASS)) { + if (delegate.visitField("field_2", "Lclass_1$class_2$class_3;")) { + for (int i = 0; i <= 6; i++) { + delegate.visitDstDesc(MappedElementKind.FIELD, i, "Lclass_1$class_2$class_3;"); + } + + delegate.visitElementContent(MappedElementKind.FIELD); + } + } + } + } + + if (!delegate.visitEnd()) { + generateOuterClassNamePropagation(delegate); + } + + return target; + } + + private static MappingDir register(MappingDir dir) { + dirs.add(dir); + dirsByPath.put(dir.path, dir); + return dir; + } + + public static Set values() { + return Collections.unmodifiableSet(dirs); + } + + private static final Set dirs = new HashSet<>(); + private static final Map dirsByPath = new HashMap<>(); + + public static final MappingDir DETECTION = register(new MappingDir(TestUtil.getResource("/detection/")) { + public T generate(T target) throws IOException { + throw new UnsupportedOperationException(); + }; + }); + public static final Path MERGING = TestUtil.getResource("/merging/"); + + public static class READING { + public static final Path BASE_DIR = TestUtil.getResource("/reading/"); + + public static final MappingDir VALID = register(new MappingDir(BASE_DIR.resolve("valid/")) { + public T generate(T target) throws IOException { + return generateValid(target); + }; + }); + public static final MappingDir HOLES = register(new MappingDir(BASE_DIR.resolve("holes/")) { + public T generate(T target) throws IOException { + return generateHoles(target); + }; + }); + public static final MappingDir REPEATED_ELEMENTS = register(new MappingDir(BASE_DIR.resolve("repeated-elements/")) { + public T generate(T target) throws IOException { + return generateRepeatedElements(target, true, true); + }; + }); + } + + public static class PROPAGATION { + public static final Path BASE_DIR = TestUtil.getResource("/outer-class-name-propagation/"); + + public static final MappingDir UNPROPAGATED = register(new MappingDir(BASE_DIR.resolve("unpropagated/")) { + public T generate(T target) throws IOException { + return generateOuterClassNamePropagation(target); + }; + }); + public static final MappingDir PROPAGATED = register(new MappingDir(BASE_DIR.resolve("propagated/")) { + public T generate(T target) throws IOException { + generateOuterClassNamePropagation(new OuterClassNamePropagator(target)); + return target; + }; + }); + public static final MappingDir PROPAGATED_EXCEPT_REMAPPED_DST = register(new MappingDir(BASE_DIR.resolve("propagated-except-remapped-dst/")) { + public T generate(T target) throws IOException { + generateOuterClassNamePropagation(new OuterClassNamePropagator(target, null, false)); + return target; + }; + }); + } + + static { + // Force-load classes to ensure all MappingDirs are registered + READING.BASE_DIR.toString(); + PROPAGATION.BASE_DIR.toString(); + } + + public abstract static class MappingDir { + private final Path path; + private boolean supportsGeneration; + + private MappingDir(Path path) { + this.path = path; + + try { + generate(new NopMappingVisitor(false)); + supportsGeneration = true; + } catch (UnsupportedOperationException e) { + supportsGeneration = false; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + public Path path() { + return path; + } + + public Path pathFor(MappingFormat format) { + return path.resolve(TestUtil.getFileName(format)); + } + + public boolean isIn(Path path) { + return this.path.startsWith(path); + } + + public T read(MappingFormat format, T target) throws IOException { + MappingReader.read(pathFor(format), format, target); + return target; + } + + public boolean supportsGeneration() { + return supportsGeneration; + } + + public abstract T generate(T target) throws IOException; + } +} diff --git a/src/test/java/net/fabricmc/mappingio/test/TestUtil.java b/src/test/java/net/fabricmc/mappingio/test/TestUtil.java index 1e15bb57..321d5aa7 100644 --- a/src/test/java/net/fabricmc/mappingio/test/TestUtil.java +++ b/src/test/java/net/fabricmc/mappingio/test/TestUtil.java @@ -18,32 +18,36 @@ import java.io.IOException; import java.net.URISyntaxException; +import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import net.neoforged.srgutils.IMappingFile; import org.cadixdev.lorenz.io.MappingFormats; import org.jetbrains.annotations.Nullable; -import net.fabricmc.mappingio.MappedElementKind; -import net.fabricmc.mappingio.MappingUtil; -import net.fabricmc.mappingio.MappingVisitor; import net.fabricmc.mappingio.MappingWriter; -import net.fabricmc.mappingio.adapter.ForwardingMappingVisitor; import net.fabricmc.mappingio.format.MappingFormat; -import net.fabricmc.mappingio.format.intellij.MigrationMapConstants; -import net.fabricmc.mappingio.test.lib.jool.Unchecked; -import net.fabricmc.mappingio.test.visitors.VisitOrderVerifyingVisitor; import net.fabricmc.mappingio.tree.MappingTreeView; -import net.fabricmc.mappingio.tree.MemoryMappingTree; public final class TestUtil { + public static void setResourceRoot(Path path) { + resourceRoot = path; + } + public static Path getResource(String slashPrefixedResourcePath) { + if (resourceRoot != null) { + return resourceRoot.resolve(slashPrefixedResourcePath.substring(1)); + } + try { - return Paths.get(TestUtil.class.getResource(slashPrefixedResourcePath).toURI()); + URL url = TestUtil.class.getResource(slashPrefixedResourcePath); + + if (url == null) { + throw new IllegalArgumentException("Resource not found: " + slashPrefixedResourcePath); + } + + return Paths.get(url.toURI()); } catch (URISyntaxException e) { throw new RuntimeException(e); } @@ -151,262 +155,5 @@ public static Path writeToDir(MappingTreeView tree, Path dir, MappingFormat form return path; } - // After any changes, run "./gradlew updateTestMappings" to update the mapping files in the resources folder accordingly - public static T acceptTestMappings(T target) throws IOException { - MappingVisitor delegate = target instanceof VisitOrderVerifyingVisitor ? target : new VisitOrderVerifyingVisitor(target); - - if (delegate.visitHeader()) { - delegate.visitNamespaces(MappingUtil.NS_SOURCE_FALLBACK, Arrays.asList(MappingUtil.NS_TARGET_FALLBACK, MappingUtil.NS_TARGET_FALLBACK + "2")); - delegate.visitMetadata("name", "valid"); - delegate.visitMetadata(MigrationMapConstants.ORDER_KEY, "0"); - } - - if (delegate.visitContent()) { - int[] dstNs = new int[] { 0, 1 }; - NameGen nameGen = new NameGen(); - - if (nameGen.visitClass(delegate, dstNs)) { - nameGen.visitField(delegate, dstNs); - - if (nameGen.visitMethod(delegate, dstNs)) { - nameGen.visitMethodArg(delegate, dstNs); - nameGen.visitMethodVar(delegate, dstNs); - } - } - - if (nameGen.visitInnerClass(delegate, 1, dstNs)) { - nameGen.visitComment(delegate); - nameGen.visitField(delegate, dstNs); - } - - nameGen.visitClass(delegate, dstNs); - } - - if (!delegate.visitEnd()) { - acceptTestMappings(delegate); - } - - return target; - } - - // After any changes, run "./gradlew updateTestMappings" to update the mapping files in the resources folder accordingly. - // Make sure to keep the few manual changes in the files. - public static T acceptTestMappingsWithRepeats(T target, boolean repeatComments, boolean repeatClasses) throws IOException { - acceptTestMappings(new ForwardingMappingVisitor(new VisitOrderVerifyingVisitor(target, true)) { - private final List replayQueue = new ArrayList<>(); - - @Override - public void visitMetadata(String key, @Nullable String value) throws IOException { - super.visitMetadata(key, key.equals("name") ? "repeated-elements" : value); - } - - @Override - public boolean visitClass(String srcName) throws IOException { - replayQueue.clear(); - - if (repeatClasses) { - replayQueue.add(Unchecked.runnable(() -> super.visitClass(srcName))); - } - - return super.visitClass(srcName); - } - - @Override - public boolean visitField(String srcName, @Nullable String srcDesc) throws IOException { - replayQueue.clear(); - replayQueue.add(Unchecked.runnable(() -> super.visitField(srcName, srcDesc))); - return super.visitField(srcName, srcDesc); - } - - @Override - public boolean visitMethod(String srcName, @Nullable String srcDesc) throws IOException { - replayQueue.clear(); - replayQueue.add(Unchecked.runnable(() -> super.visitMethod(srcName, srcDesc))); - return super.visitMethod(srcName, srcDesc); - } - - @Override - public boolean visitMethodArg(int lvIndex, int argIndex, String srcName) throws IOException { - replayQueue.clear(); - replayQueue.add(Unchecked.runnable(() -> super.visitMethodArg(lvIndex, argIndex, srcName))); - return super.visitMethodArg(lvIndex, argIndex, srcName); - } - - @Override - public boolean visitMethodVar(int lvIndex, int varIndex, int startOpIdx, int endOpIdx, String srcName) throws IOException { - replayQueue.clear(); - replayQueue.add(Unchecked.runnable(() -> super.visitMethodVar(lvIndex, varIndex, startOpIdx, endOpIdx, srcName))); - return super.visitMethodVar(lvIndex, varIndex, startOpIdx, endOpIdx, srcName); - } - - @Override - public void visitDstName(MappedElementKind targetKind, int namespace, String name) throws IOException { - if (targetKind == MappedElementKind.CLASS && !repeatClasses) { - super.visitDstName(targetKind, namespace, name); - } else { - replayQueue.add(Unchecked.runnable(() -> super.visitDstName(targetKind, namespace, name))); - super.visitDstName(targetKind, namespace, name + "0"); - } - } - - @Override - public void visitDstDesc(MappedElementKind targetKind, int namespace, String desc) throws IOException { - replayQueue.add(Unchecked.runnable(() -> super.visitDstDesc(targetKind, namespace, desc))); - super.visitDstDesc(targetKind, namespace, desc); - } - - @Override - public boolean visitElementContent(MappedElementKind targetKind) throws IOException { - boolean ret = super.visitElementContent(targetKind); - - if (!replayQueue.isEmpty()) { - replayQueue.forEach(Runnable::run); - - ret = super.visitElementContent(targetKind); - } - - return ret; - } - - @Override - public void visitComment(MappedElementKind targetKind, String comment) throws IOException { - if (repeatComments) { - super.visitComment(targetKind, comment + "."); - } - - super.visitComment(targetKind, comment); - } - }); - - return target; - } - - // After any changes, run "./gradlew updateTestMappings" to update the mapping files in the resources folder accordingly - public static T acceptTestMappingsWithHoles(T target) throws IOException { - MappingVisitor delegate = target instanceof VisitOrderVerifyingVisitor ? target : new VisitOrderVerifyingVisitor(target); - - if (delegate.visitHeader()) { - delegate.visitNamespaces(MappingUtil.NS_SOURCE_FALLBACK, Arrays.asList(MappingUtil.NS_TARGET_FALLBACK, MappingUtil.NS_TARGET_FALLBACK + "2")); - } - - if (delegate.visitContent()) { - NameGen nameGen = new NameGen(); - - // (Inner) Classes - for (int nestLevel = 0; nestLevel <= 2; nestLevel++) { - nameGen.visitClass(delegate); - nameGen.visitClass(delegate); - nameGen.visitInnerClass(delegate, nestLevel, 0); - nameGen.visitInnerClass(delegate, nestLevel, 1); - - if (nameGen.visitInnerClass(delegate, nestLevel)) { - nameGen.visitComment(delegate); - } - - if (nameGen.visitInnerClass(delegate, nestLevel, 0)) { - nameGen.visitComment(delegate); - } - - if (nameGen.visitInnerClass(delegate, nestLevel, 1)) { - nameGen.visitComment(delegate); - } - } - - if (nameGen.visitClass(delegate)) { - // Fields - nameGen.visitField(delegate); - nameGen.visitField(delegate, 0); - nameGen.visitField(delegate, 1); - - if (nameGen.visitField(delegate)) { - nameGen.visitComment(delegate); - } - - if (nameGen.visitField(delegate, 0)) { - nameGen.visitComment(delegate); - } - - if (nameGen.visitField(delegate, 1)) { - nameGen.visitComment(delegate); - } - - // Methods - nameGen.visitMethod(delegate); - nameGen.visitMethod(delegate, 0); - nameGen.visitMethod(delegate, 1); - - if (nameGen.visitMethod(delegate)) { - nameGen.visitComment(delegate); - } - - if (nameGen.visitMethod(delegate, 0)) { - nameGen.visitComment(delegate); - } - - if (nameGen.visitMethod(delegate, 1)) { - nameGen.visitComment(delegate); - } - - // Method args - if (nameGen.visitMethod(delegate)) { - nameGen.visitMethodArg(delegate); - nameGen.visitMethodArg(delegate, 1); - nameGen.visitMethodArg(delegate, 0); - - if (nameGen.visitMethodArg(delegate)) { - nameGen.visitComment(delegate); - } - - if (nameGen.visitMethodArg(delegate, 0)) { - nameGen.visitComment(delegate); - } - - if (nameGen.visitMethodArg(delegate, 1)) { - nameGen.visitComment(delegate); - } - } - - // Method vars - if (nameGen.visitMethod(delegate)) { - nameGen.visitMethodVar(delegate); - nameGen.visitMethodVar(delegate, 1); - nameGen.visitMethodVar(delegate, 0); - - if (nameGen.visitMethodVar(delegate)) { - nameGen.visitComment(delegate); - } - - if (nameGen.visitMethodVar(delegate, 0)) { - nameGen.visitComment(delegate); - } - - if (nameGen.visitMethodVar(delegate, 1)) { - nameGen.visitComment(delegate); - } - } - } - } - - if (!delegate.visitEnd()) { - acceptTestMappingsWithHoles(delegate); - } - - return target; - } - - public static class MappingDirs { - @Nullable - public static MemoryMappingTree getCorrespondingTree(Path dir) throws IOException { - if (dir.equals(VALID)) return acceptTestMappings(new MemoryMappingTree()); - if (dir.equals(REPEATED_ELEMENTS)) return acceptTestMappingsWithRepeats(new MemoryMappingTree(), true, true); - if (dir.equals(HOLES)) return acceptTestMappingsWithHoles(new MemoryMappingTree()); - return null; - } - - public static final Path DETECTION = getResource("/detection/"); - public static final Path VALID = getResource("/reading/valid/"); - public static final Path REPEATED_ELEMENTS = getResource("/reading/repeated-elements/"); - public static final Path HOLES = getResource("/reading/holes/"); - public static final Path MERGING = getResource("/merging/"); - } + private static Path resourceRoot; } diff --git a/src/test/java/net/fabricmc/mappingio/test/lib/jool/Unchecked.java b/src/test/java/net/fabricmc/mappingio/test/lib/jool/Unchecked.java index 3738eb63..dfcf09ca 100644 --- a/src/test/java/net/fabricmc/mappingio/test/lib/jool/Unchecked.java +++ b/src/test/java/net/fabricmc/mappingio/test/lib/jool/Unchecked.java @@ -21,6 +21,7 @@ import java.util.function.Consumer; import net.fabricmc.mappingio.test.lib.jool.fi.lang.CheckedRunnable; +import net.fabricmc.mappingio.test.lib.jool.fi.util.function.CheckedConsumer; /** * Improved interoperability between checked exceptions and Java 8. @@ -101,4 +102,47 @@ public static Runnable runnable(CheckedRunnable runnable, Consumer ha } }; } + + /** + * Wrap a {@link CheckedConsumer} in a {@link Consumer}. + * + *

Example: + *


+	 * Arrays.asList("a", "b").stream().forEach(Unchecked.consumer(s -> {
+	 *     if (s.length() > 10)
+	 *         throw new Exception("Only short strings allowed");
+	 * }));
+	 * 
+ */ + public static Consumer consumer(CheckedConsumer consumer) { + return consumer(consumer, THROWABLE_TO_RUNTIME_EXCEPTION); + } + + /** + * Wrap a {@link CheckedConsumer} in a {@link Consumer} with a custom handler for checked exceptions. + * + *

Example: + *


+	 * Arrays.asList("a", "b").stream().forEach(Unchecked.consumer(
+	 *     s -> {
+	 *         if (s.length() > 10)
+	 *             throw new Exception("Only short strings allowed");
+	 *     },
+	 *     e -> {
+	 *         throw new IllegalStateException(e);
+	 *     }
+	 * ));
+	 * 
+ */ + public static Consumer consumer(CheckedConsumer consumer, Consumer handler) { + return t -> { + try { + consumer.accept(t); + } catch (Throwable e) { + handler.accept(e); + + throw new IllegalStateException("Exception handler must throw a RuntimeException", e); + } + }; + } } diff --git a/src/test/java/net/fabricmc/mappingio/test/lib/jool/fi/util/function/CheckedConsumer.java b/src/test/java/net/fabricmc/mappingio/test/lib/jool/fi/util/function/CheckedConsumer.java new file mode 100644 index 00000000..122e1bed --- /dev/null +++ b/src/test/java/net/fabricmc/mappingio/test/lib/jool/fi/util/function/CheckedConsumer.java @@ -0,0 +1,34 @@ +/* + * Copyright (c), Data Geekery GmbH, contact@datageekery.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.mappingio.test.lib.jool.fi.util.function; + +import java.util.function.Consumer; + +/** + * A {@link Consumer} that allows for checked exceptions. + * + * @author Lukas Eder + */ +@FunctionalInterface +public interface CheckedConsumer { + /** + * Performs this operation on the given argument. + * + * @param t the input argument + */ + void accept(T t) throws Throwable; +} diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/adapter/OuterClassNamePropagatorTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/OuterClassNamePropagationTest.java similarity index 51% rename from src/test/java/net/fabricmc/mappingio/test/tests/adapter/OuterClassNamePropagatorTest.java rename to src/test/java/net/fabricmc/mappingio/test/tests/OuterClassNamePropagationTest.java index c39fa898..f7118d1b 100644 --- a/src/test/java/net/fabricmc/mappingio/test/tests/adapter/OuterClassNamePropagatorTest.java +++ b/src/test/java/net/fabricmc/mappingio/test/tests/OuterClassNamePropagationTest.java @@ -14,104 +14,108 @@ * limitations under the License. */ -package net.fabricmc.mappingio.test.tests.adapter; +package net.fabricmc.mappingio.test.tests; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.IOException; -import java.util.Arrays; +import java.util.Collections; import java.util.EnumSet; +import java.util.List; import java.util.Set; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import net.fabricmc.mappingio.MappedElementKind; import net.fabricmc.mappingio.MappingFlag; import net.fabricmc.mappingio.MappingVisitor; +import net.fabricmc.mappingio.adapter.FlatAsRegularMappingVisitor; import net.fabricmc.mappingio.adapter.OuterClassNamePropagator; +import net.fabricmc.mappingio.format.MappingFormat; +import net.fabricmc.mappingio.test.TestMappings; +import net.fabricmc.mappingio.test.TestMappings.MappingDir; import net.fabricmc.mappingio.test.visitors.NopMappingVisitor; -import net.fabricmc.mappingio.test.visitors.VisitOrderVerifyingVisitor; +import net.fabricmc.mappingio.test.visitors.SubsetAssertingVisitor; +import net.fabricmc.mappingio.tree.MappingTreeView; import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.mappingio.tree.VisitableMappingTree; -public class OuterClassNamePropagatorTest { - private static void accept(MappingVisitor visitor) throws IOException { - visitor = new VisitOrderVerifyingVisitor(visitor); +public class OuterClassNamePropagationTest { + private static String srcNamespace; + private static List dstNamespaces; + private static String invalidNs = "invalid"; - do { - if (visitor.visitHeader()) { - visitor.visitNamespaces("source", Arrays.asList("dstNs0", "dstNs1", "dstNs2", "dstNs3", "dstNs4", "dstNs5", "dstNs6")); - } + @BeforeAll + public static void setup() throws IOException { + MappingTreeView tree = acceptMappings(new MemoryMappingTree()); + srcNamespace = tree.getSrcNamespace(); + dstNamespaces = tree.getDstNamespaces(); - if (visitor.visitContent()) { - if (visitor.visitClass("class_1")) { - visitor.visitDstName(MappedElementKind.CLASS, 0, "class1Ns0Rename"); - visitor.visitDstName(MappedElementKind.CLASS, 1, "class1Ns1Rename"); - visitor.visitDstName(MappedElementKind.CLASS, 2, "class1Ns2Rename"); - visitor.visitDstName(MappedElementKind.CLASS, 4, "class1Ns4Rename"); - - if (visitor.visitElementContent(MappedElementKind.CLASS)) { - if (visitor.visitField("field_1", "Lclass_1;")) { - for (int i = 0; i <= 6; i++) { - visitor.visitDstDesc(MappedElementKind.FIELD, i, "Lclass_1;"); - } - - visitor.visitElementContent(MappedElementKind.FIELD); - } - } - } + assert !srcNamespace.equals(invalidNs); + assert !dstNamespaces.contains(invalidNs); + } - if (visitor.visitClass("class_1$class_2")) { - visitor.visitDstName(MappedElementKind.CLASS, 2, "class1Ns2Rename$class2Ns2Rename"); - visitor.visitDstName(MappedElementKind.CLASS, 3, "class_1$class2Ns3Rename"); - visitor.visitDstName(MappedElementKind.CLASS, 4, "class_1$class_2"); - visitor.visitDstName(MappedElementKind.CLASS, 5, "class_1$class2Ns5Rename"); - - if (visitor.visitElementContent(MappedElementKind.CLASS)) { - if (visitor.visitField("field_2", "Lclass_1$class_2;")) { - for (int i = 0; i <= 6; i++) { - visitor.visitDstDesc(MappedElementKind.FIELD, i, "Lclass_1$class_2;"); - } - - visitor.visitElementContent(MappedElementKind.FIELD); - } - } - } + private static T acceptMappings(T visitor) throws IOException { + return TestMappings.generateOuterClassNamePropagation(visitor); + } - if (visitor.visitClass("class_1$class_2$class_3")) { - visitor.visitDstName(MappedElementKind.CLASS, 5, "class_1$class2Ns5Rename$class3Ns5Rename"); - visitor.visitDstName(MappedElementKind.CLASS, 6, "class_1$class_2$class3Ns6Rename"); + @Test + public void visitor() throws IOException { + acceptMappings(new OuterClassNamePropagator( + new OuterClassNameChecker(false, dstNamespaces, true))); - if (visitor.visitElementContent(MappedElementKind.CLASS)) { - if (visitor.visitField("field_2", "Lclass_1$class_2$class_3;")) { - for (int i = 0; i <= 6; i++) { - visitor.visitDstDesc(MappedElementKind.FIELD, i, "Lclass_1$class_2$class_3;"); - } + for (int pass = 1; pass <= 2; pass++) { + boolean processRemappedDstNames = pass == 1; - visitor.visitElementContent(MappedElementKind.FIELD); - } - } - } - } - } while (!visitor.visitEnd()); + acceptMappings(new OuterClassNamePropagator( + new OuterClassNameChecker(false, dstNamespaces, processRemappedDstNames), + dstNamespaces, + processRemappedDstNames)); + } + + assertThrows(UnsupportedOperationException.class, () -> acceptMappings(new OuterClassNamePropagator( + new NopMappingVisitor(false), + Collections.singletonList(srcNamespace), + false))); + assertThrows(IllegalArgumentException.class, () -> acceptMappings(new OuterClassNamePropagator( + new NopMappingVisitor(false), + Collections.singletonList(invalidNs), + false))); } @Test - public void directVisit() throws IOException { - accept(new OuterClassNamePropagator(new CheckingVisitor(false))); + public void visitorThroughTree() throws IOException { + for (int pass = 1; pass <= 2; pass++) { + boolean processRemappedDstNames = pass == 1; + + VisitableMappingTree tree = new MemoryMappingTree(); + acceptMappings(new OuterClassNamePropagator(tree, dstNamespaces, processRemappedDstNames)); + tree.accept(new OuterClassNameChecker(true, dstNamespaces, processRemappedDstNames)); + + checkDiskEquivalence(tree, processRemappedDstNames); + } } - @Test - public void tree() throws IOException { - VisitableMappingTree tree = new MemoryMappingTree(); - accept(new OuterClassNamePropagator(tree)); - tree.accept(new CheckingVisitor(true)); + private void checkDiskEquivalence(VisitableMappingTree tree, boolean processRemappedDstNames) throws IOException { + for (MappingFormat format : MappingFormat.values()) { + MappingDir dir = processRemappedDstNames + ? TestMappings.PROPAGATION.PROPAGATED + : TestMappings.PROPAGATION.PROPAGATED_EXCEPT_REMAPPED_DST; + + VisitableMappingTree diskTree = dir.read(format, new MemoryMappingTree()); + + tree.accept(new FlatAsRegularMappingVisitor(new SubsetAssertingVisitor(diskTree, format, null))); + diskTree.accept(new FlatAsRegularMappingVisitor(new SubsetAssertingVisitor(tree, null, format))); + } } - private static class CheckingVisitor extends NopMappingVisitor { - CheckingVisitor(boolean tree) { + private static class OuterClassNameChecker extends NopMappingVisitor { + OuterClassNameChecker(boolean mappingsPassedThroughTree, List dstNamespaces, boolean processRemappedDstNames) { super(true); - this.tree = tree; + this.tree = mappingsPassedThroughTree; + this.processRemappedDstNames = processRemappedDstNames; } @Override @@ -131,7 +135,28 @@ public void visitDstDesc(MappedElementKind targetKind, int namespace, String des switch (clsSrcName) { case "class_1": - assertEquals("Lclass_1;", desc); + if (!tree) { + assertEquals("Lclass_1;", desc); + break; + } + + switch (namespace) { + case 0: + assertEquals("Lclass1Ns0Rename;", desc); + break; + case 1: + assertEquals("Lclass1Ns1Rename;", desc); + break; + case 2: + assertEquals("Lclass1Ns2Rename;", desc); + break; + case 4: + assertEquals("Lclass1Ns4Rename;", desc); + break; + default: + throw new IllegalStateException(); + } + break; case "class_1$class_2": switch (namespace) { @@ -148,7 +173,7 @@ public void visitDstDesc(MappedElementKind targetKind, int namespace, String des assertEquals("Lclass_1$class2Ns3Rename;", desc); break; case 4: - assertEquals("Lclass_1$class_2;", desc); + assertEquals("Lclass1Ns4Rename$class_2;", desc); break; case 5: assertEquals("Lclass_1$class2Ns5Rename;", desc); @@ -176,10 +201,14 @@ public void visitDstDesc(MappedElementKind targetKind, int namespace, String des assertEquals("Lclass_1$class2Ns3Rename$class_3;", desc); break; case 4: - assertEquals("Lclass_1$class_2$class_3;", desc); + assertEquals("Lclass1Ns4Rename$class_2$class_3;", desc); break; case 5: - assertEquals("Lclass_1$class2Ns5Rename$class3Ns5Rename;", desc); + assertEquals( + processRemappedDstNames + ? "Lclass_1$class2Ns5Rename$class3Ns5Rename;" + : "Lclass_1$class_2$class3Ns5Rename;", + desc); break; case 6: assertEquals("Lclass_1$class_2$class3Ns6Rename;", desc); @@ -216,7 +245,7 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam assertEquals("class_1$class2Ns3Rename", name); break; case 4: - assertEquals("class_1$class_2", name); + assertEquals("class1Ns4Rename$class_2", name); break; case 5: assertEquals("class_1$class2Ns5Rename", name); @@ -244,10 +273,14 @@ public void visitDstName(MappedElementKind targetKind, int namespace, String nam assertEquals("class_1$class2Ns3Rename$class_3", name); break; case 4: - assertEquals("class_1$class_2$class_3", name); + assertEquals("class1Ns4Rename$class_2$class_3", name); break; case 5: - assertEquals("class_1$class2Ns5Rename$class3Ns5Rename", name); + assertEquals( + processRemappedDstNames + ? "class_1$class2Ns5Rename$class3Ns5Rename" + : "class_1$class_2$class3Ns5Rename", + name); break; case 6: assertEquals("class_1$class_2$class3Ns6Rename", name); @@ -268,6 +301,7 @@ public boolean visitEnd() throws IOException { } private final boolean tree; + private final boolean processRemappedDstNames; private byte passesDone = 0; private String clsSrcName; } diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/reading/DetectionTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/reading/DetectionTest.java index 46126bb8..0e0d485a 100644 --- a/src/test/java/net/fabricmc/mappingio/test/tests/reading/DetectionTest.java +++ b/src/test/java/net/fabricmc/mappingio/test/tests/reading/DetectionTest.java @@ -30,98 +30,26 @@ import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.format.MappingFormat; -import net.fabricmc.mappingio.test.TestUtil; +import net.fabricmc.mappingio.test.TestMappings; +import net.fabricmc.mappingio.test.TestMappings.MappingDir; import net.fabricmc.mappingio.test.visitors.NopMappingVisitor; public class DetectionTest { - private static final Path dir = TestUtil.MappingDirs.DETECTION; + private static final MappingDir dir = TestMappings.DETECTION; @Test - public void enigmaFile() throws Exception { - MappingFormat format = MappingFormat.ENIGMA_FILE; - check(format); - } - - @Test - public void enigmaDirectory() throws Exception { - MappingFormat format = MappingFormat.ENIGMA_DIR; - check(format); - } - - @Test - public void tinyFile() throws Exception { - MappingFormat format = MappingFormat.TINY_FILE; - check(format); - } - - @Test - public void tinyV2File() throws Exception { - MappingFormat format = MappingFormat.TINY_2_FILE; - check(format); - } - - @Test - public void srgFile() throws Exception { - MappingFormat format = MappingFormat.SRG_FILE; - check(format); - } - - @Test - public void xsrgFile() throws Exception { - MappingFormat format = MappingFormat.XSRG_FILE; - check(format); - } - - @Test - public void jamFile() throws Exception { - MappingFormat format = MappingFormat.JAM_FILE; - check(format); - } - - @Test - public void csrgFile() throws Exception { - MappingFormat format = MappingFormat.CSRG_FILE; - check(format); - } - - @Test - public void tsrgFile() throws Exception { - MappingFormat format = MappingFormat.TSRG_FILE; - check(format); - } - - @Test - public void tsrgV2File() throws Exception { - MappingFormat format = MappingFormat.TSRG_2_FILE; - check(format); - } - - @Test - public void proguardFile() throws Exception { - MappingFormat format = MappingFormat.PROGUARD_FILE; - check(format); - } - - @Test - public void migrationMapFile() throws Exception { - MappingFormat format = MappingFormat.INTELLIJ_MIGRATION_MAP_FILE; - check(format); - } - - @Test - public void recafSimpleFile() throws Exception { - MappingFormat format = MappingFormat.RECAF_SIMPLE_FILE; - assertThrows(AssertionFailedError.class, () -> check(format)); - } - - @Test - public void jobfFile() throws Exception { - MappingFormat format = MappingFormat.JOBF_FILE; - check(format); + public void run() throws Exception { + for (MappingFormat format : MappingFormat.values()) { + if (format == MappingFormat.RECAF_SIMPLE_FILE) { + assertThrows(AssertionFailedError.class, () -> check(format)); + } else { + check(format); + } + } } private void check(MappingFormat format) throws Exception { - Path path = dir.resolve(TestUtil.getFileName(format)); + Path path = dir.pathFor(format); assertEquals(format, MappingReader.detectFormat(path)); if (!format.hasSingleFile()) return; diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/reading/EmptyContentReadTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/reading/EmptyContentReadTest.java index 9d2c0965..491f9e55 100644 --- a/src/test/java/net/fabricmc/mappingio/test/tests/reading/EmptyContentReadTest.java +++ b/src/test/java/net/fabricmc/mappingio/test/tests/reading/EmptyContentReadTest.java @@ -46,11 +46,6 @@ public void instantiateTree() { target = new VisitOrderVerifyingVisitor(new MemoryMappingTree()); } - @Test - public void emptyEnigmaFile() throws Exception { - EnigmaFileReader.read(new StringReader(""), target); - } - @Test public void emptyTinyFile() throws Exception { String header0 = ""; @@ -85,13 +80,18 @@ public void emptyTinyV2File() throws Exception { Tiny2FileReader.read(new StringReader(header5), target); } + @Test + public void emptyEnigmaFile() throws Exception { + EnigmaFileReader.read(new StringReader(""), target); + } + @Test public void emptyProguardFile() throws Exception { ProGuardFileReader.read(new StringReader(""), target); } @Test - public void emptySrgFile() throws Exception { + public void emptySrgOrXsrgFile() throws Exception { SrgFileReader.read(new StringReader(""), target); } @@ -101,7 +101,7 @@ public void emptyJamFile() throws Exception { } @Test - public void emptyTsrgFile() throws Exception { + public void emptyCsrgOrTsrgFile() throws Exception { String header0 = ""; String header1 = "tsrg2"; String header2 = header1 + " "; diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/reading/ValidContentReadTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/reading/ValidContentReadTest.java index c055e437..10eac065 100644 --- a/src/test/java/net/fabricmc/mappingio/test/tests/reading/ValidContentReadTest.java +++ b/src/test/java/net/fabricmc/mappingio/test/tests/reading/ValidContentReadTest.java @@ -16,16 +16,18 @@ package net.fabricmc.mappingio.test.tests.reading; -import java.nio.file.Path; +import java.nio.file.Files; import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.Test; -import net.fabricmc.mappingio.MappingReader; +import net.fabricmc.mappingio.MappingUtil; +import net.fabricmc.mappingio.MappingVisitor; import net.fabricmc.mappingio.adapter.FlatAsRegularMappingVisitor; import net.fabricmc.mappingio.adapter.MappingSourceNsSwitch; import net.fabricmc.mappingio.format.MappingFormat; -import net.fabricmc.mappingio.test.TestUtil; +import net.fabricmc.mappingio.test.TestMappings; +import net.fabricmc.mappingio.test.TestMappings.MappingDir; import net.fabricmc.mappingio.test.visitors.SubsetAssertingVisitor; import net.fabricmc.mappingio.test.visitors.VisitOrderVerifyingVisitor; import net.fabricmc.mappingio.tree.MappingTreeView; @@ -34,167 +36,52 @@ public class ValidContentReadTest { @Test - public void enigmaFile() throws Exception { - MappingFormat format = MappingFormat.ENIGMA_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); - } - - @Test - public void enigmaDirectory() throws Exception { - MappingFormat format = MappingFormat.ENIGMA_DIR; - checkDefault(format); - checkHoles(format); - } - - @Test - public void tinyFile() throws Exception { - MappingFormat format = MappingFormat.TINY_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); - } - - @Test - public void tinyV2File() throws Exception { - MappingFormat format = MappingFormat.TINY_2_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); // TODO: The Tiny v2 spec disallows repeated elements, there should at least be a warning - } - - @Test - public void srgFile() throws Exception { - MappingFormat format = MappingFormat.SRG_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); - } - - @Test - public void xsrgFile() throws Exception { - MappingFormat format = MappingFormat.XSRG_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); - } - - @Test - public void jamFile() throws Exception { - MappingFormat format = MappingFormat.JAM_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); - } - - @Test - public void csrgFile() throws Exception { - MappingFormat format = MappingFormat.CSRG_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); - } - - @Test - public void tsrgFile() throws Exception { - MappingFormat format = MappingFormat.TSRG_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); - } - - @Test - public void tsrgV2File() throws Exception { - MappingFormat format = MappingFormat.TSRG_2_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); - } - - @Test - public void proguardFile() throws Exception { - MappingFormat format = MappingFormat.PROGUARD_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); - } - - @Test - public void migrationMapFile() throws Exception { - MappingFormat format = MappingFormat.INTELLIJ_MIGRATION_MAP_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); - } - - @Test - public void recafSimpleFile() throws Exception { - MappingFormat format = MappingFormat.RECAF_SIMPLE_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); - } - - @Test - public void jobfFile() throws Exception { - MappingFormat format = MappingFormat.JOBF_FILE; - checkDefault(format); - checkHoles(format); - checkRepeated(format, true); - } - - private void checkDefault(MappingFormat format) throws Exception { - Path path = TestUtil.MappingDirs.VALID.resolve(TestUtil.getFileName(format)); - - VisitableMappingTree referenceTree = TestUtil.acceptTestMappings(new MemoryMappingTree()); + public void run() throws Exception { + for (MappingDir dir : TestMappings.values()) { + for (MappingFormat format : MappingFormat.values()) { + check(dir, format); + } + } + } + + private void check(MappingDir dir, MappingFormat format) throws Exception { + if (!dir.supportsGeneration() || !Files.exists(dir.pathFor(format))) { + return; + } + + if (dir == TestMappings.PROPAGATION.UNPROPAGATED && format == MappingFormat.ENIGMA_FILE) { + // Enigma files cannot represent unpropagated outer class names, + // they are always propagated automatically since inner classes are stored as children of outer classes. + // The directory format on the other hand is able to do so by storing the classes in separate files. + return; + } + + // TODO: The Tiny v2 spec also disallows repeated elements, there should at least be warnings + boolean allowConsecutiveDuplicateElementVisits = dir == TestMappings.READING.REPEATED_ELEMENTS; + + VisitableMappingTree referenceTree = dir.generate(new MemoryMappingTree()); VisitableMappingTree tree = new MemoryMappingTree(); - boolean allowConsecutiveDuplicateElementVisits = false; - - MappingReader.read(path, format, new VisitOrderVerifyingVisitor(tree, allowConsecutiveDuplicateElementVisits)); - assertEqual(tree, format, referenceTree, allowConsecutiveDuplicateElementVisits); - tree = new MemoryMappingTree(); - MappingReader.read(path, format, - new MappingSourceNsSwitch( - new VisitOrderVerifyingVisitor( - new MappingSourceNsSwitch( - new VisitOrderVerifyingVisitor(tree, allowConsecutiveDuplicateElementVisits), - referenceTree.getSrcNamespace()), - allowConsecutiveDuplicateElementVisits), - referenceTree.getDstNamespaces().get(0))); + dir.read(format, new VisitOrderVerifyingVisitor(tree, allowConsecutiveDuplicateElementVisits)); assertEqual(tree, format, referenceTree, allowConsecutiveDuplicateElementVisits); - } - - private void checkRepeated(MappingFormat format, boolean allowConsecutiveDuplicateElementVisits) throws Exception { - Path path = TestUtil.MappingDirs.REPEATED_ELEMENTS.resolve(TestUtil.getFileName(format)); - VisitableMappingTree referenceTree = TestUtil.acceptTestMappingsWithRepeats(new MemoryMappingTree(), true, true); - VisitableMappingTree tree = new MemoryMappingTree(); - - MappingReader.read(path, format, new VisitOrderVerifyingVisitor(tree, allowConsecutiveDuplicateElementVisits)); - assertEqual(tree, format, referenceTree, allowConsecutiveDuplicateElementVisits); + if (dir == TestMappings.READING.HOLES && !format.features().hasNamespaces()) { + return; + } tree = new MemoryMappingTree(); - MappingReader.read(path, format, - new MappingSourceNsSwitch( - new VisitOrderVerifyingVisitor( - new MappingSourceNsSwitch( - new VisitOrderVerifyingVisitor(tree, allowConsecutiveDuplicateElementVisits), - referenceTree.getSrcNamespace()), - allowConsecutiveDuplicateElementVisits), - referenceTree.getDstNamespaces().get(0))); - assertEqual(tree, format, referenceTree, allowConsecutiveDuplicateElementVisits); - } - - private void checkHoles(MappingFormat format) throws Exception { - Path path = TestUtil.MappingDirs.HOLES.resolve(TestUtil.getFileName(format)); - - VisitableMappingTree referenceTree = TestUtil.acceptTestMappingsWithHoles(new MemoryMappingTree()); - VisitableMappingTree tree = new MemoryMappingTree(); - boolean allowConsecutiveDuplicateElementVisits = false; + String newSrcNs = format.features().hasNamespaces() + ? referenceTree.getDstNamespaces().get(0) + : MappingUtil.NS_TARGET_FALLBACK; + MappingVisitor target = new MappingSourceNsSwitch( + new VisitOrderVerifyingVisitor( + new MappingSourceNsSwitch( + new VisitOrderVerifyingVisitor(tree, allowConsecutiveDuplicateElementVisits), + referenceTree.getSrcNamespace()), + allowConsecutiveDuplicateElementVisits), + newSrcNs); - MappingReader.read(path, format, new VisitOrderVerifyingVisitor(tree, allowConsecutiveDuplicateElementVisits)); + dir.read(format, target); assertEqual(tree, format, referenceTree, allowConsecutiveDuplicateElementVisits); } @@ -204,10 +91,9 @@ private void assertEqual(MappingTreeView tree, MappingFormat format, MappingTree } private void assertSubset(MappingTreeView subTree, @Nullable MappingFormat subFormat, MappingTreeView supTree, @Nullable MappingFormat supFormat, boolean allowConsecutiveDuplicateElementVisits) throws Exception { - subTree.accept( - new VisitOrderVerifyingVisitor( - new FlatAsRegularMappingVisitor( - new SubsetAssertingVisitor(supTree, supFormat, subFormat)), - allowConsecutiveDuplicateElementVisits)); + subTree.accept(new VisitOrderVerifyingVisitor( + new FlatAsRegularMappingVisitor( + new SubsetAssertingVisitor(supTree, supFormat, subFormat)), + allowConsecutiveDuplicateElementVisits)); } } diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/tree/MergeTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/tree/MergeTest.java index 275ae79a..1924316b 100644 --- a/src/test/java/net/fabricmc/mappingio/test/tests/tree/MergeTest.java +++ b/src/test/java/net/fabricmc/mappingio/test/tests/tree/MergeTest.java @@ -33,7 +33,7 @@ import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.MappingVisitor; import net.fabricmc.mappingio.adapter.FlatAsRegularMappingVisitor; -import net.fabricmc.mappingio.test.TestUtil; +import net.fabricmc.mappingio.test.TestMappings; import net.fabricmc.mappingio.test.visitors.SubsetAssertingVisitor; import net.fabricmc.mappingio.test.visitors.VisitOrderVerifyingVisitor; import net.fabricmc.mappingio.tree.MappingTree.ClassMapping; @@ -41,7 +41,7 @@ import net.fabricmc.mappingio.tree.MemoryMappingTree; public class MergeTest { - private static final Path dir = TestUtil.MappingDirs.MERGING; + private static final Path dir = TestMappings.MERGING; private static final String ns1 = "ns1"; private static final String ns2 = "ns2"; private static final String ns3 = "ns3"; diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/tree/MetadataTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/tree/MetadataTest.java index 5b8e7ab5..b652fa46 100644 --- a/src/test/java/net/fabricmc/mappingio/test/tests/tree/MetadataTest.java +++ b/src/test/java/net/fabricmc/mappingio/test/tests/tree/MetadataTest.java @@ -31,7 +31,7 @@ import org.junit.jupiter.api.Test; import net.fabricmc.mappingio.MappingFlag; -import net.fabricmc.mappingio.test.TestUtil; +import net.fabricmc.mappingio.test.TestMappings; import net.fabricmc.mappingio.test.visitors.NopMappingVisitor; import net.fabricmc.mappingio.tree.MemoryMappingTree; import net.fabricmc.mappingio.tree.VisitableMappingTree; @@ -44,7 +44,7 @@ public class MetadataTest { @BeforeAll public static void setup() throws Exception { - tree = TestUtil.acceptTestMappings(new MemoryMappingTree()); + tree = TestMappings.generateValid(new MemoryMappingTree()); tree.getMetadata().clear(); for (int i = 0; i < 40; i++) { diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/tree/SetNamespacesTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/tree/SetNamespacesTest.java index 53a31a05..b7fe17b9 100644 --- a/src/test/java/net/fabricmc/mappingio/test/tests/tree/SetNamespacesTest.java +++ b/src/test/java/net/fabricmc/mappingio/test/tests/tree/SetNamespacesTest.java @@ -25,7 +25,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import net.fabricmc.mappingio.test.TestUtil; +import net.fabricmc.mappingio.test.TestMappings; import net.fabricmc.mappingio.tree.MemoryMappingTree; public class SetNamespacesTest { @@ -36,8 +36,7 @@ public class SetNamespacesTest { @BeforeEach public void setup() throws IOException { - tree = new MemoryMappingTree(); - TestUtil.acceptTestMappings(tree); + tree = TestMappings.generateValid(new MemoryMappingTree()); srcNs = tree.getSrcNamespace(); dstNs0 = tree.getDstNamespaces().get(0); diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/visiting/VisitEndTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/visiting/VisitEndTest.java index 74281e86..253af226 100644 --- a/src/test/java/net/fabricmc/mappingio/test/tests/visiting/VisitEndTest.java +++ b/src/test/java/net/fabricmc/mappingio/test/tests/visiting/VisitEndTest.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.nio.file.Files; -import java.nio.file.Path; import java.util.EnumSet; import java.util.List; import java.util.Set; @@ -31,11 +30,11 @@ import net.fabricmc.mappingio.MappedElementKind; import net.fabricmc.mappingio.MappingFlag; -import net.fabricmc.mappingio.MappingReader; import net.fabricmc.mappingio.MappingVisitor; import net.fabricmc.mappingio.adapter.FlatAsRegularMappingVisitor; import net.fabricmc.mappingio.format.MappingFormat; -import net.fabricmc.mappingio.test.TestUtil; +import net.fabricmc.mappingio.test.TestMappings; +import net.fabricmc.mappingio.test.TestMappings.MappingDir; import net.fabricmc.mappingio.test.visitors.SubsetAssertingVisitor; import net.fabricmc.mappingio.test.visitors.VisitOrderVerifyingVisitor; import net.fabricmc.mappingio.tree.MappingTree; @@ -44,112 +43,33 @@ public class VisitEndTest { @Test - public void enigmaFile() throws Exception { - MappingFormat format = MappingFormat.ENIGMA_FILE; - check(format); - } - - @Test - public void enigmaDirectory() throws Exception { - MappingFormat format = MappingFormat.ENIGMA_DIR; - check(format); - } - - @Test - public void tinyFile() throws Exception { - MappingFormat format = MappingFormat.TINY_FILE; - check(format); - } - - @Test - public void tinyV2File() throws Exception { - MappingFormat format = MappingFormat.TINY_2_FILE; - check(format); - } - - @Test - public void srgFile() throws Exception { - MappingFormat format = MappingFormat.SRG_FILE; - check(format); - } - - @Test - public void xrgFile() throws Exception { - MappingFormat format = MappingFormat.XSRG_FILE; - check(format); - } - - @Test - public void jamFile() throws Exception { - MappingFormat format = MappingFormat.JAM_FILE; - check(format); - } - - @Test - public void csrgFile() throws Exception { - MappingFormat format = MappingFormat.CSRG_FILE; - check(format); - } - - @Test - public void tsrgFile() throws Exception { - MappingFormat format = MappingFormat.TSRG_FILE; - check(format); - } - - @Test - public void tsrgV2File() throws Exception { - MappingFormat format = MappingFormat.TSRG_2_FILE; - check(format); - } - - @Test - public void proguardFile() throws Exception { - MappingFormat format = MappingFormat.PROGUARD_FILE; - check(format); - } - - @Test - public void migrationMapFile() throws Exception { - MappingFormat format = MappingFormat.INTELLIJ_MIGRATION_MAP_FILE; - check(format); - } - - @Test - public void recafSimpleFile() throws Exception { - MappingFormat format = MappingFormat.RECAF_SIMPLE_FILE; - check(format); - } - - @Test - public void jobfFile() throws Exception { - MappingFormat format = MappingFormat.JOBF_FILE; - check(format); - } - - private void check(MappingFormat format) throws Exception { - checkDir(TestUtil.MappingDirs.DETECTION, format); - checkDir(TestUtil.MappingDirs.VALID, format); - checkDir(TestUtil.MappingDirs.REPEATED_ELEMENTS, format); - checkDir(TestUtil.MappingDirs.HOLES, format); + public void run() throws Exception { + for (MappingDir dir : TestMappings.values()) { + for (MappingFormat format : MappingFormat.values()) { + check(dir, format); + } + } } - private void checkDir(Path dir, MappingFormat format) throws Exception { - Path path = dir.resolve(TestUtil.getFileName(format)); - if (!Files.exists(path)) return; + private void check(MappingDir dir, MappingFormat format) throws Exception { + if (!Files.exists(dir.pathFor(format))) { + return; + } - MappingTreeView supTree = TestUtil.MappingDirs.getCorrespondingTree(dir); + MappingTreeView supTree = dir.supportsGeneration() + ? dir.generate(new MemoryMappingTree()) + : null; - checkCompliance(format, path, 1, true, supTree); - checkCompliance(format, path, 1, false, supTree); + checkCompliance(dir, format, 1, true, supTree); + checkCompliance(dir, format, 1, false, supTree); - checkCompliance(format, path, 2, true, supTree); - checkCompliance(format, path, 3, true, supTree); + checkCompliance(dir, format, 2, true, supTree); + checkCompliance(dir, format, 3, true, supTree); - VisitEndTestVisitor nonFlaggedVisitor; + VisitEndComplianceChecker nonFlaggedVisitor; try { - nonFlaggedVisitor = checkCompliance(format, path, 2, false, supTree); + nonFlaggedVisitor = checkCompliance(dir, format, 2, false, supTree); } catch (Exception e) { return; // Reader doesn't support multiple passes without NEEDS_MULTIPLE_PASSES } @@ -158,19 +78,20 @@ private void checkDir(Path dir, MappingFormat format) throws Exception { assertEquals(nonFlaggedVisitor.finishedVisitPassCount, nonFlaggedVisitor.visitPassCountToFinish); } - private VisitEndTestVisitor checkCompliance(MappingFormat format, Path path, int visitPassCountToFinish, boolean setFlag, MappingTreeView supTree) throws Exception { - VisitEndTestVisitor visitor = new VisitEndTestVisitor(visitPassCountToFinish, setFlag, supTree, format); - MappingReader.read(path, format, new VisitOrderVerifyingVisitor(visitor)); + private VisitEndComplianceChecker checkCompliance(MappingDir dir, MappingFormat format, int visitPassCountToFinish, boolean setFlag, MappingTreeView supTree) throws Exception { + VisitEndComplianceChecker visitor = new VisitEndComplianceChecker(visitPassCountToFinish, setFlag, supTree, format, dir); + dir.read(format, new VisitOrderVerifyingVisitor(visitor)); assertEquals(visitor.finishedVisitPassCount, visitPassCountToFinish); return visitor; } - private static class VisitEndTestVisitor implements MappingVisitor { - private VisitEndTestVisitor(int visitPassCountToFinish, boolean setFlag, MappingTreeView supTree, MappingFormat subFormat) { + private static class VisitEndComplianceChecker implements MappingVisitor { + private VisitEndComplianceChecker(int visitPassCountToFinish, boolean setFlag, MappingTreeView supTree, MappingFormat subFormat, MappingDir dir) { this.visitPassCountToFinish = visitPassCountToFinish; this.setFlag = setFlag; this.supTree = supTree; this.subFormat = subFormat; + this.dir = dir; this.tree = new MemoryMappingTree(); this.oldTrees = new MappingTree[visitPassCountToFinish - 1]; } @@ -303,6 +224,10 @@ private void checkContent() throws IOException { if (finishedVisitPassCount > 1) supFormat = subFormat; } + if (dir == TestMappings.PROPAGATION.UNPROPAGATED && subFormat == MappingFormat.ENIGMA_FILE) { + return; + } + subTree = tree; subTree.accept(new FlatAsRegularMappingVisitor(new SubsetAssertingVisitor(supTree, supFormat, subFormat))); supTree.accept(new FlatAsRegularMappingVisitor(new SubsetAssertingVisitor(subTree, subFormat, supFormat))); @@ -312,6 +237,7 @@ private void checkContent() throws IOException { private final boolean setFlag; private final MappingTreeView supTree; private final MappingFormat subFormat; + private final MappingDir dir; private final MappingTree[] oldTrees; private int finishedVisitPassCount; private MemoryMappingTree tree; diff --git a/src/test/java/net/fabricmc/mappingio/test/tests/writing/WriteTest.java b/src/test/java/net/fabricmc/mappingio/test/tests/writing/WriteTest.java index 1da2f861..6fd5a540 100644 --- a/src/test/java/net/fabricmc/mappingio/test/tests/writing/WriteTest.java +++ b/src/test/java/net/fabricmc/mappingio/test/tests/writing/WriteTest.java @@ -18,22 +18,22 @@ import java.io.IOException; import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; import net.neoforged.srgutils.IMappingFile; import net.neoforged.srgutils.INamedMappingFile; -import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import net.fabricmc.mappingio.MappedElementKind; import net.fabricmc.mappingio.MappingReader; +import net.fabricmc.mappingio.MappingVisitor; import net.fabricmc.mappingio.MappingWriter; import net.fabricmc.mappingio.adapter.FlatAsRegularMappingVisitor; import net.fabricmc.mappingio.adapter.ForwardingMappingVisitor; import net.fabricmc.mappingio.adapter.MappingNsCompleter; import net.fabricmc.mappingio.format.MappingFormat; +import net.fabricmc.mappingio.test.TestMappings; +import net.fabricmc.mappingio.test.TestMappings.MappingDir; import net.fabricmc.mappingio.test.TestUtil; import net.fabricmc.mappingio.test.visitors.SubsetAssertingVisitor; import net.fabricmc.mappingio.tree.MappingTreeView; @@ -42,116 +42,44 @@ public class WriteTest { @TempDir - private static Path dir; - private static MappingTreeView validTree; - private static Map treeNsAltMap = new HashMap<>(); - private static MappingTreeView validWithRepeatsTree; - private static Map treeWithRepeatsNsAltMap = new HashMap<>(); - private static MappingTreeView validWithHolesTree; - private static Map treeWithHolesNsAltMap = new HashMap<>(); - - @BeforeAll - public static void setup() throws Exception { - validTree = TestUtil.acceptTestMappings(new MemoryMappingTree()); - treeNsAltMap.put(validTree.getDstNamespaces().get(0), validTree.getSrcNamespace()); - treeNsAltMap.put(validTree.getDstNamespaces().get(1), validTree.getSrcNamespace()); - - validWithRepeatsTree = TestUtil.acceptTestMappingsWithRepeats(new MemoryMappingTree(), true, true); - treeWithRepeatsNsAltMap.put(validWithRepeatsTree.getDstNamespaces().get(0), validWithRepeatsTree.getSrcNamespace()); - treeWithRepeatsNsAltMap.put(validWithRepeatsTree.getDstNamespaces().get(1), validWithRepeatsTree.getSrcNamespace()); - - validWithHolesTree = TestUtil.acceptTestMappingsWithHoles(new MemoryMappingTree()); - treeWithHolesNsAltMap.put(validWithHolesTree.getDstNamespaces().get(0), validWithHolesTree.getSrcNamespace()); - treeWithHolesNsAltMap.put(validWithHolesTree.getDstNamespaces().get(1), validWithHolesTree.getSrcNamespace()); - } - - @Test - public void enigmaFile() throws Exception { - check(MappingFormat.ENIGMA_FILE); - } - - @Test - public void enigmaDirectory() throws Exception { - check(MappingFormat.ENIGMA_DIR); - } - - @Test - public void tinyFile() throws Exception { - check(MappingFormat.TINY_FILE); - } + private static Path targetDir; @Test - public void tinyV2File() throws Exception { - check(MappingFormat.TINY_2_FILE); - } - - @Test - public void srgFile() throws Exception { - check(MappingFormat.SRG_FILE); - } - - @Test - public void xsrgFile() throws Exception { - check(MappingFormat.XSRG_FILE); - } - - @Test - public void jamFile() throws Exception { - check(MappingFormat.JAM_FILE); - } - - @Test - public void csrgFile() throws Exception { - check(MappingFormat.CSRG_FILE); - } - - @Test - public void tsrgFile() throws Exception { - check(MappingFormat.TSRG_FILE); - } - - @Test - public void tsrgV2File() throws Exception { - check(MappingFormat.TSRG_2_FILE); - } - - @Test - public void proguardFile() throws Exception { - check(MappingFormat.PROGUARD_FILE); - } - - @Test - public void migrationMapFile() throws Exception { - check(MappingFormat.INTELLIJ_MIGRATION_MAP_FILE); - } - - @Test - public void recafSimpleFile() throws Exception { - check(MappingFormat.RECAF_SIMPLE_FILE); - } - - @Test - public void jobfFile() throws Exception { - check(MappingFormat.JOBF_FILE); - } - - private void check(MappingFormat format) throws Exception { - Path path = dir.resolve(TestUtil.getFileName(format)); - TestUtil.acceptTestMappings(MappingWriter.create(path, format)); - readWithMio(validTree, path, format); - readWithLorenz(path, format); - readWithSrgUtils(validTree, format, treeNsAltMap); - - boolean isEnigma = format == MappingFormat.ENIGMA_FILE || format == MappingFormat.ENIGMA_DIR; - TestUtil.acceptTestMappingsWithRepeats(MappingWriter.create(path, format), !isEnigma, !isEnigma); - readWithMio(validWithRepeatsTree, path, format); - readWithLorenz(path, format); - readWithSrgUtils(validWithRepeatsTree, format, treeWithRepeatsNsAltMap); + public void run() throws Exception { + for (MappingDir dir : TestMappings.values()) { + for (MappingFormat format : MappingFormat.values()) { + check(dir, format); + } + } + } + + private void check(MappingDir dir, MappingFormat format) throws Exception { + if (!dir.supportsGeneration() || !format.hasWriter) { + return; + } + + Path path = targetDir.resolve(TestUtil.getFileName(format)); + MappingTreeView tree = dir.generate(new MemoryMappingTree()); + MappingVisitor target = MappingWriter.create(path, format); + + if (dir.isIn(TestMappings.PROPAGATION.BASE_DIR) && !format.features().hasNamespaces()) { + target = new MappingNsCompleter(target); + } + + if (dir == TestMappings.READING.REPEATED_ELEMENTS) { + boolean isEnigma = format == MappingFormat.ENIGMA_FILE || format == MappingFormat.ENIGMA_DIR; + TestMappings.generateRepeatedElements(target, !isEnigma, !isEnigma); + } else { + dir.generate(target); + } + + if (!(dir == TestMappings.PROPAGATION.UNPROPAGATED && format == MappingFormat.ENIGMA_FILE)) { + // See ValidContentReadTest for explanation + readWithMio(tree, path, format); + } - TestUtil.acceptTestMappingsWithHoles(MappingWriter.create(path, format)); - readWithMio(validWithHolesTree, path, format); readWithLorenz(path, format); - readWithSrgUtils(validWithHolesTree, format, treeWithHolesNsAltMap); + readWithSrgUtils(tree, format); } private void readWithMio(MappingTreeView origTree, Path outputPath, MappingFormat outputFormat) throws Exception { @@ -168,7 +96,7 @@ private void readWithLorenz(Path path, MappingFormat format) throws Exception { lorenzFormat.read(path); } - private void readWithSrgUtils(MappingTreeView tree, MappingFormat format, Map nsAltMap) throws Exception { + private void readWithSrgUtils(MappingTreeView tree, MappingFormat format) throws Exception { IMappingFile.Format srgUtilsFormat = TestUtil.toSrgUtilsFormat(format); if (srgUtilsFormat == null) return; @@ -186,10 +114,9 @@ private void readWithSrgUtils(MappingTreeView tree, MappingFormat format, Map dstNamespaces) throws IOException { String expectedSrcNs = subFeatures.hasNamespaces() ? supTree.getSrcNamespace() : MappingUtil.NS_SOURCE_FALLBACK; assertEquals(expectedSrcNs, srcNamespace, "Incoming mappings have different source namespace than supTree"); - this.subDstNamespaces = dstNamespaces; + subDstNamespaces = new ArrayList<>(dstNamespaces); if (!subFeatures.hasNamespaces()) { assertEquals(1, dstNamespaces.size(), "Incoming mappings have multiple namespaces (" @@ -71,6 +72,7 @@ public void visitNamespaces(String srcNamespace, List dstNamespaces) thr + subFormat + ") declaring not to support them"); assertEquals(MappingUtil.NS_TARGET_FALLBACK, dstNamespaces.get(0), "Incoming mappings don't have default destination namespace name of non-namespaced formats"); + subDstNamespaces.set(0, supTree.getNamespaceName(0)); // TODO: Make this configurable return; } @@ -85,7 +87,16 @@ public void visitNamespaces(String srcNamespace, List dstNamespaces) thr break; } - if (i < dstNamespaces.size() - 1) continue; + if (i < dstNamespaces.size() - 1) { + continue; + } else if (supTree.getNamespaceName(0).equals(MappingUtil.NS_TARGET_FALLBACK)) { + // None of the incoming namespaces equal supTree's, which uses the fallback namespace. + // Let's assume it's equivalent to the first incoming sub namespace. + // TODO: Make this configurable + subNsIfSupNotNamespaced = 0; + subDstNamespaces.set(0, supTree.getNamespaceName(0)); + break; + } } assertTrue(contained, "Incoming namespace not contained in supTree: " + dstNs); diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/csrg.csrg b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/csrg.csrg new file mode 100644 index 00000000..2d994d41 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/csrg.csrg @@ -0,0 +1,6 @@ +class_1 class1Ns0Rename +class_1 field_1 field_1 +class_1$class_2 class1Ns0Rename$class_2 +class_1$class_2 field_2 field_2 +class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 +class_1$class_2$class_3 field_2 field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/enigma-dir/class1Ns0Rename.mapping b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/enigma-dir/class1Ns0Rename.mapping new file mode 100644 index 00000000..9340f589 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/enigma-dir/class1Ns0Rename.mapping @@ -0,0 +1,6 @@ +CLASS class_1 class1Ns0Rename + FIELD field_1 field_1 Lclass_1; + CLASS class_2 + FIELD field_2 field_2 Lclass_1$class_2; + CLASS class_3 + FIELD field_2 field_2 Lclass_1$class_2$class_3; diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/enigma.mappings b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/enigma.mappings new file mode 100644 index 00000000..9340f589 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/enigma.mappings @@ -0,0 +1,6 @@ +CLASS class_1 class1Ns0Rename + FIELD field_1 field_1 Lclass_1; + CLASS class_2 + FIELD field_2 field_2 Lclass_1$class_2; + CLASS class_3 + FIELD field_2 field_2 Lclass_1$class_2$class_3; diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/jam.jam b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/jam.jam new file mode 100644 index 00000000..be55282c --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/jam.jam @@ -0,0 +1,6 @@ +CL class_1 class1Ns0Rename +CL class_1$class_2 class1Ns0Rename$class_2 +CL class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 +FD class_1 field_1 Lclass_1; field_1 +FD class_1$class_2 field_2 Lclass_1$class_2; field_2 +FD class_1$class_2$class_3 field_2 Lclass_1$class_2$class_3; field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/jobf.jobf b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/jobf.jobf new file mode 100644 index 00000000..4304af55 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/jobf.jobf @@ -0,0 +1,6 @@ +c class_1 = class1Ns0Rename +f class_1.field_1:Lclass_1; = field_1 +c class_1$class_2 = class1Ns0Rename$class_2 +f class_1$class_2.field_2:Lclass_1$class_2; = field_2 +c class_1$class_2$class_3 = class1Ns0Rename$class_2$class_3 +f class_1$class_2$class_3.field_2:Lclass_1$class_2$class_3; = field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/migration-map.xml b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/migration-map.xml new file mode 100644 index 00000000..01514276 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/migration-map.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/proguard.txt b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/proguard.txt new file mode 100644 index 00000000..331eb8f2 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/proguard.txt @@ -0,0 +1,6 @@ +class_1 -> class1Ns0Rename: + class_1 field_1 -> field_1 +class_1$class_2 -> class1Ns0Rename$class_2: + class_1$class_2 field_2 -> field_2 +class_1$class_2$class_3 -> class1Ns0Rename$class_2$class_3: + class_1$class_2$class_3 field_2 -> field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/recaf-simple.txt b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/recaf-simple.txt new file mode 100644 index 00000000..7b584dc4 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/recaf-simple.txt @@ -0,0 +1,6 @@ +class_1 class1Ns0Rename +class_1.field_1 Lclass_1; field_1 +class_1$class_2 class1Ns0Rename$class_2 +class_1$class_2.field_2 Lclass_1$class_2; field_2 +class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 +class_1$class_2$class_3.field_2 Lclass_1$class_2$class_3; field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/srg.srg b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/srg.srg new file mode 100644 index 00000000..574caa40 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/srg.srg @@ -0,0 +1,6 @@ +CL: class_1 class1Ns0Rename +FD: class_1/field_1 class1Ns0Rename/field_1 +CL: class_1$class_2 class1Ns0Rename$class_2 +FD: class_1$class_2/field_2 class1Ns0Rename$class_2/field_2 +CL: class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 +FD: class_1$class_2$class_3/field_2 class1Ns0Rename$class_2$class_3/field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tiny.tiny b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tiny.tiny new file mode 100644 index 00000000..cffa8a5e --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tiny.tiny @@ -0,0 +1,4 @@ +v1 source dstNs0 dstNs1 dstNs2 dstNs3 dstNs4 dstNs5 dstNs6 +CLASS class_1 class1Ns0Rename class1Ns1Rename class1Ns2Rename class1Ns4Rename +CLASS class_1$class_2 class1Ns0Rename$class_2 class1Ns1Rename$class_2 class1Ns2Rename$class2Ns2Rename class_1$class2Ns3Rename class1Ns4Rename$class_2 class_1$class2Ns5Rename +CLASS class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 class1Ns1Rename$class_2$class_3 class1Ns2Rename$class2Ns2Rename$class_3 class_1$class2Ns3Rename$class_3 class1Ns4Rename$class_2$class_3 class_1$class_2$class3Ns5Rename class_1$class_2$class3Ns6Rename diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tinyV2.tiny b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tinyV2.tiny new file mode 100644 index 00000000..dbc564f2 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tinyV2.tiny @@ -0,0 +1,7 @@ +tiny 2 0 source dstNs0 dstNs1 dstNs2 dstNs3 dstNs4 dstNs5 dstNs6 +c class_1 class1Ns0Rename class1Ns1Rename class1Ns2Rename class1Ns4Rename + f Lclass_1; field_1 +c class_1$class_2 class1Ns0Rename$class_2 class1Ns1Rename$class_2 class1Ns2Rename$class2Ns2Rename class_1$class2Ns3Rename class1Ns4Rename$class_2 class_1$class2Ns5Rename + f Lclass_1$class_2; field_2 +c class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 class1Ns1Rename$class_2$class_3 class1Ns2Rename$class2Ns2Rename$class_3 class_1$class2Ns3Rename$class_3 class1Ns4Rename$class_2$class_3 class_1$class_2$class3Ns5Rename class_1$class_2$class3Ns6Rename + f Lclass_1$class_2$class_3; field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tsrg.tsrg b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tsrg.tsrg new file mode 100644 index 00000000..b950c94d --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tsrg.tsrg @@ -0,0 +1,6 @@ +class_1 class1Ns0Rename + field_1 field_1 +class_1$class_2 class1Ns0Rename$class_2 + field_2 field_2 +class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 + field_2 field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tsrgV2.tsrg b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tsrgV2.tsrg new file mode 100644 index 00000000..6ad171bb --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/tsrgV2.tsrg @@ -0,0 +1,4 @@ +tsrg2 source dstNs0 dstNs1 dstNs2 dstNs3 dstNs4 dstNs5 dstNs6 +class_1 class1Ns0Rename class1Ns1Rename class1Ns2Rename class_1 class1Ns4Rename class_1 class_1 +class_1$class_2 class1Ns0Rename$class_2 class1Ns1Rename$class_2 class1Ns2Rename$class2Ns2Rename class_1$class2Ns3Rename class1Ns4Rename$class_2 class_1$class2Ns5Rename class_1$class_2 +class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 class1Ns1Rename$class_2$class_3 class1Ns2Rename$class2Ns2Rename$class_3 class_1$class2Ns3Rename$class_3 class1Ns4Rename$class_2$class_3 class_1$class_2$class3Ns5Rename class_1$class_2$class3Ns6Rename diff --git a/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/xsrg.xsrg b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/xsrg.xsrg new file mode 100644 index 00000000..4fbfad26 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated-except-remapped-dst/xsrg.xsrg @@ -0,0 +1,6 @@ +CL: class_1 class1Ns0Rename +FD: class_1/field_1 Lclass_1; class1Ns0Rename/field_1 Lclass_1; +CL: class_1$class_2 class1Ns0Rename$class_2 +FD: class_1$class_2/field_2 Lclass_1$class_2; class1Ns0Rename$class_2/field_2 Lclass1Ns0Rename$class_2; +CL: class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 +FD: class_1$class_2$class_3/field_2 Lclass_1$class_2$class_3; class1Ns0Rename$class_2$class_3/field_2 Lclass1Ns0Rename$class_2$class_3; diff --git a/src/test/resources/outer-class-name-propagation/propagated/csrg.csrg b/src/test/resources/outer-class-name-propagation/propagated/csrg.csrg new file mode 100644 index 00000000..2d994d41 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/csrg.csrg @@ -0,0 +1,6 @@ +class_1 class1Ns0Rename +class_1 field_1 field_1 +class_1$class_2 class1Ns0Rename$class_2 +class_1$class_2 field_2 field_2 +class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 +class_1$class_2$class_3 field_2 field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated/enigma-dir/class1Ns0Rename.mapping b/src/test/resources/outer-class-name-propagation/propagated/enigma-dir/class1Ns0Rename.mapping new file mode 100644 index 00000000..9340f589 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/enigma-dir/class1Ns0Rename.mapping @@ -0,0 +1,6 @@ +CLASS class_1 class1Ns0Rename + FIELD field_1 field_1 Lclass_1; + CLASS class_2 + FIELD field_2 field_2 Lclass_1$class_2; + CLASS class_3 + FIELD field_2 field_2 Lclass_1$class_2$class_3; diff --git a/src/test/resources/outer-class-name-propagation/propagated/enigma.mappings b/src/test/resources/outer-class-name-propagation/propagated/enigma.mappings new file mode 100644 index 00000000..9340f589 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/enigma.mappings @@ -0,0 +1,6 @@ +CLASS class_1 class1Ns0Rename + FIELD field_1 field_1 Lclass_1; + CLASS class_2 + FIELD field_2 field_2 Lclass_1$class_2; + CLASS class_3 + FIELD field_2 field_2 Lclass_1$class_2$class_3; diff --git a/src/test/resources/outer-class-name-propagation/propagated/jam.jam b/src/test/resources/outer-class-name-propagation/propagated/jam.jam new file mode 100644 index 00000000..be55282c --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/jam.jam @@ -0,0 +1,6 @@ +CL class_1 class1Ns0Rename +CL class_1$class_2 class1Ns0Rename$class_2 +CL class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 +FD class_1 field_1 Lclass_1; field_1 +FD class_1$class_2 field_2 Lclass_1$class_2; field_2 +FD class_1$class_2$class_3 field_2 Lclass_1$class_2$class_3; field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated/jobf.jobf b/src/test/resources/outer-class-name-propagation/propagated/jobf.jobf new file mode 100644 index 00000000..4304af55 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/jobf.jobf @@ -0,0 +1,6 @@ +c class_1 = class1Ns0Rename +f class_1.field_1:Lclass_1; = field_1 +c class_1$class_2 = class1Ns0Rename$class_2 +f class_1$class_2.field_2:Lclass_1$class_2; = field_2 +c class_1$class_2$class_3 = class1Ns0Rename$class_2$class_3 +f class_1$class_2$class_3.field_2:Lclass_1$class_2$class_3; = field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated/migration-map.xml b/src/test/resources/outer-class-name-propagation/propagated/migration-map.xml new file mode 100644 index 00000000..01514276 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/migration-map.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/test/resources/outer-class-name-propagation/propagated/proguard.txt b/src/test/resources/outer-class-name-propagation/propagated/proguard.txt new file mode 100644 index 00000000..331eb8f2 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/proguard.txt @@ -0,0 +1,6 @@ +class_1 -> class1Ns0Rename: + class_1 field_1 -> field_1 +class_1$class_2 -> class1Ns0Rename$class_2: + class_1$class_2 field_2 -> field_2 +class_1$class_2$class_3 -> class1Ns0Rename$class_2$class_3: + class_1$class_2$class_3 field_2 -> field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated/recaf-simple.txt b/src/test/resources/outer-class-name-propagation/propagated/recaf-simple.txt new file mode 100644 index 00000000..7b584dc4 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/recaf-simple.txt @@ -0,0 +1,6 @@ +class_1 class1Ns0Rename +class_1.field_1 Lclass_1; field_1 +class_1$class_2 class1Ns0Rename$class_2 +class_1$class_2.field_2 Lclass_1$class_2; field_2 +class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 +class_1$class_2$class_3.field_2 Lclass_1$class_2$class_3; field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated/srg.srg b/src/test/resources/outer-class-name-propagation/propagated/srg.srg new file mode 100644 index 00000000..574caa40 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/srg.srg @@ -0,0 +1,6 @@ +CL: class_1 class1Ns0Rename +FD: class_1/field_1 class1Ns0Rename/field_1 +CL: class_1$class_2 class1Ns0Rename$class_2 +FD: class_1$class_2/field_2 class1Ns0Rename$class_2/field_2 +CL: class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 +FD: class_1$class_2$class_3/field_2 class1Ns0Rename$class_2$class_3/field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated/tiny.tiny b/src/test/resources/outer-class-name-propagation/propagated/tiny.tiny new file mode 100644 index 00000000..ede8e32d --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/tiny.tiny @@ -0,0 +1,4 @@ +v1 source dstNs0 dstNs1 dstNs2 dstNs3 dstNs4 dstNs5 dstNs6 +CLASS class_1 class1Ns0Rename class1Ns1Rename class1Ns2Rename class1Ns4Rename +CLASS class_1$class_2 class1Ns0Rename$class_2 class1Ns1Rename$class_2 class1Ns2Rename$class2Ns2Rename class_1$class2Ns3Rename class1Ns4Rename$class_2 class_1$class2Ns5Rename +CLASS class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 class1Ns1Rename$class_2$class_3 class1Ns2Rename$class2Ns2Rename$class_3 class_1$class2Ns3Rename$class_3 class1Ns4Rename$class_2$class_3 class_1$class2Ns5Rename$class3Ns5Rename class_1$class_2$class3Ns6Rename diff --git a/src/test/resources/outer-class-name-propagation/propagated/tinyV2.tiny b/src/test/resources/outer-class-name-propagation/propagated/tinyV2.tiny new file mode 100644 index 00000000..4d1b404b --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/tinyV2.tiny @@ -0,0 +1,7 @@ +tiny 2 0 source dstNs0 dstNs1 dstNs2 dstNs3 dstNs4 dstNs5 dstNs6 +c class_1 class1Ns0Rename class1Ns1Rename class1Ns2Rename class1Ns4Rename + f Lclass_1; field_1 +c class_1$class_2 class1Ns0Rename$class_2 class1Ns1Rename$class_2 class1Ns2Rename$class2Ns2Rename class_1$class2Ns3Rename class1Ns4Rename$class_2 class_1$class2Ns5Rename + f Lclass_1$class_2; field_2 +c class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 class1Ns1Rename$class_2$class_3 class1Ns2Rename$class2Ns2Rename$class_3 class_1$class2Ns3Rename$class_3 class1Ns4Rename$class_2$class_3 class_1$class2Ns5Rename$class3Ns5Rename class_1$class_2$class3Ns6Rename + f Lclass_1$class_2$class_3; field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated/tsrg.tsrg b/src/test/resources/outer-class-name-propagation/propagated/tsrg.tsrg new file mode 100644 index 00000000..b950c94d --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/tsrg.tsrg @@ -0,0 +1,6 @@ +class_1 class1Ns0Rename + field_1 field_1 +class_1$class_2 class1Ns0Rename$class_2 + field_2 field_2 +class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 + field_2 field_2 diff --git a/src/test/resources/outer-class-name-propagation/propagated/tsrgV2.tsrg b/src/test/resources/outer-class-name-propagation/propagated/tsrgV2.tsrg new file mode 100644 index 00000000..7d40cb2a --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/tsrgV2.tsrg @@ -0,0 +1,4 @@ +tsrg2 source dstNs0 dstNs1 dstNs2 dstNs3 dstNs4 dstNs5 dstNs6 +class_1 class1Ns0Rename class1Ns1Rename class1Ns2Rename class_1 class1Ns4Rename class_1 class_1 +class_1$class_2 class1Ns0Rename$class_2 class1Ns1Rename$class_2 class1Ns2Rename$class2Ns2Rename class_1$class2Ns3Rename class1Ns4Rename$class_2 class_1$class2Ns5Rename class_1$class_2 +class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 class1Ns1Rename$class_2$class_3 class1Ns2Rename$class2Ns2Rename$class_3 class_1$class2Ns3Rename$class_3 class1Ns4Rename$class_2$class_3 class_1$class2Ns5Rename$class3Ns5Rename class_1$class_2$class3Ns6Rename diff --git a/src/test/resources/outer-class-name-propagation/propagated/xsrg.xsrg b/src/test/resources/outer-class-name-propagation/propagated/xsrg.xsrg new file mode 100644 index 00000000..4fbfad26 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/propagated/xsrg.xsrg @@ -0,0 +1,6 @@ +CL: class_1 class1Ns0Rename +FD: class_1/field_1 Lclass_1; class1Ns0Rename/field_1 Lclass_1; +CL: class_1$class_2 class1Ns0Rename$class_2 +FD: class_1$class_2/field_2 Lclass_1$class_2; class1Ns0Rename$class_2/field_2 Lclass1Ns0Rename$class_2; +CL: class_1$class_2$class_3 class1Ns0Rename$class_2$class_3 +FD: class_1$class_2$class_3/field_2 Lclass_1$class_2$class_3; class1Ns0Rename$class_2$class_3/field_2 Lclass1Ns0Rename$class_2$class_3; diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/csrg.csrg b/src/test/resources/outer-class-name-propagation/unpropagated/csrg.csrg new file mode 100644 index 00000000..86979208 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/csrg.csrg @@ -0,0 +1,6 @@ +class_1 class1Ns0Rename +class_1 field_1 field_1 +class_1$class_2 class_1$class_2 +class_1$class_2 field_2 field_2 +class_1$class_2$class_3 class_1$class_2$class_3 +class_1$class_2$class_3 field_2 field_2 diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/enigma-dir/class1Ns0Rename.mapping b/src/test/resources/outer-class-name-propagation/unpropagated/enigma-dir/class1Ns0Rename.mapping new file mode 100644 index 00000000..5d2c3060 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/enigma-dir/class1Ns0Rename.mapping @@ -0,0 +1,2 @@ +CLASS class_1 class1Ns0Rename + FIELD field_1 field_1 Lclass_1; diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/enigma-dir/class_1.mapping b/src/test/resources/outer-class-name-propagation/unpropagated/enigma-dir/class_1.mapping new file mode 100644 index 00000000..137aa22e --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/enigma-dir/class_1.mapping @@ -0,0 +1,5 @@ +CLASS class_1 + CLASS class_2 + FIELD field_2 field_2 Lclass_1$class_2; + CLASS class_3 + FIELD field_2 field_2 Lclass_1$class_2$class_3; diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/enigma.mappings b/src/test/resources/outer-class-name-propagation/unpropagated/enigma.mappings new file mode 100644 index 00000000..9340f589 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/enigma.mappings @@ -0,0 +1,6 @@ +CLASS class_1 class1Ns0Rename + FIELD field_1 field_1 Lclass_1; + CLASS class_2 + FIELD field_2 field_2 Lclass_1$class_2; + CLASS class_3 + FIELD field_2 field_2 Lclass_1$class_2$class_3; diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/jam.jam b/src/test/resources/outer-class-name-propagation/unpropagated/jam.jam new file mode 100644 index 00000000..1e59e4a5 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/jam.jam @@ -0,0 +1,6 @@ +CL class_1 class1Ns0Rename +CL class_1$class_2 class_1$class_2 +CL class_1$class_2$class_3 class_1$class_2$class_3 +FD class_1 field_1 Lclass_1; field_1 +FD class_1$class_2 field_2 Lclass_1$class_2; field_2 +FD class_1$class_2$class_3 field_2 Lclass_1$class_2$class_3; field_2 diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/jobf.jobf b/src/test/resources/outer-class-name-propagation/unpropagated/jobf.jobf new file mode 100644 index 00000000..05a4bae4 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/jobf.jobf @@ -0,0 +1,6 @@ +c class_1 = class1Ns0Rename +f class_1.field_1:Lclass_1; = field_1 +c class_1$class_2 = class_1$class_2 +f class_1$class_2.field_2:Lclass_1$class_2; = field_2 +c class_1$class_2$class_3 = class_1$class_2$class_3 +f class_1$class_2$class_3.field_2:Lclass_1$class_2$class_3; = field_2 diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/migration-map.xml b/src/test/resources/outer-class-name-propagation/unpropagated/migration-map.xml new file mode 100644 index 00000000..ff55e316 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/migration-map.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/proguard.txt b/src/test/resources/outer-class-name-propagation/unpropagated/proguard.txt new file mode 100644 index 00000000..2d314d05 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/proguard.txt @@ -0,0 +1,6 @@ +class_1 -> class1Ns0Rename: + class_1 field_1 -> field_1 +class_1$class_2 -> class_1$class_2: + class_1$class_2 field_2 -> field_2 +class_1$class_2$class_3 -> class_1$class_2$class_3: + class_1$class_2$class_3 field_2 -> field_2 diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/recaf-simple.txt b/src/test/resources/outer-class-name-propagation/unpropagated/recaf-simple.txt new file mode 100644 index 00000000..1d71b2fb --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/recaf-simple.txt @@ -0,0 +1,6 @@ +class_1 class1Ns0Rename +class_1.field_1 Lclass_1; field_1 +class_1$class_2 class_1$class_2 +class_1$class_2.field_2 Lclass_1$class_2; field_2 +class_1$class_2$class_3 class_1$class_2$class_3 +class_1$class_2$class_3.field_2 Lclass_1$class_2$class_3; field_2 diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/srg.srg b/src/test/resources/outer-class-name-propagation/unpropagated/srg.srg new file mode 100644 index 00000000..e021678e --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/srg.srg @@ -0,0 +1,6 @@ +CL: class_1 class1Ns0Rename +FD: class_1/field_1 class1Ns0Rename/field_1 +CL: class_1$class_2 class_1$class_2 +FD: class_1$class_2/field_2 class_1$class_2/field_2 +CL: class_1$class_2$class_3 class_1$class_2$class_3 +FD: class_1$class_2$class_3/field_2 class_1$class_2$class_3/field_2 diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/tiny.tiny b/src/test/resources/outer-class-name-propagation/unpropagated/tiny.tiny new file mode 100644 index 00000000..46d09851 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/tiny.tiny @@ -0,0 +1,4 @@ +v1 source dstNs0 dstNs1 dstNs2 dstNs3 dstNs4 dstNs5 dstNs6 +CLASS class_1 class1Ns0Rename class1Ns1Rename class1Ns2Rename class1Ns4Rename +CLASS class_1$class_2 class1Ns2Rename$class2Ns2Rename class_1$class2Ns3Rename class_1$class_2 class_1$class2Ns5Rename +CLASS class_1$class_2$class_3 class_1$class_2$class3Ns5Rename class_1$class_2$class3Ns6Rename diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/tinyV2.tiny b/src/test/resources/outer-class-name-propagation/unpropagated/tinyV2.tiny new file mode 100644 index 00000000..753dbab2 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/tinyV2.tiny @@ -0,0 +1,7 @@ +tiny 2 0 source dstNs0 dstNs1 dstNs2 dstNs3 dstNs4 dstNs5 dstNs6 +c class_1 class1Ns0Rename class1Ns1Rename class1Ns2Rename class1Ns4Rename + f Lclass_1; field_1 +c class_1$class_2 class1Ns2Rename$class2Ns2Rename class_1$class2Ns3Rename class_1$class_2 class_1$class2Ns5Rename + f Lclass_1$class_2; field_2 +c class_1$class_2$class_3 class_1$class_2$class3Ns5Rename class_1$class_2$class3Ns6Rename + f Lclass_1$class_2$class_3; field_2 diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/tsrg.tsrg b/src/test/resources/outer-class-name-propagation/unpropagated/tsrg.tsrg new file mode 100644 index 00000000..502ef552 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/tsrg.tsrg @@ -0,0 +1,6 @@ +class_1 class1Ns0Rename + field_1 field_1 +class_1$class_2 class_1$class_2 + field_2 field_2 +class_1$class_2$class_3 class_1$class_2$class_3 + field_2 field_2 diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/tsrgV2.tsrg b/src/test/resources/outer-class-name-propagation/unpropagated/tsrgV2.tsrg new file mode 100644 index 00000000..49128247 --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/tsrgV2.tsrg @@ -0,0 +1,4 @@ +tsrg2 source dstNs0 dstNs1 dstNs2 dstNs3 dstNs4 dstNs5 dstNs6 +class_1 class1Ns0Rename class1Ns1Rename class1Ns2Rename class_1 class1Ns4Rename class_1 class_1 +class_1$class_2 class_1$class_2 class_1$class_2 class1Ns2Rename$class2Ns2Rename class_1$class2Ns3Rename class_1$class_2 class_1$class2Ns5Rename class_1$class_2 +class_1$class_2$class_3 class_1$class_2$class_3 class_1$class_2$class_3 class_1$class_2$class_3 class_1$class_2$class_3 class_1$class_2$class_3 class_1$class_2$class3Ns5Rename class_1$class_2$class3Ns6Rename diff --git a/src/test/resources/outer-class-name-propagation/unpropagated/xsrg.xsrg b/src/test/resources/outer-class-name-propagation/unpropagated/xsrg.xsrg new file mode 100644 index 00000000..d61ea49b --- /dev/null +++ b/src/test/resources/outer-class-name-propagation/unpropagated/xsrg.xsrg @@ -0,0 +1,6 @@ +CL: class_1 class1Ns0Rename +FD: class_1/field_1 Lclass_1; class1Ns0Rename/field_1 Lclass_1; +CL: class_1$class_2 class_1$class_2 +FD: class_1$class_2/field_2 Lclass_1$class_2; class_1$class_2/field_2 Lclass_1$class_2; +CL: class_1$class_2$class_3 class_1$class_2$class_3 +FD: class_1$class_2$class_3/field_2 Lclass_1$class_2$class_3; class_1$class_2$class_3/field_2 Lclass_1$class_2$class_3; diff --git a/src/test/resources/reading/repeated-elements/enigma-dir/class1Ns0Rename.mapping b/src/test/resources/reading/repeated-elements/enigma-dir/class1Ns0Rename.mapping new file mode 100644 index 00000000..b7edb56b --- /dev/null +++ b/src/test/resources/reading/repeated-elements/enigma-dir/class1Ns0Rename.mapping @@ -0,0 +1,11 @@ +CLASS class_1 class1Ns0Rename + FIELD field_1 field1Ns0Rename0 I + FIELD field_1 field1Ns0Rename I + METHOD method_1 method1Ns0Rename0 ()I + METHOD method_1 method1Ns0Rename ()I + ARG 1 param1Ns0Rename0 + ARG 1 param1Ns0Rename + CLASS class_2 class2Ns0Rename + COMMENT This is a comment + FIELD field_2 field2Ns0Rename0 Lcls; + FIELD field_2 field2Ns0Rename Lcls; diff --git a/src/test/resources/reading/repeated-elements/enigma-dir/package_3/class3Ns0Rename.mapping b/src/test/resources/reading/repeated-elements/enigma-dir/package_3/class3Ns0Rename.mapping new file mode 100644 index 00000000..2c9f1c72 --- /dev/null +++ b/src/test/resources/reading/repeated-elements/enigma-dir/package_3/class3Ns0Rename.mapping @@ -0,0 +1 @@ +CLASS class_3 package_3/class3Ns0Rename