From ed9b5cdfc648e86fd463bfa8d86b94c41671e14c Mon Sep 17 00:00:00 2001 From: jeff Date: Sun, 8 Feb 2015 21:29:25 -0500 Subject: switch all classes to new signature/type system --- test/cuchaz/enigma/EntryFactory.java | 67 ++++++ test/cuchaz/enigma/TestDeobfuscator.java | 58 +++++ test/cuchaz/enigma/TestInnerClasses.java | 90 +++++++ .../enigma/TestJarIndexConstructorReferences.java | 124 ++++++++++ .../cuchaz/enigma/TestJarIndexInheritanceTree.java | 228 ++++++++++++++++++ test/cuchaz/enigma/TestJarIndexLoneClass.java | 165 +++++++++++++ test/cuchaz/enigma/TestSignature.java | 266 +++++++++++++++++++++ test/cuchaz/enigma/TestSourceIndex.java | 50 ++++ test/cuchaz/enigma/TestTokensConstructors.java | 136 +++++++++++ test/cuchaz/enigma/TestTranslator.java | 39 +++ test/cuchaz/enigma/TestType.java | 229 ++++++++++++++++++ test/cuchaz/enigma/TokenChecker.java | 65 +++++ test/cuchaz/enigma/inputs/Keep.java | 7 + .../enigma/inputs/constructors/BaseClass.java | 15 ++ test/cuchaz/enigma/inputs/constructors/Caller.java | 47 ++++ .../inputs/constructors/DefaultConstructable.java | 5 + .../enigma/inputs/constructors/SubClass.java | 28 +++ .../enigma/inputs/constructors/SubSubClass.java | 11 + .../enigma/inputs/inheritanceTree/BaseClass.java | 21 ++ .../enigma/inputs/inheritanceTree/SubclassA.java | 11 + .../enigma/inputs/inheritanceTree/SubclassB.java | 30 +++ .../inputs/inheritanceTree/SubsubclassAA.java | 24 ++ .../enigma/inputs/innerClasses/A_Anonymous.java | 14 ++ .../innerClasses/B_AnonymousWithScopeArgs.java | 13 + .../inputs/innerClasses/C_ConstructorArgs.java | 20 ++ .../enigma/inputs/innerClasses/D_Simple.java | 8 + .../innerClasses/E_AnonymousWithOuterAccess.java | 21 ++ test/cuchaz/enigma/inputs/loneClass/LoneClass.java | 14 ++ test/cuchaz/enigma/inputs/translation/A.java | 8 + test/cuchaz/enigma/resources/translation.mappings | 4 + 30 files changed, 1818 insertions(+) create mode 100644 test/cuchaz/enigma/EntryFactory.java create mode 100644 test/cuchaz/enigma/TestDeobfuscator.java create mode 100644 test/cuchaz/enigma/TestInnerClasses.java create mode 100644 test/cuchaz/enigma/TestJarIndexConstructorReferences.java create mode 100644 test/cuchaz/enigma/TestJarIndexInheritanceTree.java create mode 100644 test/cuchaz/enigma/TestJarIndexLoneClass.java create mode 100644 test/cuchaz/enigma/TestSignature.java create mode 100644 test/cuchaz/enigma/TestSourceIndex.java create mode 100644 test/cuchaz/enigma/TestTokensConstructors.java create mode 100644 test/cuchaz/enigma/TestTranslator.java create mode 100644 test/cuchaz/enigma/TestType.java create mode 100644 test/cuchaz/enigma/TokenChecker.java create mode 100644 test/cuchaz/enigma/inputs/Keep.java create mode 100644 test/cuchaz/enigma/inputs/constructors/BaseClass.java create mode 100644 test/cuchaz/enigma/inputs/constructors/Caller.java create mode 100644 test/cuchaz/enigma/inputs/constructors/DefaultConstructable.java create mode 100644 test/cuchaz/enigma/inputs/constructors/SubClass.java create mode 100644 test/cuchaz/enigma/inputs/constructors/SubSubClass.java create mode 100644 test/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java create mode 100644 test/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java create mode 100644 test/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java create mode 100644 test/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java create mode 100644 test/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java create mode 100644 test/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java create mode 100644 test/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java create mode 100644 test/cuchaz/enigma/inputs/innerClasses/D_Simple.java create mode 100644 test/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java create mode 100644 test/cuchaz/enigma/inputs/loneClass/LoneClass.java create mode 100644 test/cuchaz/enigma/inputs/translation/A.java create mode 100644 test/cuchaz/enigma/resources/translation.mappings (limited to 'test/cuchaz') diff --git a/test/cuchaz/enigma/EntryFactory.java b/test/cuchaz/enigma/EntryFactory.java new file mode 100644 index 00000000..fa90779d --- /dev/null +++ b/test/cuchaz/enigma/EntryFactory.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin.\ + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma; + +import cuchaz.enigma.analysis.EntryReference; +import cuchaz.enigma.mapping.BehaviorEntry; +import cuchaz.enigma.mapping.ClassEntry; +import cuchaz.enigma.mapping.ConstructorEntry; +import cuchaz.enigma.mapping.FieldEntry; +import cuchaz.enigma.mapping.MethodEntry; +import cuchaz.enigma.mapping.Signature; + +public class EntryFactory { + + public static ClassEntry newClass(String name) { + return new ClassEntry(name); + } + + public static FieldEntry newField(String className, String fieldName) { + return newField(newClass(className), fieldName); + } + + public static FieldEntry newField(ClassEntry classEntry, String fieldName) { + return new FieldEntry(classEntry, fieldName); + } + + 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 Signature(methodSignature)); + } + + public static ConstructorEntry newConstructor(String className, String signature) { + return newConstructor(newClass(className), signature); + } + + public static ConstructorEntry newConstructor(ClassEntry classEntry, String signature) { + return new ConstructorEntry(classEntry, new Signature(signature)); + } + + public static EntryReference newFieldReferenceByMethod(FieldEntry fieldEntry, String callerClassName, String callerName, String callerSignature) { + return new EntryReference(fieldEntry, "", newMethod(callerClassName, callerName, callerSignature)); + } + + public static EntryReference newFieldReferenceByConstructor(FieldEntry fieldEntry, String callerClassName, String callerSignature) { + return new EntryReference(fieldEntry, "", newConstructor(callerClassName, callerSignature)); + } + + public static EntryReference newBehaviorReferenceByMethod(BehaviorEntry behaviorEntry, String callerClassName, String callerName, String callerSignature) { + return new EntryReference(behaviorEntry, "", newMethod(callerClassName, callerName, callerSignature)); + } + + public static EntryReference newBehaviorReferenceByConstructor(BehaviorEntry behaviorEntry, String callerClassName, String callerSignature) { + return new EntryReference(behaviorEntry, "", newConstructor(callerClassName, callerSignature)); + } +} diff --git a/test/cuchaz/enigma/TestDeobfuscator.java b/test/cuchaz/enigma/TestDeobfuscator.java new file mode 100644 index 00000000..26d492d8 --- /dev/null +++ b/test/cuchaz/enigma/TestDeobfuscator.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin.\ + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.util.List; +import java.util.jar.JarFile; + +import org.junit.Test; + +import com.google.common.collect.Lists; + +import cuchaz.enigma.mapping.ClassEntry; + +public class TestDeobfuscator { + + private Deobfuscator getDeobfuscator() + throws IOException { + return new Deobfuscator(new JarFile("build/testLoneClass.obf.jar")); + } + + @Test + public void loadJar() + throws Exception { + getDeobfuscator(); + } + + @Test + public void getClasses() + throws Exception { + Deobfuscator deobfuscator = getDeobfuscator(); + List obfClasses = Lists.newArrayList(); + List deobfClasses = Lists.newArrayList(); + deobfuscator.getSeparatedClasses(obfClasses, deobfClasses); + assertEquals(1, obfClasses.size()); + assertEquals("none/a", obfClasses.get(0).getName()); + assertEquals(1, deobfClasses.size()); + assertEquals("cuchaz/enigma/inputs/Keep", deobfClasses.get(0).getName()); + } + + @Test + public void decompileClass() + throws Exception { + Deobfuscator deobfuscator = getDeobfuscator(); + deobfuscator.getSource(deobfuscator.getSourceTree("none/a")); + } +} diff --git a/test/cuchaz/enigma/TestInnerClasses.java b/test/cuchaz/enigma/TestInnerClasses.java new file mode 100644 index 00000000..2e16a330 --- /dev/null +++ b/test/cuchaz/enigma/TestInnerClasses.java @@ -0,0 +1,90 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import java.util.jar.JarFile; + +import org.junit.Test; + +import cuchaz.enigma.analysis.JarIndex; + +public class TestInnerClasses { + + private JarIndex m_index; + private Deobfuscator m_deobfuscator; + + private static final String AnonymousOuter = "none/a"; + private static final String AnonymousInner = "b"; + private static final String SimpleOuter = "none/g"; + private static final String SimpleInner = "h"; + private static final String ConstructorArgsOuter = "none/e"; + private static final String ConstructorArgsInner = "f"; + private static final String AnonymousWithScopeArgsOuter = "none/c"; + private static final String AnonymousWithScopeArgsInner = "d"; + private static final String AnonymousWithOuterAccessOuter = "none/i"; + private static final String AnonymousWithOuterAccessInner = "j"; + + public TestInnerClasses() + throws Exception { + m_index = new JarIndex(); + JarFile jar = new JarFile("build/testInnerClasses.obf.jar"); + m_index.indexJar(jar, true); + m_deobfuscator = new Deobfuscator(jar); + } + + @Test + public void simple() { + assertThat(m_index.getOuterClass(SimpleInner), is(SimpleOuter)); + assertThat(m_index.getInnerClasses(SimpleOuter), containsInAnyOrder(SimpleInner)); + assertThat(m_index.isAnonymousClass(SimpleInner), is(false)); + decompile(SimpleOuter); + } + + @Test + public void anonymous() { + assertThat(m_index.getOuterClass(AnonymousInner), is(AnonymousOuter)); + assertThat(m_index.getInnerClasses(AnonymousOuter), containsInAnyOrder(AnonymousInner)); + assertThat(m_index.isAnonymousClass(AnonymousInner), is(true)); + decompile(AnonymousOuter); + } + + @Test + public void constructorArgs() { + assertThat(m_index.getOuterClass(ConstructorArgsInner), is(ConstructorArgsOuter)); + assertThat(m_index.getInnerClasses(ConstructorArgsOuter), containsInAnyOrder(ConstructorArgsInner)); + assertThat(m_index.isAnonymousClass(ConstructorArgsInner), is(false)); + decompile(ConstructorArgsOuter); + } + + @Test + public void anonymousWithScopeArgs() { + assertThat(m_index.getOuterClass(AnonymousWithScopeArgsInner), is(AnonymousWithScopeArgsOuter)); + assertThat(m_index.getInnerClasses(AnonymousWithScopeArgsOuter), containsInAnyOrder(AnonymousWithScopeArgsInner)); + assertThat(m_index.isAnonymousClass(AnonymousWithScopeArgsInner), is(true)); + decompile(AnonymousWithScopeArgsOuter); + } + + @Test + public void anonymousWithOuterAccess() { + assertThat(m_index.getOuterClass(AnonymousWithOuterAccessInner), is(AnonymousWithOuterAccessOuter)); + assertThat(m_index.getInnerClasses(AnonymousWithOuterAccessOuter), containsInAnyOrder(AnonymousWithOuterAccessInner)); + assertThat(m_index.isAnonymousClass(AnonymousWithOuterAccessInner), is(true)); + decompile(AnonymousWithOuterAccessOuter); + } + + private void decompile(String name) { + m_deobfuscator.getSourceTree(name); + } +} diff --git a/test/cuchaz/enigma/TestJarIndexConstructorReferences.java b/test/cuchaz/enigma/TestJarIndexConstructorReferences.java new file mode 100644 index 00000000..22812fea --- /dev/null +++ b/test/cuchaz/enigma/TestJarIndexConstructorReferences.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma; + +import static cuchaz.enigma.EntryFactory.*; +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import java.io.File; +import java.util.Collection; +import java.util.jar.JarFile; + +import org.junit.Test; + +import cuchaz.enigma.analysis.EntryReference; +import cuchaz.enigma.analysis.JarIndex; +import cuchaz.enigma.mapping.BehaviorEntry; +import cuchaz.enigma.mapping.ClassEntry; + +public class TestJarIndexConstructorReferences { + + private JarIndex m_index; + + private ClassEntry m_baseClass = newClass("none/a"); + private ClassEntry m_subClass = newClass("none/d"); + private ClassEntry m_subsubClass = newClass("none/e"); + private ClassEntry m_defaultClass = newClass("none/c"); + private ClassEntry m_callerClass = newClass("none/b"); + + public TestJarIndexConstructorReferences() + throws Exception { + File jarFile = new File("build/testConstructors.obf.jar"); + m_index = new JarIndex(); + m_index.indexJar(new JarFile(jarFile), false); + } + + @Test + public void obfEntries() { + assertThat(m_index.getObfClassEntries(), containsInAnyOrder(newClass("cuchaz/enigma/inputs/Keep"), m_baseClass, m_subClass, m_subsubClass, m_defaultClass, m_callerClass)); + } + + @Test + @SuppressWarnings("unchecked") + public void baseDefault() { + BehaviorEntry source = newConstructor(m_baseClass, "()V"); + Collection> references = m_index.getBehaviorReferences(source); + assertThat(references, containsInAnyOrder( + newBehaviorReferenceByMethod(source, m_callerClass.getName(), "a", "()V"), + newBehaviorReferenceByConstructor(source, m_subClass.getName(), "()V"), + newBehaviorReferenceByConstructor(source, m_subClass.getName(), "(III)V") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void baseInt() { + BehaviorEntry source = newConstructor(m_baseClass, "(I)V"); + assertThat(m_index.getBehaviorReferences(source), containsInAnyOrder( + newBehaviorReferenceByMethod(source, m_callerClass.getName(), "b", "()V") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void subDefault() { + BehaviorEntry source = newConstructor(m_subClass, "()V"); + assertThat(m_index.getBehaviorReferences(source), containsInAnyOrder( + newBehaviorReferenceByMethod(source, m_callerClass.getName(), "c", "()V"), + newBehaviorReferenceByConstructor(source, m_subClass.getName(), "(I)V") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void subInt() { + BehaviorEntry source = newConstructor(m_subClass, "(I)V"); + assertThat(m_index.getBehaviorReferences(source), containsInAnyOrder( + newBehaviorReferenceByMethod(source, m_callerClass.getName(), "d", "()V"), + newBehaviorReferenceByConstructor(source, m_subClass.getName(), "(II)V"), + newBehaviorReferenceByConstructor(source, m_subsubClass.getName(), "(I)V") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void subIntInt() { + BehaviorEntry source = newConstructor(m_subClass, "(II)V"); + assertThat(m_index.getBehaviorReferences(source), containsInAnyOrder( + newBehaviorReferenceByMethod(source, m_callerClass.getName(), "e", "()V") + )); + } + + @Test + public void subIntIntInt() { + BehaviorEntry source = newConstructor(m_subClass, "(III)V"); + assertThat(m_index.getBehaviorReferences(source), is(empty())); + } + + @Test + @SuppressWarnings("unchecked") + public void subsubInt() { + BehaviorEntry source = newConstructor(m_subsubClass, "(I)V"); + assertThat(m_index.getBehaviorReferences(source), containsInAnyOrder( + newBehaviorReferenceByMethod(source, m_callerClass.getName(), "f", "()V") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void defaultConstructable() { + BehaviorEntry source = newConstructor(m_defaultClass, "()V"); + assertThat(m_index.getBehaviorReferences(source), containsInAnyOrder( + newBehaviorReferenceByMethod(source, m_callerClass.getName(), "g", "()V") + )); + } +} diff --git a/test/cuchaz/enigma/TestJarIndexInheritanceTree.java b/test/cuchaz/enigma/TestJarIndexInheritanceTree.java new file mode 100644 index 00000000..1d6e5a55 --- /dev/null +++ b/test/cuchaz/enigma/TestJarIndexInheritanceTree.java @@ -0,0 +1,228 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma; + +import static cuchaz.enigma.EntryFactory.*; +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import java.util.Collection; +import java.util.Set; +import java.util.jar.JarFile; + +import org.junit.Test; + +import cuchaz.enigma.analysis.Access; +import cuchaz.enigma.analysis.EntryReference; +import cuchaz.enigma.analysis.JarIndex; +import cuchaz.enigma.analysis.TranslationIndex; +import cuchaz.enigma.mapping.BehaviorEntry; +import cuchaz.enigma.mapping.ClassEntry; +import cuchaz.enigma.mapping.FieldEntry; +import cuchaz.enigma.mapping.MethodEntry; + +public class TestJarIndexInheritanceTree { + + private JarIndex m_index; + + private ClassEntry m_baseClass = newClass("none/a"); + private ClassEntry m_subClassA = newClass("none/b"); + private ClassEntry m_subClassAA = newClass("none/d"); + private ClassEntry m_subClassB = newClass("none/c"); + private FieldEntry m_nameField = new FieldEntry(m_baseClass, "a"); + private FieldEntry m_numThingsField = new FieldEntry(m_subClassB, "a"); + + public TestJarIndexInheritanceTree() + throws Exception { + m_index = new JarIndex(); + m_index.indexJar(new JarFile("build/testInheritanceTree.obf.jar"), false); + } + + @Test + public void obfEntries() { + assertThat(m_index.getObfClassEntries(), containsInAnyOrder( + newClass("cuchaz/enigma/inputs/Keep"), + m_baseClass, + m_subClassA, + m_subClassAA, + m_subClassB + )); + } + + @Test + public void translationIndex() { + + TranslationIndex index = m_index.getTranslationIndex(); + + // base class + assertThat(index.getSuperclass(m_baseClass), is(nullValue())); + assertThat(index.getAncestry(m_baseClass), is(empty())); + assertThat(index.getSubclass(m_baseClass), containsInAnyOrder( + m_subClassA, + m_subClassB + )); + + // subclass a + assertThat(index.getSuperclass(m_subClassA), is(m_baseClass)); + assertThat(index.getAncestry(m_subClassA), contains(m_baseClass)); + assertThat(index.getSubclass(m_subClassA), contains(m_subClassAA)); + + // subclass aa + assertThat(index.getSuperclass(m_subClassAA), is(m_subClassA)); + assertThat(index.getAncestry(m_subClassAA), contains(m_subClassA, m_baseClass)); + assertThat(index.getSubclass(m_subClassAA), is(empty())); + + // subclass b + assertThat(index.getSuperclass(m_subClassB), is(m_baseClass)); + assertThat(index.getAncestry(m_subClassB), contains(m_baseClass)); + assertThat(index.getSubclass(m_subClassB), is(empty())); + } + + @Test + public void access() { + assertThat(m_index.getAccess(m_nameField), is(Access.Private)); + assertThat(m_index.getAccess(m_numThingsField), is(Access.Private)); + } + + @Test + public void relatedMethodImplementations() { + + Set entries; + + // getName() + entries = m_index.getRelatedMethodImplementations(newMethod(m_baseClass, "a", "()Ljava/lang/String;")); + assertThat(entries, containsInAnyOrder( + newMethod(m_baseClass, "a", "()Ljava/lang/String;"), + newMethod(m_subClassAA, "a", "()Ljava/lang/String;") + )); + entries = m_index.getRelatedMethodImplementations(newMethod(m_subClassAA, "a", "()Ljava/lang/String;")); + assertThat(entries, containsInAnyOrder( + newMethod(m_baseClass, "a", "()Ljava/lang/String;"), + newMethod(m_subClassAA, "a", "()Ljava/lang/String;") + )); + + // doBaseThings() + entries = m_index.getRelatedMethodImplementations(newMethod(m_baseClass, "a", "()V")); + assertThat(entries, containsInAnyOrder( + newMethod(m_baseClass, "a", "()V"), + newMethod(m_subClassAA, "a", "()V"), + newMethod(m_subClassB, "a", "()V") + )); + entries = m_index.getRelatedMethodImplementations(newMethod(m_subClassAA, "a", "()V")); + assertThat(entries, containsInAnyOrder( + newMethod(m_baseClass, "a", "()V"), + newMethod(m_subClassAA, "a", "()V"), + newMethod(m_subClassB, "a", "()V") + )); + entries = m_index.getRelatedMethodImplementations(newMethod(m_subClassB, "a", "()V")); + assertThat(entries, containsInAnyOrder( + newMethod(m_baseClass, "a", "()V"), + newMethod(m_subClassAA, "a", "()V"), + newMethod(m_subClassB, "a", "()V") + )); + + // doBThings + entries = m_index.getRelatedMethodImplementations(newMethod(m_subClassB, "b", "()V")); + assertThat(entries, containsInAnyOrder(newMethod(m_subClassB, "b", "()V"))); + } + + @Test + @SuppressWarnings("unchecked") + public void fieldReferences() { + Collection> references; + + // name + references = m_index.getFieldReferences(m_nameField); + assertThat(references, containsInAnyOrder( + newFieldReferenceByConstructor(m_nameField, m_baseClass.getName(), "(Ljava/lang/String;)V"), + newFieldReferenceByMethod(m_nameField, m_baseClass.getName(), "a", "()Ljava/lang/String;") + )); + + // numThings + references = m_index.getFieldReferences(m_numThingsField); + assertThat(references, containsInAnyOrder( + newFieldReferenceByConstructor(m_numThingsField, m_subClassB.getName(), "()V"), + newFieldReferenceByMethod(m_numThingsField, m_subClassB.getName(), "b", "()V") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void behaviorReferences() { + + BehaviorEntry source; + Collection> references; + + // baseClass constructor + source = newConstructor(m_baseClass, "(Ljava/lang/String;)V"); + references = m_index.getBehaviorReferences(source); + assertThat(references, containsInAnyOrder( + newBehaviorReferenceByConstructor(source, m_subClassA.getName(), "(Ljava/lang/String;)V"), + newBehaviorReferenceByConstructor(source, m_subClassB.getName(), "()V") + )); + + // subClassA constructor + source = newConstructor(m_subClassA, "(Ljava/lang/String;)V"); + references = m_index.getBehaviorReferences(source); + assertThat(references, containsInAnyOrder( + newBehaviorReferenceByConstructor(source, m_subClassAA.getName(), "()V") + )); + + // baseClass.getName() + source = newMethod(m_baseClass, "a", "()Ljava/lang/String;"); + references = m_index.getBehaviorReferences(source); + assertThat(references, containsInAnyOrder( + newBehaviorReferenceByMethod(source, m_subClassAA.getName(), "a", "()Ljava/lang/String;"), + newBehaviorReferenceByMethod(source, m_subClassB.getName(), "a", "()V") + )); + + // subclassAA.getName() + source = newMethod(m_subClassAA, "a", "()Ljava/lang/String;"); + references = m_index.getBehaviorReferences(source); + assertThat(references, containsInAnyOrder( + newBehaviorReferenceByMethod(source, m_subClassAA.getName(), "a", "()V") + )); + } + + @Test + public void containsEntries() { + + // classes + assertThat(m_index.containsObfClass(m_baseClass), is(true)); + assertThat(m_index.containsObfClass(m_subClassA), is(true)); + assertThat(m_index.containsObfClass(m_subClassAA), is(true)); + assertThat(m_index.containsObfClass(m_subClassB), is(true)); + + // fields + assertThat(m_index.containsObfField(m_nameField), is(true)); + assertThat(m_index.containsObfField(m_numThingsField), is(true)); + + // methods + // getName() + assertThat(m_index.containsObfBehavior(newMethod(m_baseClass, "a", "()Ljava/lang/String;")), is(true)); + assertThat(m_index.containsObfBehavior(newMethod(m_subClassA, "a", "()Ljava/lang/String;")), is(false)); + assertThat(m_index.containsObfBehavior(newMethod(m_subClassAA, "a", "()Ljava/lang/String;")), is(true)); + assertThat(m_index.containsObfBehavior(newMethod(m_subClassB, "a", "()Ljava/lang/String;")), is(false)); + + // doBaseThings() + assertThat(m_index.containsObfBehavior(newMethod(m_baseClass, "a", "()V")), is(true)); + assertThat(m_index.containsObfBehavior(newMethod(m_subClassA, "a", "()V")), is(false)); + assertThat(m_index.containsObfBehavior(newMethod(m_subClassAA, "a", "()V")), is(true)); + assertThat(m_index.containsObfBehavior(newMethod(m_subClassB, "a", "()V")), is(true)); + + // doBThings() + assertThat(m_index.containsObfBehavior(newMethod(m_baseClass, "b", "()V")), is(false)); + assertThat(m_index.containsObfBehavior(newMethod(m_subClassA, "b", "()V")), is(false)); + assertThat(m_index.containsObfBehavior(newMethod(m_subClassAA, "b", "()V")), is(false)); + assertThat(m_index.containsObfBehavior(newMethod(m_subClassB, "b", "()V")), is(true)); + + } +} diff --git a/test/cuchaz/enigma/TestJarIndexLoneClass.java b/test/cuchaz/enigma/TestJarIndexLoneClass.java new file mode 100644 index 00000000..c6a9e550 --- /dev/null +++ b/test/cuchaz/enigma/TestJarIndexLoneClass.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma; + +import static cuchaz.enigma.EntryFactory.*; +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import java.util.Collection; +import java.util.Set; +import java.util.jar.JarFile; + +import org.junit.Test; + +import cuchaz.enigma.analysis.Access; +import cuchaz.enigma.analysis.ClassImplementationsTreeNode; +import cuchaz.enigma.analysis.ClassInheritanceTreeNode; +import cuchaz.enigma.analysis.EntryReference; +import cuchaz.enigma.analysis.JarIndex; +import cuchaz.enigma.analysis.MethodImplementationsTreeNode; +import cuchaz.enigma.analysis.MethodInheritanceTreeNode; +import cuchaz.enigma.mapping.BehaviorEntry; +import cuchaz.enigma.mapping.ClassEntry; +import cuchaz.enigma.mapping.FieldEntry; +import cuchaz.enigma.mapping.MethodEntry; +import cuchaz.enigma.mapping.Translator; + +public class TestJarIndexLoneClass { + + private JarIndex m_index; + + public TestJarIndexLoneClass() + throws Exception { + m_index = new JarIndex(); + m_index.indexJar(new JarFile("build/testLoneClass.obf.jar"), false); + } + + @Test + public void obfEntries() { + assertThat(m_index.getObfClassEntries(), containsInAnyOrder( + newClass("cuchaz/enigma/inputs/Keep"), + newClass("none/a") + )); + } + + @Test + public void translationIndex() { + assertThat(m_index.getTranslationIndex().getSuperclass(new ClassEntry("none/a")), is(nullValue())); + assertThat(m_index.getTranslationIndex().getSuperclass(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(nullValue())); + assertThat(m_index.getTranslationIndex().getAncestry(new ClassEntry("none/a")), is(empty())); + assertThat(m_index.getTranslationIndex().getAncestry(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(empty())); + assertThat(m_index.getTranslationIndex().getSubclass(new ClassEntry("none/a")), is(empty())); + assertThat(m_index.getTranslationIndex().getSubclass(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(empty())); + } + + @Test + public void access() { + assertThat(m_index.getAccess(newField("none/a", "a")), is(Access.Private)); + assertThat(m_index.getAccess(newMethod("none/a", "a", "()Ljava/lang/String;")), is(Access.Public)); + assertThat(m_index.getAccess(newField("none/a", "b")), is(nullValue())); + } + + @Test + public void classInheritance() { + ClassInheritanceTreeNode node = m_index.getClassInheritance(new Translator(), newClass("none/a")); + assertThat(node, is(not(nullValue()))); + assertThat(node.getObfClassName(), is("none/a")); + assertThat(node.getChildCount(), is(0)); + } + + @Test + public void methodInheritance() { + MethodEntry source = newMethod("none/a", "a", "()Ljava/lang/String;"); + MethodInheritanceTreeNode node = m_index.getMethodInheritance(new Translator(), source); + assertThat(node, is(not(nullValue()))); + assertThat(node.getMethodEntry(), is(source)); + assertThat(node.getChildCount(), is(0)); + } + + @Test + public void classImplementations() { + ClassImplementationsTreeNode node = m_index.getClassImplementations(new Translator(), newClass("none/a")); + assertThat(node, is(nullValue())); + } + + @Test + public void methodImplementations() { + MethodEntry source = newMethod("none/a", "a", "()Ljava/lang/String;"); + MethodImplementationsTreeNode node = m_index.getMethodImplementations(new Translator(), source); + assertThat(node, is(nullValue())); + } + + @Test + public void relatedMethodImplementations() { + Set entries = m_index.getRelatedMethodImplementations(newMethod("none/a", "a", "()Ljava/lang/String;")); + assertThat(entries, containsInAnyOrder( + newMethod("none/a", "a", "()Ljava/lang/String;") + )); + } + + @Test + @SuppressWarnings("unchecked") + public void fieldReferences() { + FieldEntry source = newField("none/a", "a"); + Collection> references = m_index.getFieldReferences(source); + assertThat(references, containsInAnyOrder( + newFieldReferenceByConstructor(source, "none/a", "(Ljava/lang/String;)V"), + newFieldReferenceByMethod(source, "none/a", "a", "()Ljava/lang/String;") + )); + } + + @Test + public void behaviorReferences() { + assertThat(m_index.getBehaviorReferences(newMethod("none/a", "a", "()Ljava/lang/String;")), is(empty())); + } + + @Test + public void innerClasses() { + assertThat(m_index.getInnerClasses("none/a"), is(empty())); + } + + @Test + public void outerClass() { + assertThat(m_index.getOuterClass("a"), is(nullValue())); + } + + @Test + public void isAnonymousClass() { + assertThat(m_index.isAnonymousClass("none/a"), is(false)); + } + + @Test + public void interfaces() { + assertThat(m_index.getInterfaces("none/a"), is(empty())); + } + + @Test + public void implementingClasses() { + assertThat(m_index.getImplementingClasses("none/a"), is(empty())); + } + + @Test + public void isInterface() { + assertThat(m_index.isInterface("none/a"), is(false)); + } + + @Test + public void contains() { + assertThat(m_index.containsObfClass(newClass("none/a")), is(true)); + assertThat(m_index.containsObfClass(newClass("none/b")), is(false)); + assertThat(m_index.containsObfField(newField("none/a", "a")), is(true)); + assertThat(m_index.containsObfField(newField("none/a", "b")), is(false)); + assertThat(m_index.containsObfBehavior(newMethod("none/a", "a", "()Ljava/lang/String;")), is(true)); + assertThat(m_index.containsObfBehavior(newMethod("none/a", "b", "()Ljava/lang/String;")), is(false)); + } +} diff --git a/test/cuchaz/enigma/TestSignature.java b/test/cuchaz/enigma/TestSignature.java new file mode 100644 index 00000000..183a4fd4 --- /dev/null +++ b/test/cuchaz/enigma/TestSignature.java @@ -0,0 +1,266 @@ +package cuchaz.enigma; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import org.junit.Test; + +import cuchaz.enigma.mapping.ClassNameReplacer; +import cuchaz.enigma.mapping.Signature; +import cuchaz.enigma.mapping.Type; + + +public class TestSignature { + + @Test + public void easiest() { + final Signature sig = new Signature("()V"); + assertThat(sig.getArgumentTypes(), is(empty())); + assertThat(sig.getReturnType(), is(new Type("V"))); + } + + @Test + public void primitives() { + { + final Signature sig = new Signature("(I)V"); + assertThat(sig.getArgumentTypes(), contains( + new Type("I") + )); + assertThat(sig.getReturnType(), is(new Type("V"))); + } + { + final Signature sig = new Signature("(I)I"); + assertThat(sig.getArgumentTypes(), contains( + new Type("I") + )); + assertThat(sig.getReturnType(), is(new Type("I"))); + } + { + final Signature sig = new Signature("(IBCJ)Z"); + assertThat(sig.getArgumentTypes(), contains( + new Type("I"), + new Type("B"), + new Type("C"), + new Type("J") + )); + assertThat(sig.getReturnType(), is(new Type("Z"))); + } + } + + @Test + public void classes() { + { + final Signature sig = new Signature("([LFoo;)V"); + assertThat(sig.getArgumentTypes().size(), is(1)); + assertThat(sig.getArgumentTypes().get(0), is(new Type("[LFoo;"))); + assertThat(sig.getReturnType(), is(new Type("V"))); + } + { + final Signature sig = new Signature("(LFoo;)LBar;"); + assertThat(sig.getArgumentTypes(), contains( + new Type("LFoo;") + )); + assertThat(sig.getReturnType(), is(new Type("LBar;"))); + } + { + final Signature sig = new Signature("(LFoo;LMoo;LZoo;)LBar;"); + assertThat(sig.getArgumentTypes(), contains( + new Type("LFoo;"), + new Type("LMoo;"), + new Type("LZoo;") + )); + assertThat(sig.getReturnType(), is(new Type("LBar;"))); + } + { + final Signature sig = new Signature("(LFoo;LMoo;)LBar;"); + assertThat(sig.getArgumentTypes(), contains( + new Type("LFoo;"), + new Type("LMoo;") + )); + assertThat(sig.getReturnType(), is(new Type("LBar;"))); + } + } + + @Test + public void arrays() { + { + final Signature sig = new Signature("([I)V"); + assertThat(sig.getArgumentTypes(), contains( + new Type("[I") + )); + assertThat(sig.getReturnType(), is(new Type("V"))); + } + { + final Signature sig = new Signature("([I)[J"); + assertThat(sig.getArgumentTypes(), contains( + new Type("[I") + )); + assertThat(sig.getReturnType(), is(new Type("[J"))); + } + { + final Signature sig = new Signature("([I[Z[F)[D"); + assertThat(sig.getArgumentTypes(), contains( + new Type("[I"), + new Type("[Z"), + new Type("[F") + )); + assertThat(sig.getReturnType(), is(new Type("[D"))); + } + } + + @Test + public void mixed() { + { + final Signature sig = new Signature("(I[JLFoo;)Z"); + assertThat(sig.getArgumentTypes(), contains( + new Type("I"), + new Type("[J"), + new Type("LFoo;") + )); + assertThat(sig.getReturnType(), is(new Type("Z"))); + } + { + final Signature sig = new Signature("(III)[LFoo;"); + assertThat(sig.getArgumentTypes(), contains( + new Type("I"), + new Type("I"), + new Type("I") + )); + assertThat(sig.getReturnType(), is(new Type("[LFoo;"))); + } + } + + @Test + public void replaceClasses() { + { + final Signature oldSig = new Signature("()V"); + final Signature sig = new Signature(oldSig, new ClassNameReplacer() { + @Override + public String replace(String val) { + return null; + } + }); + assertThat(sig.getArgumentTypes(), is(empty())); + assertThat(sig.getReturnType(), is(new Type("V"))); + } + { + final Signature oldSig = new Signature("(IJLFoo;)V"); + final Signature sig = new Signature(oldSig, new ClassNameReplacer() { + @Override + public String replace(String val) { + return null; + } + }); + assertThat(sig.getArgumentTypes(), contains( + new Type("I"), + new Type("J"), + new Type("LFoo;") + )); + assertThat(sig.getReturnType(), is(new Type("V"))); + } + { + final Signature oldSig = new Signature("(LFoo;LBar;)LMoo;"); + final Signature sig = new Signature(oldSig, new ClassNameReplacer() { + @Override + public String replace(String val) { + if (val.equals("Foo")) { + return "Bar"; + } + return null; + } + }); + assertThat(sig.getArgumentTypes(), contains( + new Type("LBar;"), + new Type("LBar;") + )); + assertThat(sig.getReturnType(), is(new Type("LMoo;"))); + } + { + final Signature oldSig = new Signature("(LFoo;LBar;)LMoo;"); + final Signature sig = new Signature(oldSig, new ClassNameReplacer() { + @Override + public String replace(String val) { + if (val.equals("Moo")) { + return "Cow"; + } + return null; + } + }); + assertThat(sig.getArgumentTypes(), contains( + new Type("LFoo;"), + new Type("LBar;") + )); + assertThat(sig.getReturnType(), is(new Type("LCow;"))); + } + } + + @Test + public void replaceArrayClasses() { + { + final Signature oldSig = new Signature("([LFoo;)[[[LBar;"); + final Signature sig = new Signature(oldSig, new ClassNameReplacer() { + @Override + public String replace(String val) { + if (val.equals("Foo")) { + return "Food"; + } else if (val.equals("Bar")) { + return "Beer"; + } + return null; + } + }); + assertThat(sig.getArgumentTypes(), contains( + new Type("[LFood;") + )); + assertThat(sig.getReturnType(), is(new Type("[[[LBeer;"))); + } + } + + @Test + public void equals() { + + // base + assertThat(new Signature("()V"), is(new Signature("()V"))); + + // arguments + assertThat(new Signature("(I)V"), is(new Signature("(I)V"))); + assertThat(new Signature("(ZIZ)V"), is(new Signature("(ZIZ)V"))); + assertThat(new Signature("(LFoo;)V"), is(new Signature("(LFoo;)V"))); + assertThat(new Signature("(LFoo;LBar;)V"), is(new Signature("(LFoo;LBar;)V"))); + assertThat(new Signature("([I)V"), is(new Signature("([I)V"))); + assertThat(new Signature("([[D[[[J)V"), is(new Signature("([[D[[[J)V"))); + + assertThat(new Signature("()V"), is(not(new Signature("(I)V")))); + assertThat(new Signature("(I)V"), is(not(new Signature("()V")))); + assertThat(new Signature("(IJ)V"), is(not(new Signature("(JI)V")))); + assertThat(new Signature("([[Z)V"), is(not(new Signature("([[LFoo;)V")))); + assertThat(new Signature("(LFoo;LBar;)V"), is(not(new Signature("(LFoo;LCow;)V")))); + assertThat(new Signature("([LFoo;LBar;)V"), is(not(new Signature("(LFoo;LCow;)V")))); + + // return type + assertThat(new Signature("()I"), is(new Signature("()I"))); + assertThat(new Signature("()Z"), is(new Signature("()Z"))); + assertThat(new Signature("()[D"), is(new Signature("()[D"))); + assertThat(new Signature("()[[[Z"), is(new Signature("()[[[Z"))); + assertThat(new Signature("()LFoo;"), is(new Signature("()LFoo;"))); + assertThat(new Signature("()[LFoo;"), is(new Signature("()[LFoo;"))); + + assertThat(new Signature("()I"), is(not(new Signature("()Z")))); + assertThat(new Signature("()Z"), is(not(new Signature("()I")))); + assertThat(new Signature("()[D"), is(not(new Signature("()[J")))); + assertThat(new Signature("()[[[Z"), is(not(new Signature("()[[Z")))); + assertThat(new Signature("()LFoo;"), is(not(new Signature("()LBar;")))); + assertThat(new Signature("()[LFoo;"), is(not(new Signature("()[LBar;")))); + } + + @Test + public void testToString() { + assertThat(new Signature("()V").toString(), is("()V")); + assertThat(new Signature("(I)V").toString(), is("(I)V")); + assertThat(new Signature("(ZIZ)V").toString(), is("(ZIZ)V")); + assertThat(new Signature("(LFoo;)V").toString(), is("(LFoo;)V")); + assertThat(new Signature("(LFoo;LBar;)V").toString(), is("(LFoo;LBar;)V")); + assertThat(new Signature("([I)V").toString(), is("([I)V")); + assertThat(new Signature("([[D[[[J)V").toString(), is("([[D[[[J)V")); + } +} diff --git a/test/cuchaz/enigma/TestSourceIndex.java b/test/cuchaz/enigma/TestSourceIndex.java new file mode 100644 index 00000000..357acb62 --- /dev/null +++ b/test/cuchaz/enigma/TestSourceIndex.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma; + +import java.util.Set; +import java.util.jar.JarFile; + +import org.junit.Test; + +import com.google.common.collect.Sets; +import com.strobel.decompiler.languages.java.ast.CompilationUnit; + +import cuchaz.enigma.mapping.ClassEntry; + +public class TestSourceIndex { + + // TEMP + //@Test + public void indexEverything() + throws Exception { + Deobfuscator deobfuscator = new Deobfuscator(new JarFile("input/1.8.jar")); + + // get all classes that aren't inner classes + Set classEntries = Sets.newHashSet(); + for (ClassEntry obfClassEntry : deobfuscator.getJarIndex().getObfClassEntries()) { + if (!obfClassEntry.isInnerClass()) { + classEntries.add(obfClassEntry); + } + } + + for (ClassEntry obfClassEntry : classEntries) { + try { + CompilationUnit tree = deobfuscator.getSourceTree(obfClassEntry.getName()); + String source = deobfuscator.getSource(tree); + deobfuscator.getSourceIndex(tree, source); + } catch (Throwable t) { + throw new Error("Unable to index " + obfClassEntry, t); + } + } + } +} diff --git a/test/cuchaz/enigma/TestTokensConstructors.java b/test/cuchaz/enigma/TestTokensConstructors.java new file mode 100644 index 00000000..6758d2a7 --- /dev/null +++ b/test/cuchaz/enigma/TestTokensConstructors.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma; + +import static cuchaz.enigma.EntryFactory.*; +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import java.util.jar.JarFile; + +import org.junit.Test; + +import cuchaz.enigma.mapping.BehaviorEntry; + +public class TestTokensConstructors extends TokenChecker { + + public TestTokensConstructors() + throws Exception { + super(new JarFile("build/testConstructors.obf.jar")); + } + + @Test + public void baseDeclarations() { + assertThat(getDeclarationToken(newConstructor("none/a", "()V")), is("a")); + assertThat(getDeclarationToken(newConstructor("none/a", "(I)V")), is("a")); + } + + @Test + public void subDeclarations() { + assertThat(getDeclarationToken(newConstructor("none/d", "()V")), is("d")); + assertThat(getDeclarationToken(newConstructor("none/d", "(I)V")), is("d")); + assertThat(getDeclarationToken(newConstructor("none/d", "(II)V")), is("d")); + assertThat(getDeclarationToken(newConstructor("none/d", "(III)V")), is("d")); + } + + @Test + public void subsubDeclarations() { + assertThat(getDeclarationToken(newConstructor("none/e", "(I)V")), is("e")); + } + + @Test + public void defaultDeclarations() { + assertThat(getDeclarationToken(newConstructor("none/c", "()V")), nullValue()); + } + + @Test + public void baseDefaultReferences() { + BehaviorEntry source = newConstructor("none/a", "()V"); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "none/b", "a", "()V")), + containsInAnyOrder("a") + ); + assertThat( + getReferenceTokens(newBehaviorReferenceByConstructor(source, "none/d", "()V")), + is(empty()) // implicit call, not decompiled to token + ); + assertThat( + getReferenceTokens(newBehaviorReferenceByConstructor(source, "none/d", "(III)V")), + is(empty()) // implicit call, not decompiled to token + ); + } + + @Test + public void baseIntReferences() { + BehaviorEntry source = newConstructor("none/a", "(I)V"); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "none/b", "b", "()V")), + containsInAnyOrder("a") + ); + } + + @Test + public void subDefaultReferences() { + BehaviorEntry source = newConstructor("none/d", "()V"); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "none/b", "c", "()V")), + containsInAnyOrder("d") + ); + assertThat( + getReferenceTokens(newBehaviorReferenceByConstructor(source, "none/d", "(I)V")), + containsInAnyOrder("this") + ); + } + + @Test + public void subIntReferences() { + BehaviorEntry source = newConstructor("none/d", "(I)V"); + assertThat(getReferenceTokens( + newBehaviorReferenceByMethod(source, "none/b", "d", "()V")), + containsInAnyOrder("d") + ); + assertThat(getReferenceTokens( + newBehaviorReferenceByConstructor(source, "none/d", "(II)V")), + containsInAnyOrder("this") + ); + assertThat(getReferenceTokens( + newBehaviorReferenceByConstructor(source, "none/e", "(I)V")), + containsInAnyOrder("super") + ); + } + + @Test + public void subIntIntReferences() { + BehaviorEntry source = newConstructor("none/d", "(II)V"); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "none/b", "e", "()V")), + containsInAnyOrder("d") + ); + } + + @Test + public void subsubIntReferences() { + BehaviorEntry source = newConstructor("none/e", "(I)V"); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "none/b", "f", "()V")), + containsInAnyOrder("e") + ); + } + + @Test + public void defaultConstructableReferences() { + BehaviorEntry source = newConstructor("none/c", "()V"); + assertThat( + getReferenceTokens(newBehaviorReferenceByMethod(source, "none/b", "g", "()V")), + containsInAnyOrder("c") + ); + } +} diff --git a/test/cuchaz/enigma/TestTranslator.java b/test/cuchaz/enigma/TestTranslator.java new file mode 100644 index 00000000..290f6f04 --- /dev/null +++ b/test/cuchaz/enigma/TestTranslator.java @@ -0,0 +1,39 @@ +package cuchaz.enigma; + +import static cuchaz.enigma.EntryFactory.*; +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.jar.JarFile; + +import org.junit.Test; + +import cuchaz.enigma.mapping.Mappings; +import cuchaz.enigma.mapping.MappingsReader; +import cuchaz.enigma.mapping.TranslationDirection; +import cuchaz.enigma.mapping.Translator; + + +public class TestTranslator { + + private Deobfuscator m_deobfuscator; + private Mappings m_mappings; + + public TestTranslator() + throws Exception { + m_deobfuscator = new Deobfuscator(new JarFile("build/testTranslation.obf.jar")); + try (InputStream in = getClass().getResourceAsStream("/cuchaz/enigma/resources/translation.mappings")) { + m_mappings = new MappingsReader().read(new InputStreamReader(in)); + m_deobfuscator.setMappings(m_mappings); + } + } + + @Test + public void deobfuscatingTranslations() + throws Exception { + Translator translator = m_deobfuscator.getTranslator(TranslationDirection.Deobfuscating); + assertThat(translator.translateEntry(newClass("none/a")), is(newClass("deobf/A"))); + } +} diff --git a/test/cuchaz/enigma/TestType.java b/test/cuchaz/enigma/TestType.java new file mode 100644 index 00000000..7c3cebe2 --- /dev/null +++ b/test/cuchaz/enigma/TestType.java @@ -0,0 +1,229 @@ +package cuchaz.enigma; + +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import cuchaz.enigma.mapping.Type; + +import static cuchaz.enigma.EntryFactory.*; + + +public class TestType { + + @Test + public void isVoid() { + assertThat(new Type("V").isVoid(), is(true)); + assertThat(new Type("Z").isVoid(), is(false)); + assertThat(new Type("B").isVoid(), is(false)); + assertThat(new Type("C").isVoid(), is(false)); + assertThat(new Type("I").isVoid(), is(false)); + assertThat(new Type("J").isVoid(), is(false)); + assertThat(new Type("F").isVoid(), is(false)); + assertThat(new Type("D").isVoid(), is(false)); + assertThat(new Type("LFoo;").isVoid(), is(false)); + assertThat(new Type("[I").isVoid(), is(false)); + } + + @Test + public void isPrimitive() { + assertThat(new Type("V").isPrimitive(), is(false)); + assertThat(new Type("Z").isPrimitive(), is(true)); + assertThat(new Type("B").isPrimitive(), is(true)); + assertThat(new Type("C").isPrimitive(), is(true)); + assertThat(new Type("I").isPrimitive(), is(true)); + assertThat(new Type("J").isPrimitive(), is(true)); + assertThat(new Type("F").isPrimitive(), is(true)); + assertThat(new Type("D").isPrimitive(), is(true)); + assertThat(new Type("LFoo;").isPrimitive(), is(false)); + assertThat(new Type("[I").isPrimitive(), is(false)); + } + + @Test + public void getPrimitive() { + assertThat(new Type("Z").getPrimitive(), is(Type.Primitive.Boolean)); + assertThat(new Type("B").getPrimitive(), is(Type.Primitive.Byte)); + assertThat(new Type("C").getPrimitive(), is(Type.Primitive.Character)); + assertThat(new Type("I").getPrimitive(), is(Type.Primitive.Integer)); + assertThat(new Type("J").getPrimitive(), is(Type.Primitive.Long)); + assertThat(new Type("F").getPrimitive(), is(Type.Primitive.Float)); + assertThat(new Type("D").getPrimitive(), is(Type.Primitive.Double)); + } + + @Test + public void isClass() { + assertThat(new Type("V").isClass(), is(false)); + assertThat(new Type("Z").isClass(), is(false)); + assertThat(new Type("B").isClass(), is(false)); + assertThat(new Type("C").isClass(), is(false)); + assertThat(new Type("I").isClass(), is(false)); + assertThat(new Type("J").isClass(), is(false)); + assertThat(new Type("F").isClass(), is(false)); + assertThat(new Type("D").isClass(), is(false)); + assertThat(new Type("LFoo;").isClass(), is(true)); + assertThat(new Type("[I").isClass(), is(false)); + } + + @Test + public void getClassEntry() { + assertThat(new Type("LFoo;").getClassEntry(), is(newClass("Foo"))); + assertThat(new Type("LFoo;").getClassEntry(), is(newClass("Foo"))); + } + + @Test + public void getArrayClassEntry() { + assertThat(new Type("[LFoo;").getClassEntry(), is(newClass("Foo"))); + assertThat(new Type("[[[LFoo;").getClassEntry(), is(newClass("Foo"))); + } + + @Test + public void isArray() { + assertThat(new Type("V").isArray(), is(false)); + assertThat(new Type("Z").isArray(), is(false)); + assertThat(new Type("B").isArray(), is(false)); + assertThat(new Type("C").isArray(), is(false)); + assertThat(new Type("I").isArray(), is(false)); + assertThat(new Type("J").isArray(), is(false)); + assertThat(new Type("F").isArray(), is(false)); + assertThat(new Type("D").isArray(), is(false)); + assertThat(new Type("LFoo;").isArray(), is(false)); + assertThat(new Type("[I").isArray(), is(true)); + } + + @Test + public void getArrayDimension() { + assertThat(new Type("[I").getArrayDimension(), is(1)); + assertThat(new Type("[[I").getArrayDimension(), is(2)); + assertThat(new Type("[[[I").getArrayDimension(), is(3)); + } + + @Test + public void getArrayType() { + assertThat(new Type("[I").getArrayType(), is(new Type("I"))); + assertThat(new Type("[[I").getArrayType(), is(new Type("I"))); + assertThat(new Type("[[[I").getArrayType(), is(new Type("I"))); + assertThat(new Type("[Ljava/lang/String;").getArrayType(), is(new Type("Ljava/lang/String;"))); + } + + @Test + public void hasClass() { + assertThat(new Type("LFoo;").hasClass(), is(true)); + assertThat(new Type("LCow;").hasClass(), is(true)); + assertThat(new Type("[LBar;").hasClass(), is(true)); + assertThat(new Type("[[[LCat;").hasClass(), is(true)); + + assertThat(new Type("V").hasClass(), is(false)); + assertThat(new Type("[I").hasClass(), is(false)); + assertThat(new Type("[[[I").hasClass(), is(false)); + assertThat(new Type("Z").hasClass(), is(false)); + } + + @Test + public void parseVoid() { + final String answer = "V"; + assertThat(Type.parseFirst("V"), is(answer)); + assertThat(Type.parseFirst("VVV"), is(answer)); + assertThat(Type.parseFirst("VIJ"), is(answer)); + assertThat(Type.parseFirst("V[I"), is(answer)); + assertThat(Type.parseFirst("VLFoo;"), is(answer)); + assertThat(Type.parseFirst("V[LFoo;"), is(answer)); + } + + @Test + public void parsePrimitive() { + final String answer = "I"; + assertThat(Type.parseFirst("I"), is(answer)); + assertThat(Type.parseFirst("III"), is(answer)); + assertThat(Type.parseFirst("IJZ"), is(answer)); + assertThat(Type.parseFirst("I[I"), is(answer)); + assertThat(Type.parseFirst("ILFoo;"), is(answer)); + assertThat(Type.parseFirst("I[LFoo;"), is(answer)); + } + + @Test + public void parseClass() { + { + final String answer = "LFoo;"; + assertThat(Type.parseFirst("LFoo;"), is(answer)); + assertThat(Type.parseFirst("LFoo;I"), is(answer)); + assertThat(Type.parseFirst("LFoo;JZ"), is(answer)); + assertThat(Type.parseFirst("LFoo;[I"), is(answer)); + assertThat(Type.parseFirst("LFoo;LFoo;"), is(answer)); + assertThat(Type.parseFirst("LFoo;[LFoo;"), is(answer)); + } + { + final String answer = "LFoo;"; + assertThat(Type.parseFirst("LFoo;"), is(answer)); + assertThat(Type.parseFirst("LFoo;I"), is(answer)); + assertThat(Type.parseFirst("LFoo;JZ"), is(answer)); + assertThat(Type.parseFirst("LFoo;[I"), is(answer)); + assertThat(Type.parseFirst("LFoo;LFoo;"), is(answer)); + assertThat(Type.parseFirst("LFoo;[LFoo;"), is(answer)); + } + { + final String answer = "LFoo;"; + assertThat(Type.parseFirst("LFoo;"), is(answer)); + assertThat(Type.parseFirst("LFoo;I"), is(answer)); + assertThat(Type.parseFirst("LFoo;JZ"), is(answer)); + assertThat(Type.parseFirst("LFoo;[I"), is(answer)); + assertThat(Type.parseFirst("LFoo;LFoo;"), is(answer)); + assertThat(Type.parseFirst("LFoo;[LFoo;"), is(answer)); + } + } + + @Test + public void parseArray() { + { + final String answer = "[I"; + assertThat(Type.parseFirst("[I"), is(answer)); + assertThat(Type.parseFirst("[III"), is(answer)); + assertThat(Type.parseFirst("[IJZ"), is(answer)); + assertThat(Type.parseFirst("[I[I"), is(answer)); + assertThat(Type.parseFirst("[ILFoo;"), is(answer)); + } + { + final String answer = "[[I"; + assertThat(Type.parseFirst("[[I"), is(answer)); + assertThat(Type.parseFirst("[[III"), is(answer)); + assertThat(Type.parseFirst("[[IJZ"), is(answer)); + assertThat(Type.parseFirst("[[I[I"), is(answer)); + assertThat(Type.parseFirst("[[ILFoo;"), is(answer)); + } + { + final String answer = "[LFoo;"; + assertThat(Type.parseFirst("[LFoo;"), is(answer)); + assertThat(Type.parseFirst("[LFoo;II"), is(answer)); + assertThat(Type.parseFirst("[LFoo;JZ"), is(answer)); + assertThat(Type.parseFirst("[LFoo;[I"), is(answer)); + assertThat(Type.parseFirst("[LFoo;LFoo;"), is(answer)); + } + } + + @Test + public void equals() { + assertThat(new Type("V"), is(new Type("V"))); + assertThat(new Type("Z"), is(new Type("Z"))); + assertThat(new Type("B"), is(new Type("B"))); + assertThat(new Type("C"), is(new Type("C"))); + assertThat(new Type("I"), is(new Type("I"))); + assertThat(new Type("J"), is(new Type("J"))); + assertThat(new Type("F"), is(new Type("F"))); + assertThat(new Type("D"), is(new Type("D"))); + assertThat(new Type("LFoo;"), is(new Type("LFoo;"))); + assertThat(new Type("[I"), is(new Type("[I"))); + assertThat(new Type("[[[I"), is(new Type("[[[I"))); + assertThat(new Type("[LFoo;"), is(new Type("[LFoo;"))); + assertThat(new Type("LFoo;"), is(new Type("LFoo;"))); + + assertThat(new Type("V"), is(not(new Type("I")))); + assertThat(new Type("I"), is(not(new Type("J")))); + assertThat(new Type("I"), is(not(new Type("LBar;")))); + assertThat(new Type("I"), is(not(new Type("[I")))); + assertThat(new Type("LFoo;"), is(not(new Type("LBar;")))); + assertThat(new Type("LFoo;"), is(not(new Type("LFoo;")))); + assertThat(new Type("[I"), is(not(new Type("[Z")))); + assertThat(new Type("[[[I"), is(not(new Type("[I")))); + assertThat(new Type("[LFoo;"), is(not(new Type("[LBar;")))); + } +} diff --git a/test/cuchaz/enigma/TokenChecker.java b/test/cuchaz/enigma/TokenChecker.java new file mode 100644 index 00000000..a72c2fc8 --- /dev/null +++ b/test/cuchaz/enigma/TokenChecker.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2014 Jeff Martin. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the GNU Public License v3.0 + * which accompanies this distribution, and is available at + * http://www.gnu.org/licenses/gpl.html + * + * Contributors: + * Jeff Martin - initial API and implementation + ******************************************************************************/ +package cuchaz.enigma; + +import java.io.IOException; +import java.util.Collection; +import java.util.List; +import java.util.jar.JarFile; + +import com.google.common.collect.Lists; +import com.strobel.decompiler.languages.java.ast.CompilationUnit; + +import cuchaz.enigma.analysis.EntryReference; +import cuchaz.enigma.analysis.SourceIndex; +import cuchaz.enigma.analysis.Token; +import cuchaz.enigma.mapping.Entry; + +public class TokenChecker { + + private Deobfuscator m_deobfuscator; + + protected TokenChecker(JarFile jarFile) + throws IOException { + m_deobfuscator = new Deobfuscator(jarFile); + } + + protected String getDeclarationToken(Entry entry) { + // decompile the class + CompilationUnit tree = m_deobfuscator.getSourceTree(entry.getClassName()); + // DEBUG + // tree.acceptVisitor( new TreeDumpVisitor( new File( "tree." + entry.getClassName().replace( '/', '.' ) + ".txt" ) ), null ); + String source = m_deobfuscator.getSource(tree); + SourceIndex index = m_deobfuscator.getSourceIndex(tree, source); + + // get the token value + Token token = index.getDeclarationToken(entry); + if (token == null) { + return null; + } + return source.substring(token.start, token.end); + } + + @SuppressWarnings("unchecked") + protected Collection getReferenceTokens(EntryReference reference) { + // decompile the class + CompilationUnit tree = m_deobfuscator.getSourceTree(reference.context.getClassName()); + String source = m_deobfuscator.getSource(tree); + SourceIndex index = m_deobfuscator.getSourceIndex(tree, source); + + // get the token values + List values = Lists.newArrayList(); + for (Token token : index.getReferenceTokens((EntryReference)reference)) { + values.add(source.substring(token.start, token.end)); + } + return values; + } +} diff --git a/test/cuchaz/enigma/inputs/Keep.java b/test/cuchaz/enigma/inputs/Keep.java new file mode 100644 index 00000000..390e82fb --- /dev/null +++ b/test/cuchaz/enigma/inputs/Keep.java @@ -0,0 +1,7 @@ +package cuchaz.enigma.inputs; + +public class Keep { + public static void main(String[] args) { + System.out.println("Keep me!"); + } +} diff --git a/test/cuchaz/enigma/inputs/constructors/BaseClass.java b/test/cuchaz/enigma/inputs/constructors/BaseClass.java new file mode 100644 index 00000000..93453086 --- /dev/null +++ b/test/cuchaz/enigma/inputs/constructors/BaseClass.java @@ -0,0 +1,15 @@ +package cuchaz.enigma.inputs.constructors; + +// none/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/test/cuchaz/enigma/inputs/constructors/Caller.java b/test/cuchaz/enigma/inputs/constructors/Caller.java new file mode 100644 index 00000000..57278751 --- /dev/null +++ b/test/cuchaz/enigma/inputs/constructors/Caller.java @@ -0,0 +1,47 @@ +package cuchaz.enigma.inputs.constructors; + +// none/b +public class Caller { + + // a()V + public void callBaseDefault() { + // none/a.()V + System.out.println(new BaseClass()); + } + + // b()V + public void callBaseInt() { + // none/a.(I)V + System.out.println(new BaseClass(5)); + } + + // c()V + public void callSubDefault() { + // none/d.()V + System.out.println(new SubClass()); + } + + // d()V + public void callSubInt() { + // none/d.(I)V + System.out.println(new SubClass(6)); + } + + // e()V + public void callSubIntInt() { + // none/d.(II)V + System.out.println(new SubClass(4, 2)); + } + + // f()V + public void callSubSubInt() { + // none/e.(I)V + System.out.println(new SubSubClass(3)); + } + + // g()V + public void callDefaultConstructable() { + // none/c.()V + System.out.println(new DefaultConstructable()); + } +} diff --git a/test/cuchaz/enigma/inputs/constructors/DefaultConstructable.java b/test/cuchaz/enigma/inputs/constructors/DefaultConstructable.java new file mode 100644 index 00000000..26a3ddbb --- /dev/null +++ b/test/cuchaz/enigma/inputs/constructors/DefaultConstructable.java @@ -0,0 +1,5 @@ +package cuchaz.enigma.inputs.constructors; + +public class DefaultConstructable { + // only default constructor +} diff --git a/test/cuchaz/enigma/inputs/constructors/SubClass.java b/test/cuchaz/enigma/inputs/constructors/SubClass.java new file mode 100644 index 00000000..fecfa2b5 --- /dev/null +++ b/test/cuchaz/enigma/inputs/constructors/SubClass.java @@ -0,0 +1,28 @@ +package cuchaz.enigma.inputs.constructors; + +// none/d extends none/a +public class SubClass extends BaseClass { + + // ()V + public SubClass() { + // none/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) { + // none/a.()V + } +} diff --git a/test/cuchaz/enigma/inputs/constructors/SubSubClass.java b/test/cuchaz/enigma/inputs/constructors/SubSubClass.java new file mode 100644 index 00000000..ab84161b --- /dev/null +++ b/test/cuchaz/enigma/inputs/constructors/SubSubClass.java @@ -0,0 +1,11 @@ +package cuchaz.enigma.inputs.constructors; + +// none/e extends none/d +public class SubSubClass extends SubClass { + + // (I)V + public SubSubClass(int i) { + // none/c.(I)V + super(i); + } +} diff --git a/test/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java b/test/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java new file mode 100644 index 00000000..5b416c41 --- /dev/null +++ b/test/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java @@ -0,0 +1,21 @@ +package cuchaz.enigma.inputs.inheritanceTree; + +// none/a +public abstract class BaseClass { + + // a + private String m_name; + + // (Ljava/lang/String;)V + protected BaseClass(String name) { + m_name = name; + } + + // a()Ljava/lang/String; + public String getName() { + return m_name; + } + + // a()V + public abstract void doBaseThings(); +} diff --git a/test/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java b/test/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java new file mode 100644 index 00000000..7a99d516 --- /dev/null +++ b/test/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java @@ -0,0 +1,11 @@ +package cuchaz.enigma.inputs.inheritanceTree; + +// none/b extends none/a +public abstract class SubclassA extends BaseClass { + + // (Ljava/lang/String;)V + protected SubclassA(String name) { + // call to none/a.(Ljava/lang/String)V + super(name); + } +} diff --git a/test/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java b/test/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java new file mode 100644 index 00000000..c9485d31 --- /dev/null +++ b/test/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java @@ -0,0 +1,30 @@ +package cuchaz.enigma.inputs.inheritanceTree; + +// none/c extends none/a +public class SubclassB extends BaseClass { + + // a + private int m_numThings; + + // ()V + protected SubclassB() { + // none/a.(Ljava/lang/String;)V + super("B"); + + // access to a + m_numThings = 4; + } + + @Override + // a()V + public void doBaseThings() { + // call to none/a.a()Ljava/lang/String; + System.out.println("Base things by B! " + getName()); + } + + // b()V + public void doBThings() { + // access to a + System.out.println("" + m_numThings + " B things!"); + } +} diff --git a/test/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java b/test/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java new file mode 100644 index 00000000..afd03ac4 --- /dev/null +++ b/test/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java @@ -0,0 +1,24 @@ +package cuchaz.enigma.inputs.inheritanceTree; + +// none/d extends none/b +public class SubsubclassAA extends SubclassA { + + protected SubsubclassAA() { + // call to none/b.(Ljava/lang/String;)V + super("AA"); + } + + @Override + // a()Ljava/lang/String; + public String getName() { + // call to none/b.a()Ljava/lang/String; + return "subsub" + super.getName(); + } + + @Override + // a()V + public void doBaseThings() { + // call to none/d.a()Ljava/lang/String; + System.out.println("Base things by " + getName()); + } +} diff --git a/test/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java b/test/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java new file mode 100644 index 00000000..f7118f63 --- /dev/null +++ b/test/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java @@ -0,0 +1,14 @@ +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/test/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java b/test/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java new file mode 100644 index 00000000..42fba9a8 --- /dev/null +++ b/test/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java @@ -0,0 +1,13 @@ +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/test/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java b/test/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java new file mode 100644 index 00000000..8fa6c5b8 --- /dev/null +++ b/test/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java @@ -0,0 +1,20 @@ +package cuchaz.enigma.inputs.innerClasses; + +@SuppressWarnings("unused") +public class C_ConstructorArgs { + + class Inner { + + private int a; + + public Inner(int a) { + this.a = a; + } + } + + Inner i; + + public void foo() { + i = new Inner(5); + } +} diff --git a/test/cuchaz/enigma/inputs/innerClasses/D_Simple.java b/test/cuchaz/enigma/inputs/innerClasses/D_Simple.java new file mode 100644 index 00000000..c4fc0ef9 --- /dev/null +++ b/test/cuchaz/enigma/inputs/innerClasses/D_Simple.java @@ -0,0 +1,8 @@ +package cuchaz.enigma.inputs.innerClasses; + +public class D_Simple { + + class Inner { + // nothing to do + } +} diff --git a/test/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java b/test/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java new file mode 100644 index 00000000..e1de53cb --- /dev/null +++ b/test/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java @@ -0,0 +1,21 @@ +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/test/cuchaz/enigma/inputs/loneClass/LoneClass.java b/test/cuchaz/enigma/inputs/loneClass/LoneClass.java new file mode 100644 index 00000000..18c716e9 --- /dev/null +++ b/test/cuchaz/enigma/inputs/loneClass/LoneClass.java @@ -0,0 +1,14 @@ +package cuchaz.enigma.inputs.loneClass; + +public class LoneClass { + + private String m_name; + + public LoneClass(String name) { + m_name = name; + } + + public String getName() { + return m_name; + } +} diff --git a/test/cuchaz/enigma/inputs/translation/A.java b/test/cuchaz/enigma/inputs/translation/A.java new file mode 100644 index 00000000..b8aaf11e --- /dev/null +++ b/test/cuchaz/enigma/inputs/translation/A.java @@ -0,0 +1,8 @@ +package cuchaz.enigma.inputs.translation; + +public class A { + + public int one; + public float two; + public String three; +} diff --git a/test/cuchaz/enigma/resources/translation.mappings b/test/cuchaz/enigma/resources/translation.mappings new file mode 100644 index 00000000..70755bf6 --- /dev/null +++ b/test/cuchaz/enigma/resources/translation.mappings @@ -0,0 +1,4 @@ +CLASS none/a deobf/A + FIELD a one + FIELD b two + FIELD c three \ No newline at end of file -- cgit v1.2.3