diff options
| author | 2020-07-14 03:24:49 +0800 | |
|---|---|---|
| committer | 2020-07-13 15:24:49 -0400 | |
| commit | 6661dbd70f59c35842d113a14de3c00acf43ef7c (patch) | |
| tree | 683da4299f2ba6a0862b278bdc24897a30c70f0d | |
| parent | Fix array classes not being translated correctly (#293) (diff) | |
| download | enigma-6661dbd70f59c35842d113a14de3c00acf43ef7c.tar.gz enigma-6661dbd70f59c35842d113a14de3c00acf43ef7c.tar.xz enigma-6661dbd70f59c35842d113a14de3c00acf43ef7c.zip | |
Mapping format fixes (#294)
* add test to ensure mapping formats can read/write properly
* fix not baking last entries in TinyV2 reader
* fix broken filter in Enigma File writer
* Fix Enigma Zip writer ZipFS exception on non-matching filesystems
3 files changed, 150 insertions, 10 deletions
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/enigma/EnigmaMappingsWriter.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/enigma/EnigmaMappingsWriter.java index 7570d4b6..378ed984 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/enigma/EnigmaMappingsWriter.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/enigma/EnigmaMappingsWriter.java | |||
| @@ -55,8 +55,8 @@ public enum EnigmaMappingsWriter implements MappingsWriter { | |||
| 55 | @Override | 55 | @Override |
| 56 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { | 56 | public void write(EntryTree<EntryMapping> mappings, MappingDelta<EntryMapping> delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { |
| 57 | Collection<ClassEntry> classes = mappings.getRootNodes() | 57 | Collection<ClassEntry> classes = mappings.getRootNodes() |
| 58 | .filter(entry -> entry instanceof ClassEntry) | 58 | .filter(entry -> entry.getEntry() instanceof ClassEntry) |
| 59 | .map(entry -> (ClassEntry) entry) | 59 | .map(entry -> (ClassEntry) entry.getEntry()) |
| 60 | .collect(Collectors.toList()); | 60 | .collect(Collectors.toList()); |
| 61 | 61 | ||
| 62 | progress.init(classes.size(), I18n.translate("progress.mappings.enigma_file.writing")); | 62 | progress.init(classes.size(), I18n.translate("progress.mappings.enigma_file.writing")); |
| @@ -148,7 +148,7 @@ public enum EnigmaMappingsWriter implements MappingsWriter { | |||
| 148 | private void deleteDeadPackages(Path root, Path packagePath) throws IOException { | 148 | private void deleteDeadPackages(Path root, Path packagePath) throws IOException { |
| 149 | for (int i = packagePath.getNameCount() - 1; i >= 0; i--) { | 149 | for (int i = packagePath.getNameCount() - 1; i >= 0; i--) { |
| 150 | Path subPath = packagePath.subpath(0, i + 1); | 150 | Path subPath = packagePath.subpath(0, i + 1); |
| 151 | Path packagePart = root.resolve(subPath); | 151 | Path packagePart = root.resolve(subPath.toString()); |
| 152 | if (isEmpty(packagePart)) { | 152 | if (isEmpty(packagePart)) { |
| 153 | Files.deleteIfExists(packagePart); | 153 | Files.deleteIfExists(packagePart); |
| 154 | } | 154 | } |
diff --git a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tinyv2/TinyV2Reader.java b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tinyv2/TinyV2Reader.java index dc255693..dc3246de 100644 --- a/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tinyv2/TinyV2Reader.java +++ b/enigma/src/main/java/cuchaz/enigma/translation/mapping/serde/tinyv2/TinyV2Reader.java | |||
| @@ -71,13 +71,7 @@ public final class TinyV2Reader implements MappingsReader { | |||
| 71 | for (int i = INDENT_CLEAR_START[indent]; i < STATE_SIZE; i++) { | 71 | for (int i = INDENT_CLEAR_START[indent]; i < STATE_SIZE; i++) { |
| 72 | state.clear(i); | 72 | state.clear(i); |
| 73 | if (holds[i] != null) { | 73 | if (holds[i] != null) { |
| 74 | RawEntryMapping mapping = holds[i].getMapping(); | 74 | bakeHeld(mappings, holds[i]); |
| 75 | if (mapping != null) { | ||
| 76 | EntryMapping baked = mapping.bake(); | ||
| 77 | if (baked != null) { | ||
| 78 | mappings.insert(holds[i].getEntry(), baked); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | holds[i] = null; | 75 | holds[i] = null; |
| 82 | } | 76 | } |
| 83 | } | 77 | } |
| @@ -187,9 +181,26 @@ public final class TinyV2Reader implements MappingsReader { | |||
| 187 | } | 181 | } |
| 188 | } | 182 | } |
| 189 | 183 | ||
| 184 | //bake any remainders | ||
| 185 | for (MappingPair<? extends Entry<?>, RawEntryMapping> hold : holds) { | ||
| 186 | if (hold != null) { | ||
| 187 | bakeHeld(mappings, hold); | ||
| 188 | } | ||
| 189 | } | ||
| 190 | |||
| 190 | return mappings; | 191 | return mappings; |
| 191 | } | 192 | } |
| 192 | 193 | ||
| 194 | private static void bakeHeld(EntryTree<EntryMapping> mappings, MappingPair<? extends Entry<?>, RawEntryMapping> hold2) { | ||
| 195 | RawEntryMapping mapping = hold2.getMapping(); | ||
| 196 | if (mapping != null) { | ||
| 197 | EntryMapping baked = mapping.bake(); | ||
| 198 | if (baked != null) { | ||
| 199 | mappings.insert(hold2.getEntry(), baked); | ||
| 200 | } | ||
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 193 | private void unsupportKey(String[] parts) { | 204 | private void unsupportKey(String[] parts) { |
| 194 | throw new IllegalArgumentException("Unsupported key " + parts[0]); | 205 | throw new IllegalArgumentException("Unsupported key " + parts[0]); |
| 195 | } | 206 | } |
diff --git a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestReadWriteCycle.java b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestReadWriteCycle.java new file mode 100644 index 00000000..4f6654a4 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestReadWriteCycle.java | |||
| @@ -0,0 +1,129 @@ | |||
| 1 | package cuchaz.enigma.translation.mapping; | ||
| 2 | |||
| 3 | import cuchaz.enigma.ProgressListener; | ||
| 4 | import cuchaz.enigma.translation.mapping.serde.MappingFileNameFormat; | ||
| 5 | import cuchaz.enigma.translation.mapping.serde.MappingFormat; | ||
| 6 | import cuchaz.enigma.translation.mapping.serde.MappingParseException; | ||
| 7 | import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; | ||
| 8 | import cuchaz.enigma.translation.mapping.tree.EntryTree; | ||
| 9 | import cuchaz.enigma.translation.mapping.tree.HashEntryTree; | ||
| 10 | import cuchaz.enigma.translation.representation.entry.ClassEntry; | ||
| 11 | import cuchaz.enigma.translation.representation.entry.Entry; | ||
| 12 | import cuchaz.enigma.translation.representation.entry.FieldEntry; | ||
| 13 | import cuchaz.enigma.translation.representation.entry.MethodEntry; | ||
| 14 | import cuchaz.enigma.utils.Pair; | ||
| 15 | import org.junit.Assert; | ||
| 16 | import org.junit.Test; | ||
| 17 | |||
| 18 | import java.io.File; | ||
| 19 | import java.io.IOException; | ||
| 20 | |||
| 21 | /** | ||
| 22 | * Tests that a MappingFormat can write out a fixed set of mappings and read them back without losing any information. | ||
| 23 | * Javadoc skipped for Tiny (v1) as it doesn't support them. | ||
| 24 | */ | ||
| 25 | public class TestReadWriteCycle { | ||
| 26 | |||
| 27 | private final MappingSaveParameters parameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF); | ||
| 28 | |||
| 29 | private final Pair<ClassEntry, EntryMapping> testClazz = new Pair<>( | ||
| 30 | new ClassEntry("a/b/c"), | ||
| 31 | new EntryMapping("alpha/beta/charlie", "this is a test class") | ||
| 32 | ); | ||
| 33 | |||
| 34 | private final Pair<FieldEntry, EntryMapping> testField1 = new Pair<>( | ||
| 35 | FieldEntry.parse("a/b/c", "field1", "I"), | ||
| 36 | new EntryMapping("mapped1", "this is field 1") | ||
| 37 | ); | ||
| 38 | |||
| 39 | private final Pair<FieldEntry, EntryMapping> testField2 = new Pair<>( | ||
| 40 | FieldEntry.parse("a/b/c", "field2", "I"), | ||
| 41 | new EntryMapping("mapped2", "this is field 2") | ||
| 42 | ); | ||
| 43 | |||
| 44 | private final Pair<MethodEntry, EntryMapping> testMethod1 = new Pair<>( | ||
| 45 | MethodEntry.parse("a/b/c", "method1", "()V"), | ||
| 46 | new EntryMapping("mapped3", "this is method1") | ||
| 47 | ); | ||
| 48 | |||
| 49 | private final Pair<MethodEntry, EntryMapping> testMethod2 = new Pair<>( | ||
| 50 | MethodEntry.parse("a/b/c", "method2", "()V"), | ||
| 51 | new EntryMapping("mapped4", "this is method 2") | ||
| 52 | ); | ||
| 53 | |||
| 54 | private void insertMapping(EntryTree<EntryMapping> mappings, Pair<? extends Entry<?>, EntryMapping> mappingPair){ | ||
| 55 | mappings.insert(mappingPair.a, mappingPair.b); | ||
| 56 | } | ||
| 57 | |||
| 58 | private void testReadWriteCycle(MappingFormat mappingFormat, boolean supportsJavadoc, String tmpNameSuffix) throws IOException, MappingParseException { | ||
| 59 | //construct some known mappings to test with | ||
| 60 | EntryTree<EntryMapping> testMappings = new HashEntryTree<>(); | ||
| 61 | insertMapping(testMappings, testClazz); | ||
| 62 | insertMapping(testMappings, testField1); | ||
| 63 | insertMapping(testMappings, testField2); | ||
| 64 | insertMapping(testMappings, testMethod1); | ||
| 65 | insertMapping(testMappings, testMethod2); | ||
| 66 | |||
| 67 | Assert.assertTrue("Test mapping insertion failed: testClazz", testMappings.contains(testClazz.a)); | ||
| 68 | Assert.assertTrue("Test mapping insertion failed: testField1", testMappings.contains(testField1.a)); | ||
| 69 | Assert.assertTrue("Test mapping insertion failed: testField2", testMappings.contains(testField2.a)); | ||
| 70 | Assert.assertTrue("Test mapping insertion failed: testMethod1", testMappings.contains(testMethod1.a)); | ||
| 71 | Assert.assertTrue("Test mapping insertion failed: testMethod2", testMappings.contains(testMethod2.a)); | ||
| 72 | |||
| 73 | File tempFile = File.createTempFile("readWriteCycle", tmpNameSuffix); | ||
| 74 | tempFile.delete();//remove the auto created file | ||
| 75 | |||
| 76 | |||
| 77 | mappingFormat.write(testMappings, tempFile.toPath(), ProgressListener.none(), parameters); | ||
| 78 | Assert.assertTrue("Written file not created", tempFile.exists()); | ||
| 79 | |||
| 80 | EntryTree<EntryMapping> loadedMappings = mappingFormat.read(tempFile.toPath(), ProgressListener.none(), parameters); | ||
| 81 | |||
| 82 | Assert.assertTrue("Loaded mappings don't contain testClazz", loadedMappings.contains(testClazz.a)); | ||
| 83 | Assert.assertTrue("Loaded mappings don't contain testField1", loadedMappings.contains(testField1.a)); | ||
| 84 | Assert.assertTrue("Loaded mappings don't contain testField2", loadedMappings.contains(testField2.a)); | ||
| 85 | Assert.assertTrue("Loaded mappings don't contain testMethod1", loadedMappings.contains(testMethod1.a)); | ||
| 86 | Assert.assertTrue("Loaded mappings don't contain testMethod2", loadedMappings.contains(testMethod2.a)); | ||
| 87 | |||
| 88 | Assert.assertEquals("Incorrect mapping: testClazz", testClazz.b.getTargetName(), loadedMappings.get(testClazz.a).getTargetName()); | ||
| 89 | Assert.assertEquals("Incorrect mapping: testField1", testField1.b.getTargetName(), loadedMappings.get(testField1.a).getTargetName()); | ||
| 90 | Assert.assertEquals("Incorrect mapping: testField2", testField2.b.getTargetName(), loadedMappings.get(testField2.a).getTargetName()); | ||
| 91 | Assert.assertEquals("Incorrect mapping: testMethod1", testMethod1.b.getTargetName(), loadedMappings.get(testMethod1.a).getTargetName()); | ||
| 92 | Assert.assertEquals("Incorrect mapping: testMethod2", testMethod2.b.getTargetName(), loadedMappings.get(testMethod2.a).getTargetName()); | ||
| 93 | |||
| 94 | if (supportsJavadoc) { | ||
| 95 | Assert.assertEquals("Incorrect javadoc: testClazz", testClazz.b.getJavadoc(), loadedMappings.get(testClazz.a).getJavadoc()); | ||
| 96 | Assert.assertEquals("Incorrect javadoc: testField1", testField1.b.getJavadoc(), loadedMappings.get(testField1.a).getJavadoc()); | ||
| 97 | Assert.assertEquals("Incorrect javadoc: testField2", testField2.b.getJavadoc(), loadedMappings.get(testField2.a).getJavadoc()); | ||
| 98 | Assert.assertEquals("Incorrect javadoc: testMethod1", testMethod1.b.getJavadoc(), loadedMappings.get(testMethod1.a).getJavadoc()); | ||
| 99 | Assert.assertEquals("Incorrect javadoc: testMethod2", testMethod2.b.getJavadoc(), loadedMappings.get(testMethod2.a).getJavadoc()); | ||
| 100 | } | ||
| 101 | |||
| 102 | tempFile.delete(); | ||
| 103 | } | ||
| 104 | |||
| 105 | @Test | ||
| 106 | public void testEnigmaFile() throws IOException, MappingParseException { | ||
| 107 | testReadWriteCycle(MappingFormat.ENIGMA_FILE, true, ".enigma"); | ||
| 108 | } | ||
| 109 | |||
| 110 | @Test | ||
| 111 | public void testEnigmaDir() throws IOException, MappingParseException { | ||
| 112 | testReadWriteCycle(MappingFormat.ENIGMA_DIRECTORY, true, ".tmp"); | ||
| 113 | } | ||
| 114 | |||
| 115 | @Test | ||
| 116 | public void testEnigmaZip() throws IOException, MappingParseException { | ||
| 117 | testReadWriteCycle(MappingFormat.ENIGMA_ZIP, true, ".zip"); | ||
| 118 | } | ||
| 119 | |||
| 120 | @Test | ||
| 121 | public void testTinyFile() throws IOException, MappingParseException { | ||
| 122 | testReadWriteCycle(MappingFormat.TINY_FILE, false, ".tiny"); | ||
| 123 | } | ||
| 124 | |||
| 125 | @Test | ||
| 126 | public void testTinyV2() throws IOException, MappingParseException { | ||
| 127 | testReadWriteCycle(MappingFormat.TINY_V2, true, ".tinyv2"); | ||
| 128 | } | ||
| 129 | } | ||