From 0f47403d0220757fed189b76e2071e25b1025cb8 Mon Sep 17 00:00:00 2001 From: Runemoro Date: Wed, 3 Jun 2020 13:39:42 -0400 Subject: Split GUI code to separate module (#242) * Split into modules * Post merge compile fixes Co-authored-by: modmuss50 --- .../cuchaz/enigma/PackageVisibilityIndexTest.java | 53 +++++ .../src/test/java/cuchaz/enigma/TestDeobfed.java | 106 +++++++++ .../test/java/cuchaz/enigma/TestDeobfuscator.java | 41 ++++ .../test/java/cuchaz/enigma/TestEntryFactory.java | 49 ++++ .../test/java/cuchaz/enigma/TestInnerClasses.java | 85 +++++++ .../enigma/TestJarIndexConstructorReferences.java | 124 +++++++++++ .../cuchaz/enigma/TestJarIndexInheritanceTree.java | 227 +++++++++++++++++++ .../java/cuchaz/enigma/TestJarIndexLoneClass.java | 157 +++++++++++++ .../java/cuchaz/enigma/TestMethodDescriptor.java | 247 +++++++++++++++++++++ .../java/cuchaz/enigma/TestTokensConstructors.java | 137 ++++++++++++ .../test/java/cuchaz/enigma/TestTranslator.java | 155 +++++++++++++ .../java/cuchaz/enigma/TestTypeDescriptor.java | 243 ++++++++++++++++++++ .../src/test/java/cuchaz/enigma/TokenChecker.java | 65 ++++++ .../src/test/java/cuchaz/enigma/inputs/Keep.java | 18 ++ .../enigma/inputs/constructors/BaseClass.java | 26 +++ .../cuchaz/enigma/inputs/constructors/Caller.java | 58 +++++ .../inputs/constructors/DefaultConstructable.java | 16 ++ .../enigma/inputs/constructors/SubClass.java | 39 ++++ .../enigma/inputs/constructors/SubSubClass.java | 22 ++ .../enigma/inputs/inheritanceTree/BaseClass.java | 32 +++ .../enigma/inputs/inheritanceTree/SubclassA.java | 22 ++ .../enigma/inputs/inheritanceTree/SubclassB.java | 41 ++++ .../inputs/inheritanceTree/SubsubclassAA.java | 35 +++ .../enigma/inputs/innerClasses/A_Anonymous.java | 25 +++ .../innerClasses/B_AnonymousWithScopeArgs.java | 24 ++ .../inputs/innerClasses/C_ConstructorArgs.java | 31 +++ .../enigma/inputs/innerClasses/D_Simple.java | 19 ++ .../innerClasses/E_AnonymousWithOuterAccess.java | 32 +++ .../enigma/inputs/innerClasses/F_ClassTree.java | 30 +++ .../cuchaz/enigma/inputs/loneClass/LoneClass.java | 25 +++ .../cuchaz/enigma/inputs/packageAccess/Base.java | 7 + .../inputs/packageAccess/SamePackageChild.java | 12 + .../packageAccess/sub/OtherPackageChild.java | 14 ++ .../cuchaz/enigma/inputs/translation/A_Basic.java | 33 +++ .../enigma/inputs/translation/B_BaseClass.java | 26 +++ .../enigma/inputs/translation/C_SubClass.java | 28 +++ .../inputs/translation/D_AnonymousTesting.java | 29 +++ .../enigma/inputs/translation/E_Bridges.java | 32 +++ .../enigma/inputs/translation/F_ObjectMethods.java | 31 +++ .../enigma/inputs/translation/G_OuterClass.java | 36 +++ .../enigma/inputs/translation/H_NamelessClass.java | 40 ++++ .../enigma/inputs/translation/I_Generics.java | 35 +++ .../enigma/translation/mapping/TestComments.java | 39 ++++ .../mapping/TestTinyV2InnerClasses.java | 37 +++ .../enigma/translation/mapping/TestV2Main.java | 23 ++ 45 files changed, 2606 insertions(+) create mode 100644 enigma/src/test/java/cuchaz/enigma/PackageVisibilityIndexTest.java create mode 100644 enigma/src/test/java/cuchaz/enigma/TestDeobfed.java create mode 100644 enigma/src/test/java/cuchaz/enigma/TestDeobfuscator.java create mode 100644 enigma/src/test/java/cuchaz/enigma/TestEntryFactory.java create mode 100644 enigma/src/test/java/cuchaz/enigma/TestInnerClasses.java create mode 100644 enigma/src/test/java/cuchaz/enigma/TestJarIndexConstructorReferences.java create mode 100644 enigma/src/test/java/cuchaz/enigma/TestJarIndexInheritanceTree.java create mode 100644 enigma/src/test/java/cuchaz/enigma/TestJarIndexLoneClass.java create mode 100644 enigma/src/test/java/cuchaz/enigma/TestMethodDescriptor.java create mode 100644 enigma/src/test/java/cuchaz/enigma/TestTokensConstructors.java create mode 100644 enigma/src/test/java/cuchaz/enigma/TestTranslator.java create mode 100644 enigma/src/test/java/cuchaz/enigma/TestTypeDescriptor.java create mode 100644 enigma/src/test/java/cuchaz/enigma/TokenChecker.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/Keep.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/constructors/BaseClass.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/constructors/Caller.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/constructors/DefaultConstructable.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/constructors/SubClass.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/constructors/SubSubClass.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/D_Simple.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/F_ClassTree.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/loneClass/LoneClass.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/packageAccess/Base.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/packageAccess/SamePackageChild.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/packageAccess/sub/OtherPackageChild.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/translation/A_Basic.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/translation/B_BaseClass.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/translation/C_SubClass.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/translation/D_AnonymousTesting.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/translation/E_Bridges.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/translation/F_ObjectMethods.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/translation/G_OuterClass.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/translation/H_NamelessClass.java create mode 100644 enigma/src/test/java/cuchaz/enigma/inputs/translation/I_Generics.java create mode 100644 enigma/src/test/java/cuchaz/enigma/translation/mapping/TestComments.java create mode 100644 enigma/src/test/java/cuchaz/enigma/translation/mapping/TestTinyV2InnerClasses.java create mode 100644 enigma/src/test/java/cuchaz/enigma/translation/mapping/TestV2Main.java (limited to 'enigma/src/test/java') diff --git a/enigma/src/test/java/cuchaz/enigma/PackageVisibilityIndexTest.java b/enigma/src/test/java/cuchaz/enigma/PackageVisibilityIndexTest.java new file mode 100644 index 0000000..1dc9748 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/PackageVisibilityIndexTest.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import cuchaz.enigma.analysis.ClassCache; +import cuchaz.enigma.analysis.index.JarIndex; +import cuchaz.enigma.analysis.index.PackageVisibilityIndex; +import cuchaz.enigma.translation.representation.entry.ClassEntry; +import org.junit.Test; + +import java.nio.file.Paths; + +import static cuchaz.enigma.TestEntryFactory.newClass; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; + +public class PackageVisibilityIndexTest { + + private static final ClassEntry KEEP = newClass("cuchaz/enigma/inputs/Keep"); + private static final ClassEntry BASE = newClass("a"); + private static final ClassEntry SAME_PACKAGE_CHILD = newClass("b"); + private static final ClassEntry SAME_PACKAGE_CHILD_INNER = newClass("b$a"); + private static final ClassEntry OTHER_PACKAGE_CHILD = newClass("c"); + private static final ClassEntry OTHER_PACKAGE_CHILD_INNER = newClass("c$a"); + private final JarIndex jarIndex; + + public PackageVisibilityIndexTest() throws Exception { + ClassCache classCache = ClassCache.of(Paths.get("build/test-obf/packageAccess.jar")); + jarIndex = classCache.index(ProgressListener.none()); + } + + @Test + public void test() { + PackageVisibilityIndex visibilityIndex = jarIndex.getPackageVisibilityIndex(); + assertThat(visibilityIndex.getPartition(BASE), containsInAnyOrder(BASE, SAME_PACKAGE_CHILD, SAME_PACKAGE_CHILD_INNER)); + System.out.println(visibilityIndex.getPartitions()); + assertThat(visibilityIndex.getPartitions(), containsInAnyOrder( + containsInAnyOrder(BASE, SAME_PACKAGE_CHILD, SAME_PACKAGE_CHILD_INNER), + containsInAnyOrder(OTHER_PACKAGE_CHILD, OTHER_PACKAGE_CHILD_INNER), + contains(KEEP) + )); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/TestDeobfed.java b/enigma/src/test/java/cuchaz/enigma/TestDeobfed.java new file mode 100644 index 0000000..494d959 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/TestDeobfed.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import cuchaz.enigma.analysis.ClassCache; +import cuchaz.enigma.analysis.index.JarIndex; +import cuchaz.enigma.source.Decompiler; +import cuchaz.enigma.source.Decompilers; +import cuchaz.enigma.source.SourceSettings; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static cuchaz.enigma.TestEntryFactory.newClass; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; + +public class TestDeobfed { + private static Enigma enigma; + private static ClassCache classCache; + private static JarIndex index; + + @BeforeClass + public static void beforeClass() throws Exception { + enigma = Enigma.create(); + + Path obf = Paths.get("build/test-obf/translation.jar"); + Path deobf = Paths.get("build/test-deobf/translation.jar"); + Files.createDirectories(deobf.getParent()); + EnigmaProject project = enigma.openJar(obf, ProgressListener.none()); + project.exportRemappedJar(ProgressListener.none()).write(deobf, ProgressListener.none()); + + classCache = ClassCache.of(deobf); + index = classCache.index(ProgressListener.none()); + } + + @Test + public void obfEntries() { + assertThat(index.getEntryIndex().getClasses(), containsInAnyOrder( + newClass("cuchaz/enigma/inputs/Keep"), + newClass("a"), + newClass("b"), + newClass("c"), + newClass("d"), + newClass("d$1"), + newClass("e"), + newClass("f"), + newClass("g"), + newClass("g$a"), + newClass("g$a$a"), + newClass("g$b"), + newClass("g$b$a"), + newClass("h"), + newClass("h$a"), + newClass("h$a$a"), + newClass("h$b"), + newClass("h$b$a"), + newClass("h$b$a$a"), + newClass("h$b$a$b"), + newClass("i"), + newClass("i$a"), + newClass("i$b") + )); + } + + @Test + public void decompile() { + EnigmaProject project = new EnigmaProject(enigma, classCache, index, new byte[20]); + Decompiler decompiler = Decompilers.PROCYON.create(project.getClassCache(), new SourceSettings(false, false)); + + decompiler.getSource("a"); + decompiler.getSource("b"); + decompiler.getSource("c"); + decompiler.getSource("d"); + decompiler.getSource("d$1"); + decompiler.getSource("e"); + decompiler.getSource("f"); + decompiler.getSource("g"); + decompiler.getSource("g$a"); + decompiler.getSource("g$a$a"); + decompiler.getSource("g$b"); + decompiler.getSource("g$b$a"); + decompiler.getSource("h"); + decompiler.getSource("h$a"); + decompiler.getSource("h$a$a"); + decompiler.getSource("h$b"); + decompiler.getSource("h$b$a"); + decompiler.getSource("h$b$a$a"); + decompiler.getSource("h$b$a$b"); + decompiler.getSource("i"); + decompiler.getSource("i$a"); + decompiler.getSource("i$b"); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/TestDeobfuscator.java b/enigma/src/test/java/cuchaz/enigma/TestDeobfuscator.java new file mode 100644 index 0000000..6619d26 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/TestDeobfuscator.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import cuchaz.enigma.source.Decompiler; +import cuchaz.enigma.source.Decompilers; +import cuchaz.enigma.source.SourceSettings; +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Paths; + +public class TestDeobfuscator { + private EnigmaProject openProject() throws IOException { + Enigma enigma = Enigma.create(); + return enigma.openJar(Paths.get("build/test-obf/loneClass.jar"), ProgressListener.none()); + } + + @Test + public void loadJar() + throws Exception { + openProject(); + } + + @Test + public void decompileClass() throws Exception { + EnigmaProject project = openProject(); + Decompiler decompiler = Decompilers.PROCYON.create(project.getClassCache(), new SourceSettings(false, false)); + + decompiler.getSource("a").asString(); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/TestEntryFactory.java b/enigma/src/test/java/cuchaz/enigma/TestEntryFactory.java new file mode 100644 index 0000000..9e1425a --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/TestEntryFactory.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import cuchaz.enigma.analysis.EntryReference; +import cuchaz.enigma.translation.representation.*; +import cuchaz.enigma.translation.representation.entry.ClassEntry; +import cuchaz.enigma.translation.representation.entry.FieldEntry; +import cuchaz.enigma.translation.representation.entry.MethodEntry; + +public class TestEntryFactory { + + public static ClassEntry newClass(String name) { + return new ClassEntry(name); + } + + public static FieldEntry newField(String className, String fieldName, String fieldType) { + return newField(newClass(className), fieldName, fieldType); + } + + public static FieldEntry newField(ClassEntry classEntry, String fieldName, String fieldType) { + return new FieldEntry(classEntry, fieldName, new TypeDescriptor(fieldType)); + } + + public static MethodEntry newMethod(String className, String methodName, String methodSignature) { + return newMethod(newClass(className), methodName, methodSignature); + } + + public static MethodEntry newMethod(ClassEntry classEntry, String methodName, String methodSignature) { + return new MethodEntry(classEntry, methodName, new MethodDescriptor(methodSignature)); + } + + public static EntryReference newFieldReferenceByMethod(FieldEntry fieldEntry, String callerClassName, String callerName, String callerSignature) { + return new EntryReference<>(fieldEntry, "", newMethod(callerClassName, callerName, callerSignature)); + } + + public static EntryReference newBehaviorReferenceByMethod(MethodEntry methodEntry, String callerClassName, String callerName, String callerSignature) { + return new EntryReference<>(methodEntry, "", newMethod(callerClassName, callerName, callerSignature)); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/TestInnerClasses.java b/enigma/src/test/java/cuchaz/enigma/TestInnerClasses.java new file mode 100644 index 0000000..85c72f8 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/TestInnerClasses.java @@ -0,0 +1,85 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import cuchaz.enigma.analysis.ClassCache; +import cuchaz.enigma.analysis.index.JarIndex; +import cuchaz.enigma.source.Decompiler; +import cuchaz.enigma.source.Decompilers; +import cuchaz.enigma.source.SourceSettings; +import cuchaz.enigma.translation.representation.entry.ClassEntry; +import org.junit.Test; + +import java.nio.file.Paths; + +import static cuchaz.enigma.TestEntryFactory.newClass; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +public class TestInnerClasses { + + private static final ClassEntry SimpleOuter = newClass("d"); + private static final ClassEntry SimpleInner = newClass("d$a"); + private static final ClassEntry ConstructorArgsOuter = newClass("c"); + private static final ClassEntry ConstructorArgsInner = newClass("c$a"); + private static final ClassEntry ClassTreeRoot = newClass("f"); + private static final ClassEntry ClassTreeLevel1 = newClass("f$a"); + private static final ClassEntry ClassTreeLevel2 = newClass("f$a$a"); + private static final ClassEntry ClassTreeLevel3 = newClass("f$a$a$a"); + private final JarIndex index; + private final Decompiler decompiler; + + public TestInnerClasses() throws Exception { + ClassCache classCache = ClassCache.of(Paths.get("build/test-obf/innerClasses.jar")); + index = classCache.index(ProgressListener.none()); + decompiler = Decompilers.PROCYON.create(classCache, new SourceSettings(false, false)); + } + + @Test + public void simple() { + decompile(SimpleOuter); + } + + @Test + public void constructorArgs() { + decompile(ConstructorArgsOuter); + } + + @Test + public void classTree() { + + // root level + assertThat(index.getEntryIndex().hasClass(ClassTreeRoot), is(true)); + + // level 1 + ClassEntry fullClassEntry = new ClassEntry(ClassTreeRoot.getName() + + "$" + ClassTreeLevel1.getSimpleName()); + assertThat(index.getEntryIndex().hasClass(fullClassEntry), is(true)); + + // level 2 + fullClassEntry = new ClassEntry(ClassTreeRoot.getName() + + "$" + ClassTreeLevel1.getSimpleName() + + "$" + ClassTreeLevel2.getSimpleName()); + assertThat(index.getEntryIndex().hasClass(fullClassEntry), is(true)); + + // level 3 + fullClassEntry = new ClassEntry(ClassTreeRoot.getName() + + "$" + ClassTreeLevel1.getSimpleName() + + "$" + ClassTreeLevel2.getSimpleName() + + "$" + ClassTreeLevel3.getSimpleName()); + assertThat(index.getEntryIndex().hasClass(fullClassEntry), is(true)); + } + + private void decompile(ClassEntry classEntry) { + decompiler.getSource(classEntry.getName()); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/TestJarIndexConstructorReferences.java b/enigma/src/test/java/cuchaz/enigma/TestJarIndexConstructorReferences.java new file mode 100644 index 0000000..48975c8 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/TestJarIndexConstructorReferences.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import cuchaz.enigma.analysis.ClassCache; +import cuchaz.enigma.analysis.EntryReference; +import cuchaz.enigma.analysis.index.JarIndex; +import cuchaz.enigma.translation.representation.entry.ClassEntry; +import cuchaz.enigma.translation.representation.entry.MethodDefEntry; +import cuchaz.enigma.translation.representation.entry.MethodEntry; +import org.junit.Test; + +import java.nio.file.Paths; +import java.util.Collection; + +import static cuchaz.enigma.TestEntryFactory.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class TestJarIndexConstructorReferences { + + private JarIndex index; + + private ClassEntry baseClass = newClass("a"); + private ClassEntry subClass = newClass("d"); + private ClassEntry subsubClass = newClass("e"); + private ClassEntry defaultClass = newClass("c"); + private ClassEntry callerClass = newClass("b"); + + public TestJarIndexConstructorReferences() throws Exception { + ClassCache classCache = ClassCache.of(Paths.get("build/test-obf/constructors.jar")); + index = classCache.index(ProgressListener.none()); + } + + @Test + public void obfEntries() { + assertThat(index.getEntryIndex().getClasses(), containsInAnyOrder(newClass("cuchaz/enigma/inputs/Keep"), baseClass, + subClass, subsubClass, defaultClass, callerClass)); + } + + @Test + @SuppressWarnings("unchecked") + public void baseDefault() { + MethodEntry source = newMethod(baseClass, "", "()V"); + Collection> references = index.getReferenceIndex().getReferencesToMethod(source); + assertThat(references, containsInAnyOrder( + newBehaviorReferenceByMethod(source, callerClass.getName(), "a", "()V"), + newBehaviorReferenceByMethod(source, subClass.getName(), "", "()V"), + newBehaviorReferenceByMethod(source, subClass.getName(), "", "(III)V") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void baseInt() { + MethodEntry source = newMethod(baseClass, "", "(I)V"); + assertThat(index.getReferenceIndex().getReferencesToMethod(source), containsInAnyOrder( + newBehaviorReferenceByMethod(source, callerClass.getName(), "b", "()V") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void subDefault() { + MethodEntry source = newMethod(subClass, "", "()V"); + assertThat(index.getReferenceIndex().getReferencesToMethod(source), containsInAnyOrder( + newBehaviorReferenceByMethod(source, callerClass.getName(), "c", "()V"), + newBehaviorReferenceByMethod(source, subClass.getName(), "", "(I)V") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void subInt() { + MethodEntry source = newMethod(subClass, "", "(I)V"); + assertThat(index.getReferenceIndex().getReferencesToMethod(source), containsInAnyOrder( + newBehaviorReferenceByMethod(source, callerClass.getName(), "d", "()V"), + newBehaviorReferenceByMethod(source, subClass.getName(), "", "(II)V"), + newBehaviorReferenceByMethod(source, subsubClass.getName(), "", "(I)V") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void subIntInt() { + MethodEntry source = newMethod(subClass, "", "(II)V"); + assertThat(index.getReferenceIndex().getReferencesToMethod(source), containsInAnyOrder( + newBehaviorReferenceByMethod(source, callerClass.getName(), "e", "()V") + )); + } + + @Test + public void subIntIntInt() { + MethodEntry source = newMethod(subClass, "", "(III)V"); + assertThat(index.getReferenceIndex().getReferencesToMethod(source), is(empty())); + } + + @Test + @SuppressWarnings("unchecked") + public void subsubInt() { + MethodEntry source = newMethod(subsubClass, "", "(I)V"); + assertThat(index.getReferenceIndex().getReferencesToMethod(source), containsInAnyOrder( + newBehaviorReferenceByMethod(source, callerClass.getName(), "f", "()V") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void defaultConstructable() { + MethodEntry source = newMethod(defaultClass, "", "()V"); + assertThat(index.getReferenceIndex().getReferencesToMethod(source), containsInAnyOrder( + newBehaviorReferenceByMethod(source, callerClass.getName(), "g", "()V") + )); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/TestJarIndexInheritanceTree.java b/enigma/src/test/java/cuchaz/enigma/TestJarIndexInheritanceTree.java new file mode 100644 index 0000000..76e379c --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/TestJarIndexInheritanceTree.java @@ -0,0 +1,227 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import cuchaz.enigma.analysis.ClassCache; +import cuchaz.enigma.analysis.EntryReference; +import cuchaz.enigma.analysis.index.EntryIndex; +import cuchaz.enigma.analysis.index.InheritanceIndex; +import cuchaz.enigma.analysis.index.JarIndex; +import cuchaz.enigma.translation.mapping.EntryResolver; +import cuchaz.enigma.translation.mapping.IndexEntryResolver; +import cuchaz.enigma.translation.representation.AccessFlags; +import cuchaz.enigma.translation.representation.entry.ClassEntry; +import cuchaz.enigma.translation.representation.entry.FieldEntry; +import cuchaz.enigma.translation.representation.entry.MethodDefEntry; +import cuchaz.enigma.translation.representation.entry.MethodEntry; +import org.junit.Test; +import org.objectweb.asm.Opcodes; + +import java.nio.file.Paths; +import java.util.Collection; + +import static cuchaz.enigma.TestEntryFactory.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class TestJarIndexInheritanceTree { + + private JarIndex index; + + private ClassEntry baseClass = newClass("a"); + private ClassEntry subClassA = newClass("b"); + private ClassEntry subClassAA = newClass("d"); + private ClassEntry subClassB = newClass("c"); + private FieldEntry nameField = newField(baseClass, "a", "Ljava/lang/String;"); + private FieldEntry numThingsField = newField(subClassB, "a", "I"); + + public TestJarIndexInheritanceTree() + throws Exception { + ClassCache classCache = ClassCache.of(Paths.get("build/test-obf/inheritanceTree.jar")); + index = classCache.index(ProgressListener.none()); + } + + @Test + public void obfEntries() { + assertThat(index.getEntryIndex().getClasses(), containsInAnyOrder( + newClass("cuchaz/enigma/inputs/Keep"), baseClass, subClassA, subClassAA, subClassB + )); + } + + @Test + public void translationIndex() { + + InheritanceIndex index = this.index.getInheritanceIndex(); + + // base class + assertThat(index.getParents(baseClass), is(empty())); + assertThat(index.getAncestors(baseClass), is(empty())); + assertThat(index.getChildren(baseClass), containsInAnyOrder(subClassA, subClassB + )); + + // subclass a + assertThat(index.getParents(subClassA), contains(baseClass)); + assertThat(index.getAncestors(subClassA), containsInAnyOrder(baseClass)); + assertThat(index.getChildren(subClassA), contains(subClassAA)); + + // subclass aa + assertThat(index.getParents(subClassAA), contains(subClassA)); + assertThat(index.getAncestors(subClassAA), containsInAnyOrder(subClassA, baseClass)); + assertThat(index.getChildren(subClassAA), is(empty())); + + // subclass b + assertThat(index.getParents(subClassB), contains(baseClass)); + assertThat(index.getAncestors(subClassB), containsInAnyOrder(baseClass)); + assertThat(index.getChildren(subClassB), is(empty())); + } + + @Test + public void access() { + assertThat(index.getEntryIndex().getFieldAccess(nameField), is(new AccessFlags(Opcodes.ACC_PRIVATE))); + assertThat(index.getEntryIndex().getFieldAccess(numThingsField), is(new AccessFlags(Opcodes.ACC_PRIVATE))); + } + + @Test + public void relatedMethodImplementations() { + + Collection entries; + + EntryResolver resolver = new IndexEntryResolver(index); + // getName() + entries = resolver.resolveEquivalentMethods(newMethod(baseClass, "a", "()Ljava/lang/String;")); + assertThat(entries, containsInAnyOrder( + newMethod(baseClass, "a", "()Ljava/lang/String;"), + newMethod(subClassAA, "a", "()Ljava/lang/String;") + )); + entries = resolver.resolveEquivalentMethods(newMethod(subClassAA, "a", "()Ljava/lang/String;")); + assertThat(entries, containsInAnyOrder( + newMethod(baseClass, "a", "()Ljava/lang/String;"), + newMethod(subClassAA, "a", "()Ljava/lang/String;") + )); + + // doBaseThings() + entries = resolver.resolveEquivalentMethods(newMethod(baseClass, "a", "()V")); + assertThat(entries, containsInAnyOrder( + newMethod(baseClass, "a", "()V"), + newMethod(subClassAA, "a", "()V"), + newMethod(subClassB, "a", "()V") + )); + entries = resolver.resolveEquivalentMethods(newMethod(subClassAA, "a", "()V")); + assertThat(entries, containsInAnyOrder( + newMethod(baseClass, "a", "()V"), + newMethod(subClassAA, "a", "()V"), + newMethod(subClassB, "a", "()V") + )); + entries = resolver.resolveEquivalentMethods(newMethod(subClassB, "a", "()V")); + assertThat(entries, containsInAnyOrder( + newMethod(baseClass, "a", "()V"), + newMethod(subClassAA, "a", "()V"), + newMethod(subClassB, "a", "()V") + )); + + // doBThings + entries = resolver.resolveEquivalentMethods(newMethod(subClassB, "b", "()V")); + assertThat(entries, containsInAnyOrder(newMethod(subClassB, "b", "()V"))); + } + + @Test + @SuppressWarnings("unchecked") + public void fieldReferences() { + Collection> references; + + // name + references = index.getReferenceIndex().getReferencesToField(nameField); + assertThat(references, containsInAnyOrder( + newFieldReferenceByMethod(nameField, baseClass.getName(), "", "(Ljava/lang/String;)V"), + newFieldReferenceByMethod(nameField, baseClass.getName(), "a", "()Ljava/lang/String;") + )); + + // numThings + references = index.getReferenceIndex().getReferencesToField(numThingsField); + assertThat(references, containsInAnyOrder( + newFieldReferenceByMethod(numThingsField, subClassB.getName(), "", "()V"), + newFieldReferenceByMethod(numThingsField, subClassB.getName(), "b", "()V") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void behaviorReferences() { + + MethodEntry source; + Collection> references; + + // baseClass constructor + source = newMethod(baseClass, "", "(Ljava/lang/String;)V"); + references = index.getReferenceIndex().getReferencesToMethod(source); + assertThat(references, containsInAnyOrder( + newBehaviorReferenceByMethod(source, subClassA.getName(), "", "(Ljava/lang/String;)V"), + newBehaviorReferenceByMethod(source, subClassB.getName(), "", "()V") + )); + + // subClassA constructor + source = newMethod(subClassA, "", "(Ljava/lang/String;)V"); + references = index.getReferenceIndex().getReferencesToMethod(source); + assertThat(references, containsInAnyOrder( + newBehaviorReferenceByMethod(source, subClassAA.getName(), "", "()V") + )); + + // baseClass.getName() + source = newMethod(baseClass, "a", "()Ljava/lang/String;"); + references = index.getReferenceIndex().getReferencesToMethod(source); + assertThat(references, containsInAnyOrder( + newBehaviorReferenceByMethod(source, subClassAA.getName(), "a", "()Ljava/lang/String;"), + newBehaviorReferenceByMethod(source, subClassB.getName(), "a", "()V") + )); + + // subclassAA.getName() + source = newMethod(subClassAA, "a", "()Ljava/lang/String;"); + references = index.getReferenceIndex().getReferencesToMethod(source); + assertThat(references, containsInAnyOrder( + newBehaviorReferenceByMethod(source, subClassAA.getName(), "a", "()V") + )); + } + + @Test + public void containsEntries() { + EntryIndex entryIndex = index.getEntryIndex(); + // classes + assertThat(entryIndex.hasClass(baseClass), is(true)); + assertThat(entryIndex.hasClass(subClassA), is(true)); + assertThat(entryIndex.hasClass(subClassAA), is(true)); + assertThat(entryIndex.hasClass(subClassB), is(true)); + + // fields + assertThat(entryIndex.hasField(nameField), is(true)); + assertThat(entryIndex.hasField(numThingsField), is(true)); + + // methods + // getName() + assertThat(entryIndex.hasMethod(newMethod(baseClass, "a", "()Ljava/lang/String;")), is(true)); + assertThat(entryIndex.hasMethod(newMethod(subClassA, "a", "()Ljava/lang/String;")), is(false)); + assertThat(entryIndex.hasMethod(newMethod(subClassAA, "a", "()Ljava/lang/String;")), is(true)); + assertThat(entryIndex.hasMethod(newMethod(subClassB, "a", "()Ljava/lang/String;")), is(false)); + + // doBaseThings() + assertThat(entryIndex.hasMethod(newMethod(baseClass, "a", "()V")), is(true)); + assertThat(entryIndex.hasMethod(newMethod(subClassA, "a", "()V")), is(false)); + assertThat(entryIndex.hasMethod(newMethod(subClassAA, "a", "()V")), is(true)); + assertThat(entryIndex.hasMethod(newMethod(subClassB, "a", "()V")), is(true)); + + // doBThings() + assertThat(entryIndex.hasMethod(newMethod(baseClass, "b", "()V")), is(false)); + assertThat(entryIndex.hasMethod(newMethod(subClassA, "b", "()V")), is(false)); + assertThat(entryIndex.hasMethod(newMethod(subClassAA, "b", "()V")), is(false)); + assertThat(entryIndex.hasMethod(newMethod(subClassB, "b", "()V")), is(true)); + + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/TestJarIndexLoneClass.java b/enigma/src/test/java/cuchaz/enigma/TestJarIndexLoneClass.java new file mode 100644 index 0000000..103c366 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/TestJarIndexLoneClass.java @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import cuchaz.enigma.analysis.*; +import cuchaz.enigma.analysis.index.EntryIndex; +import cuchaz.enigma.analysis.index.InheritanceIndex; +import cuchaz.enigma.analysis.index.JarIndex; +import cuchaz.enigma.translation.VoidTranslator; +import cuchaz.enigma.translation.representation.AccessFlags; +import cuchaz.enigma.translation.representation.entry.ClassEntry; +import cuchaz.enigma.translation.representation.entry.FieldEntry; +import cuchaz.enigma.translation.representation.entry.MethodDefEntry; +import cuchaz.enigma.translation.representation.entry.MethodEntry; +import org.junit.Test; + +import java.nio.file.Paths; +import java.util.Collection; +import java.util.List; + +import static cuchaz.enigma.TestEntryFactory.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class TestJarIndexLoneClass { + + private JarIndex index; + + public TestJarIndexLoneClass() throws Exception { + ClassCache classCache = ClassCache.of(Paths.get("build/test-obf/loneClass.jar")); + index = classCache.index(ProgressListener.none()); + } + + @Test + public void obfEntries() { + assertThat(index.getEntryIndex().getClasses(), containsInAnyOrder( + newClass("cuchaz/enigma/inputs/Keep"), + newClass("a") + )); + } + + @Test + public void translationIndex() { + InheritanceIndex inheritanceIndex = index.getInheritanceIndex(); + assertThat(inheritanceIndex.getParents(new ClassEntry("a")), is(empty())); + assertThat(inheritanceIndex.getParents(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(empty())); + assertThat(inheritanceIndex.getAncestors(new ClassEntry("a")), is(empty())); + assertThat(inheritanceIndex.getAncestors(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(empty())); + assertThat(inheritanceIndex.getChildren(new ClassEntry("a")), is(empty())); + assertThat(inheritanceIndex.getChildren(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(empty())); + } + + @Test + public void access() { + EntryIndex entryIndex = index.getEntryIndex(); + assertThat(entryIndex.getFieldAccess(newField("a", "a", "Ljava/lang/String;")), is(AccessFlags.PRIVATE)); + assertThat(entryIndex.getMethodAccess(newMethod("a", "a", "()Ljava/lang/String;")), is(AccessFlags.PUBLIC)); + assertThat(entryIndex.getFieldAccess(newField("a", "b", "Ljava/lang/String;")), is(nullValue())); + assertThat(entryIndex.getFieldAccess(newField("a", "a", "LFoo;")), is(nullValue())); + } + + @Test + public void classInheritance() { + IndexTreeBuilder treeBuilder = new IndexTreeBuilder(index); + ClassInheritanceTreeNode node = treeBuilder.buildClassInheritance(VoidTranslator.INSTANCE, newClass("a")); + assertThat(node, is(not(nullValue()))); + assertThat(node.getObfClassName(), is("a")); + assertThat(node.getChildCount(), is(0)); + } + + @Test + public void methodInheritance() { + IndexTreeBuilder treeBuilder = new IndexTreeBuilder(index); + MethodEntry source = newMethod("a", "a", "()Ljava/lang/String;"); + MethodInheritanceTreeNode node = treeBuilder.buildMethodInheritance(VoidTranslator.INSTANCE, source); + assertThat(node, is(not(nullValue()))); + assertThat(node.getMethodEntry(), is(source)); + assertThat(node.getChildCount(), is(0)); + } + + @Test + public void classImplementations() { + IndexTreeBuilder treeBuilder = new IndexTreeBuilder(index); + ClassImplementationsTreeNode node = treeBuilder.buildClassImplementations(VoidTranslator.INSTANCE, newClass("a")); + assertThat(node, is(nullValue())); + } + + @Test + public void methodImplementations() { + IndexTreeBuilder treeBuilder = new IndexTreeBuilder(index); + MethodEntry source = newMethod("a", "a", "()Ljava/lang/String;"); + + List nodes = treeBuilder.buildMethodImplementations(VoidTranslator.INSTANCE, source); + assertThat(nodes, hasSize(1)); + assertThat(nodes.get(0).getMethodEntry(), is(source)); + } + + @Test + public void relatedMethodImplementations() { + Collection entries = index.getEntryResolver().resolveEquivalentMethods(newMethod("a", "a", "()Ljava/lang/String;")); + assertThat(entries, containsInAnyOrder( + newMethod("a", "a", "()Ljava/lang/String;") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void fieldReferences() { + FieldEntry source = newField("a", "a", "Ljava/lang/String;"); + Collection> references = index.getReferenceIndex().getReferencesToField(source); + assertThat(references, containsInAnyOrder( + newFieldReferenceByMethod(source, "a", "", "(Ljava/lang/String;)V"), + newFieldReferenceByMethod(source, "a", "a", "()Ljava/lang/String;") + )); + } + + @Test + public void behaviorReferences() { + assertThat(index.getReferenceIndex().getReferencesToMethod(newMethod("a", "a", "()Ljava/lang/String;")), is(empty())); + } + + @Test + public void interfaces() { + assertThat(index.getInheritanceIndex().getParents(new ClassEntry("a")), is(empty())); + } + + @Test + public void implementingClasses() { + assertThat(index.getInheritanceIndex().getChildren(new ClassEntry("a")), is(empty())); + } + + @Test + public void isInterface() { + assertThat(index.getInheritanceIndex().isParent(new ClassEntry("a")), is(false)); + } + + @Test + public void testContains() { + EntryIndex entryIndex = index.getEntryIndex(); + assertThat(entryIndex.hasClass(newClass("a")), is(true)); + assertThat(entryIndex.hasClass(newClass("b")), is(false)); + assertThat(entryIndex.hasField(newField("a", "a", "Ljava/lang/String;")), is(true)); + assertThat(entryIndex.hasField(newField("a", "b", "Ljava/lang/String;")), is(false)); + assertThat(entryIndex.hasField(newField("a", "a", "LFoo;")), is(false)); + assertThat(entryIndex.hasMethod(newMethod("a", "a", "()Ljava/lang/String;")), is(true)); + assertThat(entryIndex.hasMethod(newMethod("a", "b", "()Ljava/lang/String;")), is(false)); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/TestMethodDescriptor.java b/enigma/src/test/java/cuchaz/enigma/TestMethodDescriptor.java new file mode 100644 index 0000000..a73880d --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/TestMethodDescriptor.java @@ -0,0 +1,247 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import cuchaz.enigma.translation.representation.MethodDescriptor; +import cuchaz.enigma.translation.representation.TypeDescriptor; +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class TestMethodDescriptor { + + @Test + public void easiest() { + final MethodDescriptor sig = new MethodDescriptor("()V"); + assertThat(sig.getArgumentDescs(), is(empty())); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("V"))); + } + + @Test + public void primitives() { + { + final MethodDescriptor sig = new MethodDescriptor("(I)V"); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("I") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("V"))); + } + { + final MethodDescriptor sig = new MethodDescriptor("(I)I"); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("I") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("I"))); + } + { + final MethodDescriptor sig = new MethodDescriptor("(IBCJ)Z"); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("I"), + new TypeDescriptor("B"), + new TypeDescriptor("C"), + new TypeDescriptor("J") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("Z"))); + } + } + + @Test + public void classes() { + { + final MethodDescriptor sig = new MethodDescriptor("([LFoo;)V"); + assertThat(sig.getArgumentDescs().size(), is(1)); + assertThat(sig.getArgumentDescs().get(0), is(new TypeDescriptor("[LFoo;"))); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("V"))); + } + { + final MethodDescriptor sig = new MethodDescriptor("(LFoo;)LBar;"); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("LFoo;") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("LBar;"))); + } + { + final MethodDescriptor sig = new MethodDescriptor("(LFoo;LMoo;LZoo;)LBar;"); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("LFoo;"), + new TypeDescriptor("LMoo;"), + new TypeDescriptor("LZoo;") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("LBar;"))); + } + } + + @Test + public void arrays() { + { + final MethodDescriptor sig = new MethodDescriptor("([I)V"); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("[I") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("V"))); + } + { + final MethodDescriptor sig = new MethodDescriptor("([I)[J"); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("[I") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("[J"))); + } + { + final MethodDescriptor sig = new MethodDescriptor("([I[Z[F)[D"); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("[I"), + new TypeDescriptor("[Z"), + new TypeDescriptor("[F") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("[D"))); + } + } + + @Test + public void mixed() { + { + final MethodDescriptor sig = new MethodDescriptor("(I[JLFoo;)Z"); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("I"), + new TypeDescriptor("[J"), + new TypeDescriptor("LFoo;") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("Z"))); + } + { + final MethodDescriptor sig = new MethodDescriptor("(III)[LFoo;"); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("I"), + new TypeDescriptor("I"), + new TypeDescriptor("I") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("[LFoo;"))); + } + } + + @Test + public void replaceClasses() { + { + final MethodDescriptor oldSig = new MethodDescriptor("()V"); + final MethodDescriptor sig = oldSig.remap(s -> null); + assertThat(sig.getArgumentDescs(), is(empty())); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("V"))); + } + { + final MethodDescriptor oldSig = new MethodDescriptor("(IJLFoo;)V"); + final MethodDescriptor sig = oldSig.remap(s -> null); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("I"), + new TypeDescriptor("J"), + new TypeDescriptor("LFoo;") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("V"))); + } + { + final MethodDescriptor oldSig = new MethodDescriptor("(LFoo;LBar;)LMoo;"); + final MethodDescriptor sig = oldSig.remap(s -> { + if (s.equals("Foo")) { + return "Bar"; + } + return null; + }); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("LBar;"), + new TypeDescriptor("LBar;") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("LMoo;"))); + } + { + final MethodDescriptor oldSig = new MethodDescriptor("(LFoo;LBar;)LMoo;"); + final MethodDescriptor sig = oldSig.remap(s -> { + if (s.equals("Moo")) { + return "Cow"; + } + return null; + }); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("LFoo;"), + new TypeDescriptor("LBar;") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("LCow;"))); + } + } + + @Test + public void replaceArrayClasses() { + { + final MethodDescriptor oldSig = new MethodDescriptor("([LFoo;)[[[LBar;"); + final MethodDescriptor sig = oldSig.remap(s -> { + if (s.equals("Foo")) { + return "Food"; + } else if (s.equals("Bar")) { + return "Beer"; + } + return null; + }); + assertThat(sig.getArgumentDescs(), contains( + new TypeDescriptor("[LFood;") + )); + assertThat(sig.getReturnDesc(), is(new TypeDescriptor("[[[LBeer;"))); + } + } + + @Test + public void equals() { + + // base + assertThat(new MethodDescriptor("()V"), is(new MethodDescriptor("()V"))); + + // arguments + assertThat(new MethodDescriptor("(I)V"), is(new MethodDescriptor("(I)V"))); + assertThat(new MethodDescriptor("(ZIZ)V"), is(new MethodDescriptor("(ZIZ)V"))); + assertThat(new MethodDescriptor("(LFoo;)V"), is(new MethodDescriptor("(LFoo;)V"))); + assertThat(new MethodDescriptor("(LFoo;LBar;)V"), is(new MethodDescriptor("(LFoo;LBar;)V"))); + assertThat(new MethodDescriptor("([I)V"), is(new MethodDescriptor("([I)V"))); + assertThat(new MethodDescriptor("([[D[[[J)V"), is(new MethodDescriptor("([[D[[[J)V"))); + + assertThat(new MethodDescriptor("()V"), is(not(new MethodDescriptor("(I)V")))); + assertThat(new MethodDescriptor("(I)V"), is(not(new MethodDescriptor("()V")))); + assertThat(new MethodDescriptor("(IJ)V"), is(not(new MethodDescriptor("(JI)V")))); + assertThat(new MethodDescriptor("([[Z)V"), is(not(new MethodDescriptor("([[LFoo;)V")))); + assertThat(new MethodDescriptor("(LFoo;LBar;)V"), is(not(new MethodDescriptor("(LFoo;LCow;)V")))); + assertThat(new MethodDescriptor("([LFoo;LBar;)V"), is(not(new MethodDescriptor("(LFoo;LCow;)V")))); + + // return desc + assertThat(new MethodDescriptor("()I"), is(new MethodDescriptor("()I"))); + assertThat(new MethodDescriptor("()Z"), is(new MethodDescriptor("()Z"))); + assertThat(new MethodDescriptor("()[D"), is(new MethodDescriptor("()[D"))); + assertThat(new MethodDescriptor("()[[[Z"), is(new MethodDescriptor("()[[[Z"))); + assertThat(new MethodDescriptor("()LFoo;"), is(new MethodDescriptor("()LFoo;"))); + assertThat(new MethodDescriptor("()[LFoo;"), is(new MethodDescriptor("()[LFoo;"))); + + assertThat(new MethodDescriptor("()I"), is(not(new MethodDescriptor("()Z")))); + assertThat(new MethodDescriptor("()Z"), is(not(new MethodDescriptor("()I")))); + assertThat(new MethodDescriptor("()[D"), is(not(new MethodDescriptor("()[J")))); + assertThat(new MethodDescriptor("()[[[Z"), is(not(new MethodDescriptor("()[[Z")))); + assertThat(new MethodDescriptor("()LFoo;"), is(not(new MethodDescriptor("()LBar;")))); + assertThat(new MethodDescriptor("()[LFoo;"), is(not(new MethodDescriptor("()[LBar;")))); + } + + @Test + public void testToString() { + assertThat(new MethodDescriptor("()V").toString(), is("()V")); + assertThat(new MethodDescriptor("(I)V").toString(), is("(I)V")); + assertThat(new MethodDescriptor("(ZIZ)V").toString(), is("(ZIZ)V")); + assertThat(new MethodDescriptor("(LFoo;)V").toString(), is("(LFoo;)V")); + assertThat(new MethodDescriptor("(LFoo;LBar;)V").toString(), is("(LFoo;LBar;)V")); + assertThat(new MethodDescriptor("([I)V").toString(), is("([I)V")); + assertThat(new MethodDescriptor("([[D[[[J)V").toString(), is("([[D[[[J)V")); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/TestTokensConstructors.java b/enigma/src/test/java/cuchaz/enigma/TestTokensConstructors.java new file mode 100644 index 0000000..0398de4 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/TestTokensConstructors.java @@ -0,0 +1,137 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import cuchaz.enigma.translation.representation.entry.MethodEntry; +import org.junit.Test; + +import java.nio.file.Paths; + +import static cuchaz.enigma.TestEntryFactory.newBehaviorReferenceByMethod; +import static cuchaz.enigma.TestEntryFactory.newMethod; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +public class TestTokensConstructors extends TokenChecker { + + public TestTokensConstructors() + throws Exception { + super(Paths.get("build/test-obf/constructors.jar")); + } + + @Test + public void baseDeclarations() { + assertThat(getDeclarationToken(newMethod("a", "", "()V")), is("a")); + assertThat(getDeclarationToken(newMethod("a", "", "(I)V")), is("a")); + } + + @Test + public void subDeclarations() { + assertThat(getDeclarationToken(newMethod("d", "", "()V")), is("d")); + assertThat(getDeclarationToken(newMethod("d", "", "(I)V")), is("d")); + assertThat(getDeclarationToken(newMethod("d", "", "(II)V")), is("d")); + assertThat(getDeclarationToken(newMethod("d", "", "(III)V")), is("d")); + } + + @Test + public void subsubDeclarations() { + assertThat(getDeclarationToken(newMethod("e", "", "(I)V")), is("e")); + } + + @Test + public void defaultDeclarations() { + assertThat(getDeclarationToken(newMethod("c", "", "()V")), nullValue()); + } + + @Test + public void baseDefaultReferences() { + MethodEntry source = newMethod("a", "", "()V"); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "b", "a", "()V")), + containsInAnyOrder("a") + ); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "d", "", "()V")), + is(empty()) // implicit call, not decompiled to token + ); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "d", "", "(III)V")), + is(empty()) // implicit call, not decompiled to token + ); + } + + @Test + public void baseIntReferences() { + MethodEntry source = newMethod("a", "", "(I)V"); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "b", "b", "()V")), + containsInAnyOrder("a") + ); + } + + @Test + public void subDefaultReferences() { + MethodEntry source = newMethod("d", "", "()V"); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "b", "c", "()V")), + containsInAnyOrder("d") + ); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "d", "", "(I)V")), + containsInAnyOrder("this") + ); + } + + @Test + public void subIntReferences() { + MethodEntry source = newMethod("d", "", "(I)V"); + assertThat(getReferenceTokens( + newBehaviorReferenceByMethod(source, "b", "d", "()V")), + containsInAnyOrder("d") + ); + assertThat(getReferenceTokens( + newBehaviorReferenceByMethod(source, "d", "", "(II)V")), + containsInAnyOrder("this") + ); + assertThat(getReferenceTokens( + newBehaviorReferenceByMethod(source, "e", "", "(I)V")), + containsInAnyOrder("super") + ); + } + + @Test + public void subIntIntReferences() { + MethodEntry source = newMethod("d", "", "(II)V"); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "b", "e", "()V")), + containsInAnyOrder("d") + ); + } + + @Test + public void subsubIntReferences() { + MethodEntry source = newMethod("e", "", "(I)V"); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "b", "f", "()V")), + containsInAnyOrder("e") + ); + } + + @Test + public void defaultConstructableReferences() { + MethodEntry source = newMethod("c", "", "()V"); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "b", "g", "()V")), + containsInAnyOrder("c") + ); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/TestTranslator.java b/enigma/src/test/java/cuchaz/enigma/TestTranslator.java new file mode 100644 index 0000000..a420afe --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/TestTranslator.java @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import cuchaz.enigma.translation.representation.entry.Entry; +import org.junit.BeforeClass; +import org.junit.Test; + +import static cuchaz.enigma.TestEntryFactory.*; + +public class TestTranslator { + + @BeforeClass + public static void beforeClass() + throws Exception { + //TODO FIx + //deobfuscator = new Enigma(new JarFile("build/test-obf/translation.jar")); + //try (InputStream in = TestTranslator.class.getResourceAsStream("/cuchaz/enigma/resources/translation.mappings")) { + // mappings = new MappingsJsonReader().read(new InputStreamReader(in)); + // deobfuscator.setMappings(mappings); + // deobfTranslator = deobfuscator.getTranslator(TranslationDirection.Deobfuscating); + // obfTranslator = deobfuscator.getTranslator(TranslationDirection.Obfuscating); + //} + } + + @Test + public void basicClasses() { + assertMapping(newClass("a"), newClass("deobf/A_Basic")); + assertMapping(newClass("b"), newClass("deobf/B_BaseClass")); + assertMapping(newClass("c"), newClass("deobf/C_SubClass")); + } + + @Test + public void basicFields() { + assertMapping(newField("a", "a", "I"), newField("deobf/A_Basic", "f1", "I")); + assertMapping(newField("a", "a", "F"), newField("deobf/A_Basic", "f2", "F")); + assertMapping(newField("a", "a", "Ljava/lang/String;"), newField("deobf/A_Basic", "f3", "Ljava/lang/String;")); + } + + @Test + public void basicMethods() { + assertMapping(newMethod("a", "a", "()V"), newMethod("deobf/A_Basic", "m1", "()V")); + assertMapping(newMethod("a", "a", "()I"), newMethod("deobf/A_Basic", "m2", "()I")); + assertMapping(newMethod("a", "a", "(I)V"), newMethod("deobf/A_Basic", "m3", "(I)V")); + assertMapping(newMethod("a", "a", "(I)I"), newMethod("deobf/A_Basic", "m4", "(I)I")); + } + + // TODO: basic constructors + + @Test + public void inheritanceFields() { + assertMapping(newField("b", "a", "I"), newField("deobf/B_BaseClass", "f1", "I")); + assertMapping(newField("b", "a", "C"), newField("deobf/B_BaseClass", "f2", "C")); + assertMapping(newField("c", "b", "I"), newField("deobf/C_SubClass", "f3", "I")); + assertMapping(newField("c", "c", "I"), newField("deobf/C_SubClass", "f4", "I")); + } + + @Test + public void inheritanceFieldsShadowing() { + assertMapping(newField("c", "b", "C"), newField("deobf/C_SubClass", "f2", "C")); + } + + @Test + public void inheritanceFieldsBySubClass() { + assertMapping(newField("c", "a", "I"), newField("deobf/C_SubClass", "f1", "I")); + // NOTE: can't reference b.C by subclass since it's shadowed + } + + @Test + public void inheritanceMethods() { + assertMapping(newMethod("b", "a", "()I"), newMethod("deobf/B_BaseClass", "m1", "()I")); + assertMapping(newMethod("b", "b", "()I"), newMethod("deobf/B_BaseClass", "m2", "()I")); + assertMapping(newMethod("c", "c", "()I"), newMethod("deobf/C_SubClass", "m3", "()I")); + } + + @Test + public void inheritanceMethodsOverrides() { + assertMapping(newMethod("c", "a", "()I"), newMethod("deobf/C_SubClass", "m1", "()I")); + } + + @Test + public void inheritanceMethodsBySubClass() { + assertMapping(newMethod("c", "b", "()I"), newMethod("deobf/C_SubClass", "m2", "()I")); + } + + @Test + public void innerClasses() { + + // classes + assertMapping(newClass("g"), newClass("deobf/G_OuterClass")); + assertMapping(newClass("g$a"), newClass("deobf/G_OuterClass$A_InnerClass")); + assertMapping(newClass("g$a$a"), newClass("deobf/G_OuterClass$A_InnerClass$A_InnerInnerClass")); + assertMapping(newClass("g$b"), newClass("deobf/G_OuterClass$b")); + assertMapping(newClass("g$b$a"), newClass("deobf/G_OuterClass$b$A_NamedInnerClass")); + + // fields + assertMapping(newField("g$a", "a", "I"), newField("deobf/G_OuterClass$A_InnerClass", "f1", "I")); + assertMapping(newField("g$a", "a", "Ljava/lang/String;"), newField("deobf/G_OuterClass$A_InnerClass", "f2", "Ljava/lang/String;")); + assertMapping(newField("g$a$a", "a", "I"), newField("deobf/G_OuterClass$A_InnerClass$A_InnerInnerClass", "f3", "I")); + assertMapping(newField("g$b$a", "a", "I"), newField("deobf/G_OuterClass$b$A_NamedInnerClass", "f4", "I")); + + // methods + assertMapping(newMethod("g$a", "a", "()V"), newMethod("deobf/G_OuterClass$A_InnerClass", "m1", "()V")); + assertMapping(newMethod("g$a$a", "a", "()V"), newMethod("deobf/G_OuterClass$A_InnerClass$A_InnerInnerClass", "m2", "()V")); + } + + @Test + public void namelessClass() { + assertMapping(newClass("h"), newClass("h")); + } + + @Test + public void testGenerics() { + + // classes + assertMapping(newClass("i"), newClass("deobf/I_Generics")); + assertMapping(newClass("i$a"), newClass("deobf/I_Generics$A_Type")); + assertMapping(newClass("i$b"), newClass("deobf/I_Generics$B_Generic")); + + // fields + assertMapping(newField("i", "a", "Ljava/util/List;"), newField("deobf/I_Generics", "f1", "Ljava/util/List;")); + assertMapping(newField("i", "b", "Ljava/util/List;"), newField("deobf/I_Generics", "f2", "Ljava/util/List;")); + assertMapping(newField("i", "a", "Ljava/util/Map;"), newField("deobf/I_Generics", "f3", "Ljava/util/Map;")); + assertMapping(newField("i$b", "a", "Ljava/lang/Object;"), newField("deobf/I_Generics$B_Generic", "f4", "Ljava/lang/Object;")); + assertMapping(newField("i", "a", "Li$b;"), newField("deobf/I_Generics", "f5", "Ldeobf/I_Generics$B_Generic;")); + assertMapping(newField("i", "b", "Li$b;"), newField("deobf/I_Generics", "f6", "Ldeobf/I_Generics$B_Generic;")); + + // methods + assertMapping(newMethod("i$b", "a", "()Ljava/lang/Object;"), newMethod("deobf/I_Generics$B_Generic", "m1", "()Ljava/lang/Object;")); + } + + private void assertMapping(Entry obf, Entry deobf) { + //assertThat(deobfTranslator.translateEntry(obf), is(deobf)); + //assertThat(obfTranslator.translateEntry(deobf), is(obf)); + + //String deobfName = deobfTranslator.translate(obf); + //if (deobfName != null) { + // assertThat(deobfName, is(deobf.getName())); + //} + + //String obfName = obfTranslator.translate(deobf); + //if (obfName != null) { + // assertThat(obfName, is(obf.getName())); + //} + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/TestTypeDescriptor.java b/enigma/src/test/java/cuchaz/enigma/TestTypeDescriptor.java new file mode 100644 index 0000000..b9ebe55 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/TestTypeDescriptor.java @@ -0,0 +1,243 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import cuchaz.enigma.translation.representation.TypeDescriptor; +import org.junit.Test; + +import static cuchaz.enigma.TestEntryFactory.newClass; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; + +public class TestTypeDescriptor { + + @Test + public void isVoid() { + assertThat(new TypeDescriptor("V").isVoid(), is(true)); + assertThat(new TypeDescriptor("Z").isVoid(), is(false)); + assertThat(new TypeDescriptor("B").isVoid(), is(false)); + assertThat(new TypeDescriptor("C").isVoid(), is(false)); + assertThat(new TypeDescriptor("I").isVoid(), is(false)); + assertThat(new TypeDescriptor("J").isVoid(), is(false)); + assertThat(new TypeDescriptor("F").isVoid(), is(false)); + assertThat(new TypeDescriptor("D").isVoid(), is(false)); + assertThat(new TypeDescriptor("LFoo;").isVoid(), is(false)); + assertThat(new TypeDescriptor("[I").isVoid(), is(false)); + } + + @Test + public void isPrimitive() { + assertThat(new TypeDescriptor("V").isPrimitive(), is(false)); + assertThat(new TypeDescriptor("Z").isPrimitive(), is(true)); + assertThat(new TypeDescriptor("B").isPrimitive(), is(true)); + assertThat(new TypeDescriptor("C").isPrimitive(), is(true)); + assertThat(new TypeDescriptor("I").isPrimitive(), is(true)); + assertThat(new TypeDescriptor("J").isPrimitive(), is(true)); + assertThat(new TypeDescriptor("F").isPrimitive(), is(true)); + assertThat(new TypeDescriptor("D").isPrimitive(), is(true)); + assertThat(new TypeDescriptor("LFoo;").isPrimitive(), is(false)); + assertThat(new TypeDescriptor("[I").isPrimitive(), is(false)); + } + + @Test + public void getPrimitive() { + assertThat(new TypeDescriptor("Z").getPrimitive(), is(TypeDescriptor.Primitive.BOOLEAN)); + assertThat(new TypeDescriptor("B").getPrimitive(), is(TypeDescriptor.Primitive.BYTE)); + assertThat(new TypeDescriptor("C").getPrimitive(), is(TypeDescriptor.Primitive.CHARACTER)); + assertThat(new TypeDescriptor("I").getPrimitive(), is(TypeDescriptor.Primitive.INTEGER)); + assertThat(new TypeDescriptor("J").getPrimitive(), is(TypeDescriptor.Primitive.LONG)); + assertThat(new TypeDescriptor("F").getPrimitive(), is(TypeDescriptor.Primitive.FLOAT)); + assertThat(new TypeDescriptor("D").getPrimitive(), is(TypeDescriptor.Primitive.DOUBLE)); + } + + @Test + public void isClass() { + assertThat(new TypeDescriptor("V").isType(), is(false)); + assertThat(new TypeDescriptor("Z").isType(), is(false)); + assertThat(new TypeDescriptor("B").isType(), is(false)); + assertThat(new TypeDescriptor("C").isType(), is(false)); + assertThat(new TypeDescriptor("I").isType(), is(false)); + assertThat(new TypeDescriptor("J").isType(), is(false)); + assertThat(new TypeDescriptor("F").isType(), is(false)); + assertThat(new TypeDescriptor("D").isType(), is(false)); + assertThat(new TypeDescriptor("LFoo;").isType(), is(true)); + assertThat(new TypeDescriptor("[I").isType(), is(false)); + } + + @Test + public void getClassEntry() { + assertThat(new TypeDescriptor("LFoo;").getTypeEntry(), is(newClass("Foo"))); + assertThat(new TypeDescriptor("Ljava/lang/String;").getTypeEntry(), is(newClass("java/lang/String"))); + } + + @Test + public void getArrayClassEntry() { + assertThat(new TypeDescriptor("[LFoo;").getTypeEntry(), is(newClass("Foo"))); + assertThat(new TypeDescriptor("[[[Ljava/lang/String;").getTypeEntry(), is(newClass("java/lang/String"))); + } + + @Test + public void isArray() { + assertThat(new TypeDescriptor("V").isArray(), is(false)); + assertThat(new TypeDescriptor("Z").isArray(), is(false)); + assertThat(new TypeDescriptor("B").isArray(), is(false)); + assertThat(new TypeDescriptor("C").isArray(), is(false)); + assertThat(new TypeDescriptor("I").isArray(), is(false)); + assertThat(new TypeDescriptor("J").isArray(), is(false)); + assertThat(new TypeDescriptor("F").isArray(), is(false)); + assertThat(new TypeDescriptor("D").isArray(), is(false)); + assertThat(new TypeDescriptor("LFoo;").isArray(), is(false)); + assertThat(new TypeDescriptor("[I").isArray(), is(true)); + } + + @Test + public void getArrayDimension() { + assertThat(new TypeDescriptor("[I").getArrayDimension(), is(1)); + assertThat(new TypeDescriptor("[[I").getArrayDimension(), is(2)); + assertThat(new TypeDescriptor("[[[I").getArrayDimension(), is(3)); + } + + @Test + public void getArrayType() { + assertThat(new TypeDescriptor("[I").getArrayType(), is(new TypeDescriptor("I"))); + assertThat(new TypeDescriptor("[[I").getArrayType(), is(new TypeDescriptor("I"))); + assertThat(new TypeDescriptor("[[[I").getArrayType(), is(new TypeDescriptor("I"))); + assertThat(new TypeDescriptor("[Ljava/lang/String;").getArrayType(), is(new TypeDescriptor("Ljava/lang/String;"))); + } + + @Test + public void hasClass() { + assertThat(new TypeDescriptor("LFoo;").containsType(), is(true)); + assertThat(new TypeDescriptor("Ljava/lang/String;").containsType(), is(true)); + assertThat(new TypeDescriptor("[LBar;").containsType(), is(true)); + assertThat(new TypeDescriptor("[[[LCat;").containsType(), is(true)); + + assertThat(new TypeDescriptor("V").containsType(), is(false)); + assertThat(new TypeDescriptor("[I").containsType(), is(false)); + assertThat(new TypeDescriptor("[[[I").containsType(), is(false)); + assertThat(new TypeDescriptor("Z").containsType(), is(false)); + } + + @Test + public void parseVoid() { + final String answer = "V"; + assertThat(TypeDescriptor.parseFirst("V"), is(answer)); + assertThat(TypeDescriptor.parseFirst("VVV"), is(answer)); + assertThat(TypeDescriptor.parseFirst("VIJ"), is(answer)); + assertThat(TypeDescriptor.parseFirst("V[I"), is(answer)); + assertThat(TypeDescriptor.parseFirst("VLFoo;"), is(answer)); + assertThat(TypeDescriptor.parseFirst("V[LFoo;"), is(answer)); + } + + @Test + public void parsePrimitive() { + final String answer = "I"; + assertThat(TypeDescriptor.parseFirst("I"), is(answer)); + assertThat(TypeDescriptor.parseFirst("III"), is(answer)); + assertThat(TypeDescriptor.parseFirst("IJZ"), is(answer)); + assertThat(TypeDescriptor.parseFirst("I[I"), is(answer)); + assertThat(TypeDescriptor.parseFirst("ILFoo;"), is(answer)); + assertThat(TypeDescriptor.parseFirst("I[LFoo;"), is(answer)); + } + + @Test + public void parseClass() { + { + final String answer = "LFoo;"; + assertThat(TypeDescriptor.parseFirst("LFoo;"), is(answer)); + assertThat(TypeDescriptor.parseFirst("LFoo;I"), is(answer)); + assertThat(TypeDescriptor.parseFirst("LFoo;JZ"), is(answer)); + assertThat(TypeDescriptor.parseFirst("LFoo;[I"), is(answer)); + assertThat(TypeDescriptor.parseFirst("LFoo;LFoo;"), is(answer)); + assertThat(TypeDescriptor.parseFirst("LFoo;[LFoo;"), is(answer)); + } + { + final String answer = "Ljava/lang/String;"; + assertThat(TypeDescriptor.parseFirst("Ljava/lang/String;"), is(answer)); + assertThat(TypeDescriptor.parseFirst("Ljava/lang/String;I"), is(answer)); + assertThat(TypeDescriptor.parseFirst("Ljava/lang/String;JZ"), is(answer)); + assertThat(TypeDescriptor.parseFirst("Ljava/lang/String;[I"), is(answer)); + assertThat(TypeDescriptor.parseFirst("Ljava/lang/String;LFoo;"), is(answer)); + assertThat(TypeDescriptor.parseFirst("Ljava/lang/String;[LFoo;"), is(answer)); + } + } + + @Test + public void parseArray() { + { + final String answer = "[I"; + assertThat(TypeDescriptor.parseFirst("[I"), is(answer)); + assertThat(TypeDescriptor.parseFirst("[III"), is(answer)); + assertThat(TypeDescriptor.parseFirst("[IJZ"), is(answer)); + assertThat(TypeDescriptor.parseFirst("[I[I"), is(answer)); + assertThat(TypeDescriptor.parseFirst("[ILFoo;"), is(answer)); + } + { + final String answer = "[[I"; + assertThat(TypeDescriptor.parseFirst("[[I"), is(answer)); + assertThat(TypeDescriptor.parseFirst("[[III"), is(answer)); + assertThat(TypeDescriptor.parseFirst("[[IJZ"), is(answer)); + assertThat(TypeDescriptor.parseFirst("[[I[I"), is(answer)); + assertThat(TypeDescriptor.parseFirst("[[ILFoo;"), is(answer)); + } + { + final String answer = "[LFoo;"; + assertThat(TypeDescriptor.parseFirst("[LFoo;"), is(answer)); + assertThat(TypeDescriptor.parseFirst("[LFoo;II"), is(answer)); + assertThat(TypeDescriptor.parseFirst("[LFoo;JZ"), is(answer)); + assertThat(TypeDescriptor.parseFirst("[LFoo;[I"), is(answer)); + assertThat(TypeDescriptor.parseFirst("[LFoo;LFoo;"), is(answer)); + } + } + + @Test + public void equals() { + assertThat(new TypeDescriptor("V"), is(new TypeDescriptor("V"))); + assertThat(new TypeDescriptor("Z"), is(new TypeDescriptor("Z"))); + assertThat(new TypeDescriptor("B"), is(new TypeDescriptor("B"))); + assertThat(new TypeDescriptor("C"), is(new TypeDescriptor("C"))); + assertThat(new TypeDescriptor("I"), is(new TypeDescriptor("I"))); + assertThat(new TypeDescriptor("J"), is(new TypeDescriptor("J"))); + assertThat(new TypeDescriptor("F"), is(new TypeDescriptor("F"))); + assertThat(new TypeDescriptor("D"), is(new TypeDescriptor("D"))); + assertThat(new TypeDescriptor("LFoo;"), is(new TypeDescriptor("LFoo;"))); + assertThat(new TypeDescriptor("[I"), is(new TypeDescriptor("[I"))); + assertThat(new TypeDescriptor("[[[I"), is(new TypeDescriptor("[[[I"))); + assertThat(new TypeDescriptor("[LFoo;"), is(new TypeDescriptor("[LFoo;"))); + + assertThat(new TypeDescriptor("V"), is(not(new TypeDescriptor("I")))); + assertThat(new TypeDescriptor("I"), is(not(new TypeDescriptor("J")))); + assertThat(new TypeDescriptor("I"), is(not(new TypeDescriptor("LBar;")))); + assertThat(new TypeDescriptor("I"), is(not(new TypeDescriptor("[I")))); + assertThat(new TypeDescriptor("LFoo;"), is(not(new TypeDescriptor("LBar;")))); + assertThat(new TypeDescriptor("[I"), is(not(new TypeDescriptor("[Z")))); + assertThat(new TypeDescriptor("[[[I"), is(not(new TypeDescriptor("[I")))); + assertThat(new TypeDescriptor("[LFoo;"), is(not(new TypeDescriptor("[LBar;")))); + } + + @Test + public void testToString() { + assertThat(new TypeDescriptor("V").toString(), is("V")); + assertThat(new TypeDescriptor("Z").toString(), is("Z")); + assertThat(new TypeDescriptor("B").toString(), is("B")); + assertThat(new TypeDescriptor("C").toString(), is("C")); + assertThat(new TypeDescriptor("I").toString(), is("I")); + assertThat(new TypeDescriptor("J").toString(), is("J")); + assertThat(new TypeDescriptor("F").toString(), is("F")); + assertThat(new TypeDescriptor("D").toString(), is("D")); + assertThat(new TypeDescriptor("LFoo;").toString(), is("LFoo;")); + assertThat(new TypeDescriptor("[I").toString(), is("[I")); + assertThat(new TypeDescriptor("[[[I").toString(), is("[[[I")); + assertThat(new TypeDescriptor("[LFoo;").toString(), is("[LFoo;")); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/TokenChecker.java b/enigma/src/test/java/cuchaz/enigma/TokenChecker.java new file mode 100644 index 0000000..96fc6da --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/TokenChecker.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma; + +import com.google.common.collect.Lists; +import cuchaz.enigma.analysis.ClassCache; +import cuchaz.enigma.analysis.EntryReference; +import cuchaz.enigma.source.SourceIndex; +import cuchaz.enigma.source.*; +import cuchaz.enigma.source.Token; +import cuchaz.enigma.translation.representation.entry.Entry; + +import java.io.IOException; +import java.nio.file.Path; +import java.util.Collection; +import java.util.List; + +public class TokenChecker { + private final Decompiler decompiler; + + protected TokenChecker(Path path) throws IOException { + ClassCache classCache = ClassCache.of(path); + decompiler = Decompilers.PROCYON.create(classCache, new SourceSettings(false, false)); + } + + protected String getDeclarationToken(Entry entry) { + // decompile the class + Source source = decompiler.getSource(entry.getContainingClass().getFullName()); + // DEBUG + // tree.acceptVisitor( new TreeDumpVisitor( new File( "tree." + entry.getClassName().replace( '/', '.' ) + ".txt" ) ), null ); + String string = source.asString(); + SourceIndex index = source.index(); + + // get the token value + Token token = index.getDeclarationToken(entry); + if (token == null) { + return null; + } + return string.substring(token.start, token.end); + } + + @SuppressWarnings("unchecked") + protected Collection getReferenceTokens(EntryReference, ? extends Entry> reference) { + // decompile the class + Source source = decompiler.getSource(reference.context.getContainingClass().getFullName()); + String string = source.asString(); + SourceIndex index = source.index(); + + // get the token values + List values = Lists.newArrayList(); + for (Token token : index.getReferenceTokens((EntryReference, Entry>) reference)) { + values.add(string.substring(token.start, token.end)); + } + return values; + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/Keep.java b/enigma/src/test/java/cuchaz/enigma/inputs/Keep.java new file mode 100644 index 0000000..4dbe8e2 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/Keep.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs; + +public class Keep { + public static void main(String[] args) { + System.out.println("Keep me!"); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/constructors/BaseClass.java b/enigma/src/test/java/cuchaz/enigma/inputs/constructors/BaseClass.java new file mode 100644 index 0000000..f07e1f8 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/constructors/BaseClass.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.constructors; + +// a +public class BaseClass { + + // ()V + public BaseClass() { + System.out.println("Default constructor"); + } + + // (I)V + public BaseClass(int i) { + System.out.println("Int constructor " + i); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/constructors/Caller.java b/enigma/src/test/java/cuchaz/enigma/inputs/constructors/Caller.java new file mode 100644 index 0000000..71439fd --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/constructors/Caller.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.constructors; + +// b +public class Caller { + + // a()V + public void callBaseDefault() { + // a.()V + System.out.println(new BaseClass()); + } + + // b()V + public void callBaseInt() { + // a.(I)V + System.out.println(new BaseClass(5)); + } + + // c()V + public void callSubDefault() { + // d.()V + System.out.println(new SubClass()); + } + + // d()V + public void callSubInt() { + // d.(I)V + System.out.println(new SubClass(6)); + } + + // e()V + public void callSubIntInt() { + // d.(II)V + System.out.println(new SubClass(4, 2)); + } + + // f()V + public void callSubSubInt() { + // e.(I)V + System.out.println(new SubSubClass(3)); + } + + // g()V + public void callDefaultConstructable() { + // c.()V + System.out.println(new DefaultConstructable()); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/constructors/DefaultConstructable.java b/enigma/src/test/java/cuchaz/enigma/inputs/constructors/DefaultConstructable.java new file mode 100644 index 0000000..c3d4170 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/constructors/DefaultConstructable.java @@ -0,0 +1,16 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.constructors; + +public class DefaultConstructable { + // only default constructor +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/constructors/SubClass.java b/enigma/src/test/java/cuchaz/enigma/inputs/constructors/SubClass.java new file mode 100644 index 0000000..bc56b3b --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/constructors/SubClass.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.constructors; + +// d extends a +public class SubClass extends BaseClass { + + // ()V + public SubClass() { + // a.()V + } + + // (I)V + public SubClass(int num) { + // ()V + this(); + System.out.println("SubClass " + num); + } + + // (II)V + public SubClass(int a, int b) { + // (I)V + this(a + b); + } + + // (III)V + public SubClass(int a, int b, int c) { + // a.()V + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/constructors/SubSubClass.java b/enigma/src/test/java/cuchaz/enigma/inputs/constructors/SubSubClass.java new file mode 100644 index 0000000..87b69d3 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/constructors/SubSubClass.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.constructors; + +// e extends d +public class SubSubClass extends SubClass { + + // (I)V + public SubSubClass(int i) { + // c.(I)V + super(i); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java b/enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java new file mode 100644 index 0000000..b9c4929 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.inheritanceTree; + +// a +public abstract class BaseClass { + + // a + private String name; + + // (Ljava/lang/String;)V + protected BaseClass(String name) { + this.name = name; + } + + // a()Ljava/lang/String; + public String getName() { + return name; + } + + // a()V + public abstract void doBaseThings(); +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java b/enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java new file mode 100644 index 0000000..50e963c --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java @@ -0,0 +1,22 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.inheritanceTree; + +// b extends a +public abstract class SubclassA extends BaseClass { + + // (Ljava/lang/String;)V + protected SubclassA(String name) { + // call to a.(Ljava/lang/String)V + super(name); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java b/enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java new file mode 100644 index 0000000..d0dd664 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.inheritanceTree; + +// c extends a +public class SubclassB extends BaseClass { + + // a + private int numThings; + + // ()V + protected SubclassB() { + // a.(Ljava/lang/String;)V + super("B"); + + // access to a + numThings = 4; + } + + @Override + // a()V + public void doBaseThings() { + // call to a.a()Ljava/lang/String; + System.out.println("Base things by B! " + getName()); + } + + // b()V + public void doBThings() { + // access to a + System.out.println("" + numThings + " B things!"); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java b/enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java new file mode 100644 index 0000000..c584570 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.inheritanceTree; + +// d extends b +public class SubsubclassAA extends SubclassA { + + protected SubsubclassAA() { + // call to b.(Ljava/lang/String;)V + super("AA"); + } + + @Override + // a()Ljava/lang/String; + public String getName() { + // call to b.a()Ljava/lang/String; + return "subsub" + super.getName(); + } + + @Override + // a()V + public void doBaseThings() { + // call to d.a()Ljava/lang/String; + System.out.println("Base things by " + getName()); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java b/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java new file mode 100644 index 0000000..f652d87 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.innerClasses; + +public class A_Anonymous { + + public void foo() { + Runnable runnable = new Runnable() { + @Override + public void run() { + // don't care + } + }; + runnable.run(); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java b/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java new file mode 100644 index 0000000..d1b7601 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.innerClasses; + +public class B_AnonymousWithScopeArgs { + + public static void foo(final D_Simple arg) { + System.out.println(new Object() { + @Override + public String toString() { + return arg.toString(); + } + }); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java b/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java new file mode 100644 index 0000000..94061fa --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.innerClasses; + +@SuppressWarnings("unused") +public class C_ConstructorArgs { + + Inner i; + + public void foo() { + i = new Inner(5); + } + + class Inner { + + private int a; + + public Inner(int a) { + this.a = a; + } + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/D_Simple.java b/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/D_Simple.java new file mode 100644 index 0000000..71b3a6d --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/D_Simple.java @@ -0,0 +1,19 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.innerClasses; + +public class D_Simple { + + class Inner { + // nothing to do + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java b/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java new file mode 100644 index 0000000..976ec42 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.innerClasses; + +public class E_AnonymousWithOuterAccess { + + // reproduction of error case documented at: + // https://bitbucket.org/cuchaz/enigma/issue/61/stackoverflowerror-when-deobfuscating + + public Object makeInner() { + outerMethod(); + return new Object() { + @Override + public String toString() { + return outerMethod(); + } + }; + } + + private String outerMethod() { + return "foo"; + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/F_ClassTree.java b/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/F_ClassTree.java new file mode 100644 index 0000000..b1de3c9 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/innerClasses/F_ClassTree.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.innerClasses; + +public class F_ClassTree { + + public class Level1 { + + public int f1; + + public class Level2 { + + public int f2; + + public class Level3 { + + public int f3; + } + } + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/loneClass/LoneClass.java b/enigma/src/test/java/cuchaz/enigma/inputs/loneClass/LoneClass.java new file mode 100644 index 0000000..ddc4e31 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/loneClass/LoneClass.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.loneClass; + +public class LoneClass { + + private String name; + + public LoneClass(String name) { + this.name = name; + } + + public String getName() { + return name; + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/packageAccess/Base.java b/enigma/src/test/java/cuchaz/enigma/inputs/packageAccess/Base.java new file mode 100644 index 0000000..6f5fe30 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/packageAccess/Base.java @@ -0,0 +1,7 @@ +package cuchaz.enigma.inputs.packageAccess; + +public class Base { + protected int make() { + return 42; + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/packageAccess/SamePackageChild.java b/enigma/src/test/java/cuchaz/enigma/inputs/packageAccess/SamePackageChild.java new file mode 100644 index 0000000..cf0f657 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/packageAccess/SamePackageChild.java @@ -0,0 +1,12 @@ +package cuchaz.enigma.inputs.packageAccess; + +public class SamePackageChild extends Base { + + class Inner { + final int value; + + Inner() { + value = SamePackageChild.this.make(); // no synthetic method + } + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/packageAccess/sub/OtherPackageChild.java b/enigma/src/test/java/cuchaz/enigma/inputs/packageAccess/sub/OtherPackageChild.java new file mode 100644 index 0000000..19fb19c --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/packageAccess/sub/OtherPackageChild.java @@ -0,0 +1,14 @@ +package cuchaz.enigma.inputs.packageAccess.sub; + +import cuchaz.enigma.inputs.packageAccess.Base; + +public class OtherPackageChild extends Base { + + class Inner { + final int value; + + Inner() { + value = OtherPackageChild.this.make(); // synthetic method call + } + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/translation/A_Basic.java b/enigma/src/test/java/cuchaz/enigma/inputs/translation/A_Basic.java new file mode 100644 index 0000000..26f3718 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/translation/A_Basic.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.translation; + +public class A_Basic { + + public int one; + public float two; + public String three; + + public void m1() { + } + + public int m2() { + return 42; + } + + public void m3(int a1) { + } + + public int m4(int a1) { + return 5; // chosen by fair die roll, guaranteed to be random + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/translation/B_BaseClass.java b/enigma/src/test/java/cuchaz/enigma/inputs/translation/B_BaseClass.java new file mode 100644 index 0000000..fd7f6e7 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/translation/B_BaseClass.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.translation; + +public class B_BaseClass { + + public int f1; + public char f2; + + public int m1() { + return 5; + } + + public int m2() { + return 42; + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/translation/C_SubClass.java b/enigma/src/test/java/cuchaz/enigma/inputs/translation/C_SubClass.java new file mode 100644 index 0000000..9d74e44 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/translation/C_SubClass.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.translation; + +public class C_SubClass extends B_BaseClass { + + public char f2; // shadows B_BaseClass.f2 + public int f3; + public int f4; + + @Override + public int m1() { + return 32; + } + + public int m3() { + return 7; + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/translation/D_AnonymousTesting.java b/enigma/src/test/java/cuchaz/enigma/inputs/translation/D_AnonymousTesting.java new file mode 100644 index 0000000..99c83bb --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/translation/D_AnonymousTesting.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.translation; + +import java.util.ArrayList; +import java.util.List; + +public class D_AnonymousTesting { + + public List getObjs() { + List objs = new ArrayList(); + objs.add(new Object() { + @Override + public String toString() { + return "Object!"; + } + }); + return objs; + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/translation/E_Bridges.java b/enigma/src/test/java/cuchaz/enigma/inputs/translation/E_Bridges.java new file mode 100644 index 0000000..0b8cf2a --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/translation/E_Bridges.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.translation; + +import java.util.Iterator; + +public class E_Bridges implements Iterator { + + @Override + public boolean hasNext() { + return false; + } + + @Override + public String next() { + // the compiler will generate a bridge for this method + return "foo"; + } + + @Override + public void remove() { + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/translation/F_ObjectMethods.java b/enigma/src/test/java/cuchaz/enigma/inputs/translation/F_ObjectMethods.java new file mode 100644 index 0000000..8a92792 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/translation/F_ObjectMethods.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.translation; + +@SuppressWarnings("FinalizeCalledExplicitly") +public class F_ObjectMethods { + + public void callEmAll() + throws Throwable { + clone(); + equals(this); + finalize(); + getClass(); + hashCode(); + notify(); + notifyAll(); + toString(); + wait(); + wait(0); + wait(0, 0); + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/translation/G_OuterClass.java b/enigma/src/test/java/cuchaz/enigma/inputs/translation/G_OuterClass.java new file mode 100644 index 0000000..a1e6a85 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/translation/G_OuterClass.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.translation; + +public class G_OuterClass { + + public class A_InnerClass { + + public int f1; + public String f2; + + public void m1() {} + + public class A_InnerInnerClass { + + public int f3; + + public void m2() {} + } + } + + public class B_NamelessClass { + public class A_NamedInnerClass { + public int f4; + } + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/translation/H_NamelessClass.java b/enigma/src/test/java/cuchaz/enigma/inputs/translation/H_NamelessClass.java new file mode 100644 index 0000000..013c55a --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/translation/H_NamelessClass.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.translation; + +public class H_NamelessClass { + + public class A_InnerClass { + + public int f1; + public String f2; + + public void m1() {} + + public class A_InnerInnerClass { + + public int f3; + + public void m2() {} + } + } + + public class B_NamelessClass { + public class A_NamedInnerClass { + public int f4; + + public class A_AnotherInnerClass {} + + public class B_YetAnotherInnerClass {} + } + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/inputs/translation/I_Generics.java b/enigma/src/test/java/cuchaz/enigma/inputs/translation/I_Generics.java new file mode 100644 index 0000000..fd2ebdd --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/inputs/translation/I_Generics.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.inputs.translation; + +import java.util.List; +import java.util.Map; + +public class I_Generics { + + public List f1; + public List f2; + public Map f3; + public B_Generic f5; + public B_Generic f6; + + public class A_Type { + } + + public class B_Generic { + public T f4; + + public T m1() { + return null; + } + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestComments.java b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestComments.java new file mode 100644 index 0000000..e831943 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestComments.java @@ -0,0 +1,39 @@ +package cuchaz.enigma.translation.mapping; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import cuchaz.enigma.ProgressListener; +import cuchaz.enigma.translation.mapping.serde.MappingFileNameFormat; +import cuchaz.enigma.translation.mapping.serde.MappingParseException; +import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; +import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsReader; +import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Writer; +import cuchaz.enigma.translation.mapping.tree.EntryTree; +import org.junit.Test; + +public class TestComments { + private static Path DIRECTORY; + + static { + try { + DIRECTORY = Paths.get(TestTinyV2InnerClasses.class.getResource("/comments/").toURI()); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + } + + @Test + public void testParseAndWrite() throws IOException, MappingParseException { + ProgressListener progressListener = ProgressListener.none(); + MappingSaveParameters params = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF); + EntryTree mappings = EnigmaMappingsReader.DIRECTORY.read( + DIRECTORY, progressListener, params); + + new TinyV2Writer("intermediary", "named") + .write(mappings, DIRECTORY.resolve("convertedtiny.tiny"), progressListener, params); + } + +} \ No newline at end of file diff --git a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestTinyV2InnerClasses.java b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestTinyV2InnerClasses.java new file mode 100644 index 0000000..65941e5 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestTinyV2InnerClasses.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2015 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Lesser General Public + * License v3.0 which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/lgpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ + +package cuchaz.enigma.translation.mapping; + +import cuchaz.enigma.Enigma; +import cuchaz.enigma.EnigmaProject; +import cuchaz.enigma.ProgressListener; +import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsReader; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public final class TestTinyV2InnerClasses { + private Path jar; + private Path mappings; + + public TestTinyV2InnerClasses() throws Exception { + jar = Paths.get("build/test-obf/innerClasses.jar"); + mappings = Paths.get(TestTinyV2InnerClasses.class.getResource("/tinyV2InnerClasses/").toURI()); + } + +// @Test + public void testMappings() throws Exception { + EnigmaProject project = Enigma.create().openJar(jar, ProgressListener.none()); + project.setMappings(EnigmaMappingsReader.DIRECTORY.read(mappings, ProgressListener.none(), project.getEnigma().getProfile().getMappingSaveParameters())); + + } +} diff --git a/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestV2Main.java b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestV2Main.java new file mode 100644 index 0000000..6e4d7b9 --- /dev/null +++ b/enigma/src/test/java/cuchaz/enigma/translation/mapping/TestV2Main.java @@ -0,0 +1,23 @@ +package cuchaz.enigma.translation.mapping; + +import cuchaz.enigma.ProgressListener; +import cuchaz.enigma.translation.mapping.serde.MappingFileNameFormat; +import cuchaz.enigma.translation.mapping.serde.MappingSaveParameters; +import cuchaz.enigma.translation.mapping.serde.enigma.EnigmaMappingsReader; +import cuchaz.enigma.translation.mapping.serde.tinyv2.TinyV2Writer; +import cuchaz.enigma.translation.mapping.tree.EntryTree; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public final class TestV2Main { + public static void main(String... args) throws Exception { + Path path = Paths.get(TestV2Main.class.getResource("/tinyV2InnerClasses/").toURI()); + + MappingSaveParameters parameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF); + + EntryTree tree = EnigmaMappingsReader.DIRECTORY.read(path, ProgressListener.none(), parameters); + + new TinyV2Writer("obf", "deobf").write(tree, Paths.get("currentYarn.tiny"), ProgressListener.none(), parameters); + } +} -- cgit v1.2.3