From 4be005617b3b8c3578cca07c5d085d12916f0d1d Mon Sep 17 00:00:00 2001 From: lclc98 Date: Thu, 30 Jun 2016 00:49:21 +1000 Subject: Json format (#2) * Added new format * Fixed bug * Updated Version --- src/test/java/cuchaz/enigma/TestDeobfed.java | 95 ++++++++ src/test/java/cuchaz/enigma/TestDeobfuscator.java | 57 +++++ src/test/java/cuchaz/enigma/TestEntryFactory.java | 67 ++++++ src/test/java/cuchaz/enigma/TestInnerClasses.java | 132 ++++++++++ .../enigma/TestJarIndexConstructorReferences.java | 124 ++++++++++ .../cuchaz/enigma/TestJarIndexInheritanceTree.java | 239 ++++++++++++++++++ .../java/cuchaz/enigma/TestJarIndexLoneClass.java | 164 +++++++++++++ src/test/java/cuchaz/enigma/TestSignature.java | 268 +++++++++++++++++++++ src/test/java/cuchaz/enigma/TestSourceIndex.java | 67 ++++++ .../java/cuchaz/enigma/TestTokensConstructors.java | 136 +++++++++++ src/test/java/cuchaz/enigma/TestTranslator.java | 171 +++++++++++++ src/test/java/cuchaz/enigma/TestType.java | 243 +++++++++++++++++++ src/test/java/cuchaz/enigma/TokenChecker.java | 65 +++++ src/test/java/cuchaz/enigma/inputs/Keep.java | 17 ++ .../enigma/inputs/constructors/BaseClass.java | 25 ++ .../cuchaz/enigma/inputs/constructors/Caller.java | 57 +++++ .../inputs/constructors/DefaultConstructable.java | 15 ++ .../enigma/inputs/constructors/SubClass.java | 38 +++ .../enigma/inputs/constructors/SubSubClass.java | 21 ++ .../enigma/inputs/inheritanceTree/BaseClass.java | 31 +++ .../enigma/inputs/inheritanceTree/SubclassA.java | 21 ++ .../enigma/inputs/inheritanceTree/SubclassB.java | 40 +++ .../inputs/inheritanceTree/SubsubclassAA.java | 34 +++ .../enigma/inputs/innerClasses/A_Anonymous.java | 24 ++ .../innerClasses/B_AnonymousWithScopeArgs.java | 23 ++ .../inputs/innerClasses/C_ConstructorArgs.java | 30 +++ .../enigma/inputs/innerClasses/D_Simple.java | 18 ++ .../innerClasses/E_AnonymousWithOuterAccess.java | 31 +++ .../enigma/inputs/innerClasses/F_ClassTree.java | 30 +++ .../cuchaz/enigma/inputs/loneClass/LoneClass.java | 24 ++ .../cuchaz/enigma/inputs/translation/A_Basic.java | 32 +++ .../enigma/inputs/translation/B_BaseClass.java | 25 ++ .../enigma/inputs/translation/C_SubClass.java | 27 +++ .../inputs/translation/D_AnonymousTesting.java | 28 +++ .../enigma/inputs/translation/E_Bridges.java | 32 +++ .../enigma/inputs/translation/F_ObjectMethods.java | 29 +++ .../enigma/inputs/translation/G_OuterClass.java | 36 +++ .../enigma/inputs/translation/H_NamelessClass.java | 38 +++ .../enigma/inputs/translation/I_Generics.java | 35 +++ .../cuchaz/enigma/resources/translation.mappings | 41 ++++ 40 files changed, 2630 insertions(+) create mode 100644 src/test/java/cuchaz/enigma/TestDeobfed.java create mode 100644 src/test/java/cuchaz/enigma/TestDeobfuscator.java create mode 100644 src/test/java/cuchaz/enigma/TestEntryFactory.java create mode 100644 src/test/java/cuchaz/enigma/TestInnerClasses.java create mode 100644 src/test/java/cuchaz/enigma/TestJarIndexConstructorReferences.java create mode 100644 src/test/java/cuchaz/enigma/TestJarIndexInheritanceTree.java create mode 100644 src/test/java/cuchaz/enigma/TestJarIndexLoneClass.java create mode 100644 src/test/java/cuchaz/enigma/TestSignature.java create mode 100644 src/test/java/cuchaz/enigma/TestSourceIndex.java create mode 100644 src/test/java/cuchaz/enigma/TestTokensConstructors.java create mode 100644 src/test/java/cuchaz/enigma/TestTranslator.java create mode 100644 src/test/java/cuchaz/enigma/TestType.java create mode 100644 src/test/java/cuchaz/enigma/TokenChecker.java create mode 100644 src/test/java/cuchaz/enigma/inputs/Keep.java create mode 100644 src/test/java/cuchaz/enigma/inputs/constructors/BaseClass.java create mode 100644 src/test/java/cuchaz/enigma/inputs/constructors/Caller.java create mode 100644 src/test/java/cuchaz/enigma/inputs/constructors/DefaultConstructable.java create mode 100644 src/test/java/cuchaz/enigma/inputs/constructors/SubClass.java create mode 100644 src/test/java/cuchaz/enigma/inputs/constructors/SubSubClass.java create mode 100644 src/test/java/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java create mode 100644 src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java create mode 100644 src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java create mode 100644 src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java create mode 100644 src/test/java/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java create mode 100644 src/test/java/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java create mode 100644 src/test/java/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java create mode 100644 src/test/java/cuchaz/enigma/inputs/innerClasses/D_Simple.java create mode 100644 src/test/java/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java create mode 100644 src/test/java/cuchaz/enigma/inputs/innerClasses/F_ClassTree.java create mode 100644 src/test/java/cuchaz/enigma/inputs/loneClass/LoneClass.java create mode 100644 src/test/java/cuchaz/enigma/inputs/translation/A_Basic.java create mode 100644 src/test/java/cuchaz/enigma/inputs/translation/B_BaseClass.java create mode 100644 src/test/java/cuchaz/enigma/inputs/translation/C_SubClass.java create mode 100644 src/test/java/cuchaz/enigma/inputs/translation/D_AnonymousTesting.java create mode 100644 src/test/java/cuchaz/enigma/inputs/translation/E_Bridges.java create mode 100644 src/test/java/cuchaz/enigma/inputs/translation/F_ObjectMethods.java create mode 100644 src/test/java/cuchaz/enigma/inputs/translation/G_OuterClass.java create mode 100644 src/test/java/cuchaz/enigma/inputs/translation/H_NamelessClass.java create mode 100644 src/test/java/cuchaz/enigma/inputs/translation/I_Generics.java create mode 100644 src/test/java/cuchaz/enigma/resources/translation.mappings (limited to 'src/test/java') diff --git a/src/test/java/cuchaz/enigma/TestDeobfed.java b/src/test/java/cuchaz/enigma/TestDeobfed.java new file mode 100644 index 0000000..5f3ef8c --- /dev/null +++ b/src/test/java/cuchaz/enigma/TestDeobfed.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * 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 static cuchaz.enigma.TestEntryFactory.*; +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import java.util.jar.JarFile; + +import org.junit.BeforeClass; +import org.junit.Test; + +import cuchaz.enigma.analysis.JarIndex; + + +public class TestDeobfed { + + private static JarFile m_jar; + private static JarIndex m_index; + + @BeforeClass + public static void beforeClass() + throws Exception { + m_jar = new JarFile("build/test-deobf/translation.jar"); + m_index = new JarIndex(); + m_index.indexJar(m_jar, true); + } + + @Test + public void obfEntries() { + assertThat(m_index.getObfClassEntries(), containsInAnyOrder( + newClass("cuchaz/enigma/inputs/Keep"), + newClass("none/a"), + newClass("none/b"), + newClass("none/c"), + newClass("none/d"), + newClass("none/d$1"), + newClass("none/e"), + newClass("none/f"), + newClass("none/g"), + newClass("none/g$a"), + newClass("none/g$a$a"), + newClass("none/g$b"), + newClass("none/g$b$a"), + newClass("none/h"), + newClass("none/h$a"), + newClass("none/h$a$a"), + newClass("none/h$b"), + newClass("none/h$b$a"), + newClass("none/h$b$a$a"), + newClass("none/h$b$a$b"), + newClass("none/i"), + newClass("none/i$a"), + newClass("none/i$b") + )); + } + + @Test + public void decompile() + throws Exception { + Deobfuscator deobfuscator = new Deobfuscator(m_jar); + deobfuscator.getSourceTree("none/a"); + deobfuscator.getSourceTree("none/b"); + deobfuscator.getSourceTree("none/c"); + deobfuscator.getSourceTree("none/d"); + deobfuscator.getSourceTree("none/d$1"); + deobfuscator.getSourceTree("none/e"); + deobfuscator.getSourceTree("none/f"); + deobfuscator.getSourceTree("none/g"); + deobfuscator.getSourceTree("none/g$a"); + deobfuscator.getSourceTree("none/g$a$a"); + deobfuscator.getSourceTree("none/g$b"); + deobfuscator.getSourceTree("none/g$b$a"); + deobfuscator.getSourceTree("none/h"); + deobfuscator.getSourceTree("none/h$a"); + deobfuscator.getSourceTree("none/h$a$a"); + deobfuscator.getSourceTree("none/h$b"); + deobfuscator.getSourceTree("none/h$b$a"); + deobfuscator.getSourceTree("none/h$b$a$a"); + deobfuscator.getSourceTree("none/h$b$a$b"); + deobfuscator.getSourceTree("none/i"); + deobfuscator.getSourceTree("none/i$a"); + deobfuscator.getSourceTree("none/i$b"); + } +} diff --git a/src/test/java/cuchaz/enigma/TestDeobfuscator.java b/src/test/java/cuchaz/enigma/TestDeobfuscator.java new file mode 100644 index 0000000..1b0aa74 --- /dev/null +++ b/src/test/java/cuchaz/enigma/TestDeobfuscator.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * 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 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/test-obf/loneClass.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/src/test/java/cuchaz/enigma/TestEntryFactory.java b/src/test/java/cuchaz/enigma/TestEntryFactory.java new file mode 100644 index 0000000..4aa773b --- /dev/null +++ b/src/test/java/cuchaz/enigma/TestEntryFactory.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * 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.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; +import cuchaz.enigma.mapping.Type; + +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 Type(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 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/src/test/java/cuchaz/enigma/TestInnerClasses.java b/src/test/java/cuchaz/enigma/TestInnerClasses.java new file mode 100644 index 0000000..a4f9021 --- /dev/null +++ b/src/test/java/cuchaz/enigma/TestInnerClasses.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * 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 static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import java.util.jar.JarFile; + +import org.junit.Test; + +import static cuchaz.enigma.TestEntryFactory.*; + +import cuchaz.enigma.analysis.JarIndex; +import cuchaz.enigma.mapping.ClassEntry; + +public class TestInnerClasses { + + private JarIndex m_index; + private Deobfuscator m_deobfuscator; + + private static final ClassEntry AnonymousOuter = newClass("none/a"); + private static final ClassEntry AnonymousInner = newClass("none/a$1"); + private static final ClassEntry SimpleOuter = newClass("none/d"); + private static final ClassEntry SimpleInner = newClass("none/d$a"); + private static final ClassEntry ConstructorArgsOuter = newClass("none/c"); + private static final ClassEntry ConstructorArgsInner = newClass("none/c$a"); + private static final ClassEntry AnonymousWithScopeArgsOuter = newClass("none/b"); + private static final ClassEntry AnonymousWithScopeArgsInner = newClass("none/b$1"); + private static final ClassEntry AnonymousWithOuterAccessOuter = newClass("none/e"); + private static final ClassEntry AnonymousWithOuterAccessInner = newClass("none/e$1"); + private static final ClassEntry ClassTreeRoot = newClass("none/f"); + private static final ClassEntry ClassTreeLevel1 = newClass("none/f$a"); + private static final ClassEntry ClassTreeLevel2 = newClass("none/f$a$a"); + private static final ClassEntry ClassTreeLevel3 = newClass("none/f$a$a$a"); + + public TestInnerClasses() + throws Exception { + m_index = new JarIndex(); + JarFile jar = new JarFile("build/test-obf/innerClasses.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); + } + + @Test + public void classTree() { + + // root level + assertThat(m_index.containsObfClass(ClassTreeRoot), is(true)); + assertThat(m_index.getOuterClass(ClassTreeRoot), is(nullValue())); + assertThat(m_index.getInnerClasses(ClassTreeRoot), containsInAnyOrder(ClassTreeLevel1)); + + // level 1 + ClassEntry fullClassEntry = new ClassEntry(ClassTreeRoot.getName() + + "$" + ClassTreeLevel1.getInnermostClassName() + ); + assertThat(m_index.containsObfClass(fullClassEntry), is(true)); + assertThat(m_index.getOuterClass(ClassTreeLevel1), is(ClassTreeRoot)); + assertThat(m_index.getInnerClasses(ClassTreeLevel1), containsInAnyOrder(ClassTreeLevel2)); + + // level 2 + fullClassEntry = new ClassEntry(ClassTreeRoot.getName() + + "$" + ClassTreeLevel1.getInnermostClassName() + + "$" + ClassTreeLevel2.getInnermostClassName() + ); + assertThat(m_index.containsObfClass(fullClassEntry), is(true)); + assertThat(m_index.getOuterClass(ClassTreeLevel2), is(ClassTreeLevel1)); + assertThat(m_index.getInnerClasses(ClassTreeLevel2), containsInAnyOrder(ClassTreeLevel3)); + + // level 3 + fullClassEntry = new ClassEntry(ClassTreeRoot.getName() + + "$" + ClassTreeLevel1.getInnermostClassName() + + "$" + ClassTreeLevel2.getInnermostClassName() + + "$" + ClassTreeLevel3.getInnermostClassName() + ); + assertThat(m_index.containsObfClass(fullClassEntry), is(true)); + assertThat(m_index.getOuterClass(ClassTreeLevel3), is(ClassTreeLevel2)); + assertThat(m_index.getInnerClasses(ClassTreeLevel3), is(empty())); + } + + private void decompile(ClassEntry classEntry) { + m_deobfuscator.getSourceTree(classEntry.getName()); + } +} diff --git a/src/test/java/cuchaz/enigma/TestJarIndexConstructorReferences.java b/src/test/java/cuchaz/enigma/TestJarIndexConstructorReferences.java new file mode 100644 index 0000000..606801b --- /dev/null +++ b/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 static cuchaz.enigma.TestEntryFactory.*; +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/test-obf/constructors.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/src/test/java/cuchaz/enigma/TestJarIndexInheritanceTree.java b/src/test/java/cuchaz/enigma/TestJarIndexInheritanceTree.java new file mode 100644 index 0000000..84d2115 --- /dev/null +++ b/src/test/java/cuchaz/enigma/TestJarIndexInheritanceTree.java @@ -0,0 +1,239 @@ +/******************************************************************************* + * 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 static cuchaz.enigma.TestEntryFactory.newBehaviorReferenceByConstructor; +import static cuchaz.enigma.TestEntryFactory.newBehaviorReferenceByMethod; +import static cuchaz.enigma.TestEntryFactory.newClass; +import static cuchaz.enigma.TestEntryFactory.newConstructor; +import static cuchaz.enigma.TestEntryFactory.newField; +import static cuchaz.enigma.TestEntryFactory.newFieldReferenceByConstructor; +import static cuchaz.enigma.TestEntryFactory.newFieldReferenceByMethod; +import static cuchaz.enigma.TestEntryFactory.newMethod; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.empty; +import static org.hamcrest.Matchers.is; + +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_objectClass = newClass("java/lang/Object"); + 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 = newField(m_baseClass, "a", "Ljava/lang/String;"); + private FieldEntry m_numThingsField = newField(m_subClassB, "a", "I"); + + public TestJarIndexInheritanceTree() + throws Exception { + m_index = new JarIndex(); + m_index.indexJar(new JarFile("build/test-obf/inheritanceTree.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(m_objectClass)); + assertThat(index.getAncestry(m_baseClass), contains(m_objectClass)); + 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, m_objectClass)); + 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, m_objectClass)); + 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, m_objectClass)); + 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/src/test/java/cuchaz/enigma/TestJarIndexLoneClass.java b/src/test/java/cuchaz/enigma/TestJarIndexLoneClass.java new file mode 100644 index 0000000..bd7b03a --- /dev/null +++ b/src/test/java/cuchaz/enigma/TestJarIndexLoneClass.java @@ -0,0 +1,164 @@ +/******************************************************************************* + * 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 static cuchaz.enigma.TestEntryFactory.*; +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.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/test-obf/loneClass.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(new ClassEntry("java/lang/Object"))); + assertThat(m_index.getTranslationIndex().getSuperclass(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(new ClassEntry("java/lang/Object"))); + assertThat(m_index.getTranslationIndex().getAncestry(new ClassEntry("none/a")), contains(new ClassEntry("java/lang/Object"))); + assertThat(m_index.getTranslationIndex().getAncestry(new ClassEntry("cuchaz/enigma/inputs/Keep")), contains(new ClassEntry("java/lang/Object"))); + 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", "Ljava/lang/String;")), 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", "Ljava/lang/String;")), is(nullValue())); + assertThat(m_index.getAccess(newField("none/a", "a", "LFoo;")), 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;"); + assertThat(m_index.getMethodImplementations(new Translator(), source), is(empty())); + } + + @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", "Ljava/lang/String;"); + 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(newClass("none/a")), is(empty())); + } + + @Test + public void outerClass() { + assertThat(m_index.getOuterClass(newClass("a")), is(nullValue())); + } + + @Test + public void isAnonymousClass() { + assertThat(m_index.isAnonymousClass(newClass("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 testContains() { + 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", "Ljava/lang/String;")), is(true)); + assertThat(m_index.containsObfField(newField("none/a", "b", "Ljava/lang/String;")), is(false)); + assertThat(m_index.containsObfField(newField("none/a", "a", "LFoo;")), 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/src/test/java/cuchaz/enigma/TestSignature.java b/src/test/java/cuchaz/enigma/TestSignature.java new file mode 100644 index 0000000..8537adf --- /dev/null +++ b/src/test/java/cuchaz/enigma/TestSignature.java @@ -0,0 +1,268 @@ +/******************************************************************************* + * 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 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;"))); + } + } + + @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/src/test/java/cuchaz/enigma/TestSourceIndex.java b/src/test/java/cuchaz/enigma/TestSourceIndex.java new file mode 100644 index 0000000..58d9ca9 --- /dev/null +++ b/src/test/java/cuchaz/enigma/TestSourceIndex.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * 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 java.io.File; +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 { + @Test + public void indexEverything() + throws Exception { + // Figure out where Minecraft is... + final String mcDir = System.getProperty("enigma.test.minecraftdir"); + File mcJar = null; + if (mcDir == null) { + String osname = System.getProperty("os.name").toLowerCase(); + if (osname.contains("nix") || osname.contains("nux") || osname.contains("solaris")) { + mcJar = new File(System.getProperty("user.home"), ".minecraft/versions/1.8.3/1.8.3.jar"); + } + else if (osname.contains("mac") || osname.contains("darwin")) { + mcJar = new File(System.getProperty("user.home"), "Library/Application Support/minecraft/versions/1.8.3/1.8.3.jar"); + } + else if (osname.contains("win")) { + mcJar = new File(System.getenv("AppData"), ".minecraft/versions/1.8.3/1.8.3.jar"); + } + } + else { + mcJar = new File(mcDir, "versions/1.8.3/1.8.3.jar"); + } + + Deobfuscator deobfuscator = new Deobfuscator(new JarFile(mcJar)); + + // 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/src/test/java/cuchaz/enigma/TestTokensConstructors.java b/src/test/java/cuchaz/enigma/TestTokensConstructors.java new file mode 100644 index 0000000..66c6fd1 --- /dev/null +++ b/src/test/java/cuchaz/enigma/TestTokensConstructors.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * 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 static cuchaz.enigma.TestEntryFactory.*; +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/test-obf/constructors.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/src/test/java/cuchaz/enigma/TestTranslator.java b/src/test/java/cuchaz/enigma/TestTranslator.java new file mode 100644 index 0000000..7a430d3 --- /dev/null +++ b/src/test/java/cuchaz/enigma/TestTranslator.java @@ -0,0 +1,171 @@ +/******************************************************************************* + * 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 static cuchaz.enigma.TestEntryFactory.*; +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.BeforeClass; +import org.junit.Test; + +import cuchaz.enigma.mapping.Entry; +import cuchaz.enigma.mapping.Mappings; +import cuchaz.enigma.mapping.MappingsReader; +import cuchaz.enigma.mapping.TranslationDirection; +import cuchaz.enigma.mapping.Translator; + + +public class TestTranslator { + + private static Deobfuscator m_deobfuscator; + private static Mappings m_mappings; + private static Translator m_deobfTranslator; + private static Translator m_obfTranslator; + + @BeforeClass + public static void beforeClass() + throws Exception { + //TODO FIx +// m_deobfuscator = new Deobfuscator(new JarFile("build/test-obf/translation.jar")); +// try (InputStream in = TestTranslator.class.getResourceAsStream("/cuchaz/enigma/resources/translation.mappings")) { +// m_mappings = new MappingsReader().read(new InputStreamReader(in)); +// m_deobfuscator.setMappings(m_mappings); +// m_deobfTranslator = m_deobfuscator.getTranslator(TranslationDirection.Deobfuscating); +// m_obfTranslator = m_deobfuscator.getTranslator(TranslationDirection.Obfuscating); +// } + } + + @Test + public void basicClasses() { + assertMapping(newClass("none/a"), newClass("deobf/A_Basic")); + assertMapping(newClass("none/b"), newClass("deobf/B_BaseClass")); + assertMapping(newClass("none/c"), newClass("deobf/C_SubClass")); + } + + @Test + public void basicFields() { + assertMapping(newField("none/a", "a", "I"), newField("deobf/A_Basic", "f1", "I")); + assertMapping(newField("none/a", "a", "F"), newField("deobf/A_Basic", "f2", "F")); + assertMapping(newField("none/a", "a", "Ljava/lang/String;"), newField("deobf/A_Basic", "f3", "Ljava/lang/String;")); + } + + @Test + public void basicMethods() { + assertMapping(newMethod("none/a", "a", "()V"), newMethod("deobf/A_Basic", "m1", "()V")); + assertMapping(newMethod("none/a", "a", "()I"), newMethod("deobf/A_Basic", "m2", "()I")); + assertMapping(newMethod("none/a", "a", "(I)V"), newMethod("deobf/A_Basic", "m3", "(I)V")); + assertMapping(newMethod("none/a", "a", "(I)I"), newMethod("deobf/A_Basic", "m4", "(I)I")); + } + + // TODO: basic constructors + + @Test + public void inheritanceFields() { + assertMapping(newField("none/b", "a", "I"), newField("deobf/B_BaseClass", "f1", "I")); + assertMapping(newField("none/b", "a", "C"), newField("deobf/B_BaseClass", "f2", "C")); + assertMapping(newField("none/c", "b", "I"), newField("deobf/C_SubClass", "f3", "I")); + assertMapping(newField("none/c", "c", "I"), newField("deobf/C_SubClass", "f4", "I")); + } + + @Test + public void inheritanceFieldsShadowing() { + assertMapping(newField("none/c", "b", "C"), newField("deobf/C_SubClass", "f2", "C")); + } + + @Test + public void inheritanceFieldsBySubClass() { + assertMapping(newField("none/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("none/b", "a", "()I"), newMethod("deobf/B_BaseClass", "m1", "()I")); + assertMapping(newMethod("none/b", "b", "()I"), newMethod("deobf/B_BaseClass", "m2", "()I")); + assertMapping(newMethod("none/c", "c", "()I"), newMethod("deobf/C_SubClass", "m3", "()I")); + } + + @Test + public void inheritanceMethodsOverrides() { + assertMapping(newMethod("none/c", "a", "()I"), newMethod("deobf/C_SubClass", "m1", "()I")); + } + + @Test + public void inheritanceMethodsBySubClass() { + assertMapping(newMethod("none/c", "b", "()I"), newMethod("deobf/C_SubClass", "m2", "()I")); + } + + @Test + public void innerClasses() { + + // classes + assertMapping(newClass("none/g"), newClass("deobf/G_OuterClass")); + assertMapping(newClass("none/g$a"), newClass("deobf/G_OuterClass$A_InnerClass")); + assertMapping(newClass("none/g$a$a"), newClass("deobf/G_OuterClass$A_InnerClass$A_InnerInnerClass")); + assertMapping(newClass("none/g$b"), newClass("deobf/G_OuterClass$b")); + assertMapping(newClass("none/g$b$a"), newClass("deobf/G_OuterClass$b$A_NamedInnerClass")); + + // fields + assertMapping(newField("none/g$a", "a", "I"), newField("deobf/G_OuterClass$A_InnerClass", "f1", "I")); + assertMapping(newField("none/g$a", "a", "Ljava/lang/String;"), newField("deobf/G_OuterClass$A_InnerClass", "f2", "Ljava/lang/String;")); + assertMapping(newField("none/g$a$a", "a", "I"), newField("deobf/G_OuterClass$A_InnerClass$A_InnerInnerClass", "f3", "I")); + assertMapping(newField("none/g$b$a", "a", "I"), newField("deobf/G_OuterClass$b$A_NamedInnerClass", "f4", "I")); + + // methods + assertMapping(newMethod("none/g$a", "a", "()V"), newMethod("deobf/G_OuterClass$A_InnerClass", "m1", "()V")); + assertMapping(newMethod("none/g$a$a", "a", "()V"), newMethod("deobf/G_OuterClass$A_InnerClass$A_InnerInnerClass", "m2", "()V")); + } + + @Test + public void namelessClass() { + assertMapping(newClass("none/h"), newClass("none/h")); + } + + @Test + public void testGenerics() { + + // classes + assertMapping(newClass("none/i"), newClass("deobf/I_Generics")); + assertMapping(newClass("none/i$a"), newClass("deobf/I_Generics$A_Type")); + assertMapping(newClass("none/i$b"), newClass("deobf/I_Generics$B_Generic")); + + // fields + assertMapping(newField("none/i", "a", "Ljava/util/List;"), newField("deobf/I_Generics", "f1", "Ljava/util/List;")); + assertMapping(newField("none/i", "b", "Ljava/util/List;"), newField("deobf/I_Generics", "f2", "Ljava/util/List;")); + assertMapping(newField("none/i", "a", "Ljava/util/Map;"), newField("deobf/I_Generics", "f3", "Ljava/util/Map;")); + assertMapping(newField("none/i$b", "a", "Ljava/lang/Object;"), newField("deobf/I_Generics$B_Generic", "f4", "Ljava/lang/Object;")); + assertMapping(newField("none/i", "a", "Lnone/i$b;"), newField("deobf/I_Generics", "f5", "Ldeobf/I_Generics$B_Generic;")); + assertMapping(newField("none/i", "b", "Lnone/i$b;"), newField("deobf/I_Generics", "f6", "Ldeobf/I_Generics$B_Generic;")); + + // methods + assertMapping(newMethod("none/i$b", "a", "()Ljava/lang/Object;"), newMethod("deobf/I_Generics$B_Generic", "m1", "()Ljava/lang/Object;")); + } + + private void assertMapping(Entry obf, Entry deobf) { + assertThat(m_deobfTranslator.translateEntry(obf), is(deobf)); + assertThat(m_obfTranslator.translateEntry(deobf), is(obf)); + + String deobfName = m_deobfTranslator.translate(obf); + if (deobfName != null) { + assertThat(deobfName, is(deobf.getName())); + } + + String obfName = m_obfTranslator.translate(deobf); + if (obfName != null) { + assertThat(obfName, is(obf.getName())); + } + } +} diff --git a/src/test/java/cuchaz/enigma/TestType.java b/src/test/java/cuchaz/enigma/TestType.java new file mode 100644 index 0000000..01c235b --- /dev/null +++ b/src/test/java/cuchaz/enigma/TestType.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 static cuchaz.enigma.TestEntryFactory.*; +import static org.hamcrest.MatcherAssert.*; +import static org.hamcrest.Matchers.*; + +import org.junit.Test; + +import cuchaz.enigma.mapping.Type; + + +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("Ljava/lang/String;").getClassEntry(), is(newClass("java/lang/String"))); + } + + @Test + public void getArrayClassEntry() { + assertThat(new Type("[LFoo;").getClassEntry(), is(newClass("Foo"))); + assertThat(new Type("[[[Ljava/lang/String;").getClassEntry(), is(newClass("java/lang/String"))); + } + + @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("Ljava/lang/String;").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 = "Ljava/lang/String;"; + assertThat(Type.parseFirst("Ljava/lang/String;"), is(answer)); + assertThat(Type.parseFirst("Ljava/lang/String;I"), is(answer)); + assertThat(Type.parseFirst("Ljava/lang/String;JZ"), is(answer)); + assertThat(Type.parseFirst("Ljava/lang/String;[I"), is(answer)); + assertThat(Type.parseFirst("Ljava/lang/String;LFoo;"), is(answer)); + assertThat(Type.parseFirst("Ljava/lang/String;[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("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("[I"), is(not(new Type("[Z")))); + assertThat(new Type("[[[I"), is(not(new Type("[I")))); + assertThat(new Type("[LFoo;"), is(not(new Type("[LBar;")))); + } + + @Test + public void testToString() { + assertThat(new Type("V").toString(), is("V")); + assertThat(new Type("Z").toString(), is("Z")); + assertThat(new Type("B").toString(), is("B")); + assertThat(new Type("C").toString(), is("C")); + assertThat(new Type("I").toString(), is("I")); + assertThat(new Type("J").toString(), is("J")); + assertThat(new Type("F").toString(), is("F")); + assertThat(new Type("D").toString(), is("D")); + assertThat(new Type("LFoo;").toString(), is("LFoo;")); + assertThat(new Type("[I").toString(), is("[I")); + assertThat(new Type("[[[I").toString(), is("[[[I")); + assertThat(new Type("[LFoo;").toString(), is("[LFoo;")); + } +} diff --git a/src/test/java/cuchaz/enigma/TokenChecker.java b/src/test/java/cuchaz/enigma/TokenChecker.java new file mode 100644 index 0000000..7afb4cf --- /dev/null +++ b/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 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/src/test/java/cuchaz/enigma/inputs/Keep.java b/src/test/java/cuchaz/enigma/inputs/Keep.java new file mode 100644 index 0000000..f04875f --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/Keep.java @@ -0,0 +1,17 @@ +/******************************************************************************* + * 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/src/test/java/cuchaz/enigma/inputs/constructors/BaseClass.java b/src/test/java/cuchaz/enigma/inputs/constructors/BaseClass.java new file mode 100644 index 0000000..65e782a --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/constructors/BaseClass.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.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/src/test/java/cuchaz/enigma/inputs/constructors/Caller.java b/src/test/java/cuchaz/enigma/inputs/constructors/Caller.java new file mode 100644 index 0000000..75096ec --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/constructors/Caller.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * 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; + +// 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/src/test/java/cuchaz/enigma/inputs/constructors/DefaultConstructable.java b/src/test/java/cuchaz/enigma/inputs/constructors/DefaultConstructable.java new file mode 100644 index 0000000..655f4da --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/constructors/DefaultConstructable.java @@ -0,0 +1,15 @@ +/******************************************************************************* + * 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/src/test/java/cuchaz/enigma/inputs/constructors/SubClass.java b/src/test/java/cuchaz/enigma/inputs/constructors/SubClass.java new file mode 100644 index 0000000..b0fb3e9 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/constructors/SubClass.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * 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; + +// 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/src/test/java/cuchaz/enigma/inputs/constructors/SubSubClass.java b/src/test/java/cuchaz/enigma/inputs/constructors/SubSubClass.java new file mode 100644 index 0000000..5031405 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/constructors/SubSubClass.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * 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; + +// 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/src/test/java/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java b/src/test/java/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java new file mode 100644 index 0000000..4f9c5b0 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/inheritanceTree/BaseClass.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.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/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java b/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java new file mode 100644 index 0000000..140d2a8 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * 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; + +// 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/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java b/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java new file mode 100644 index 0000000..99d149b --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubclassB.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.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/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java b/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java new file mode 100644 index 0000000..2e414b7 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * 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; + +// 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/src/test/java/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java b/src/test/java/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java new file mode 100644 index 0000000..f644439 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/innerClasses/A_Anonymous.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 A_Anonymous { + + public void foo() { + Runnable runnable = new Runnable() { + @Override + public void run() { + // don't care + } + }; + runnable.run(); + } +} diff --git a/src/test/java/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java b/src/test/java/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java new file mode 100644 index 0000000..d78be84 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * 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/src/test/java/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java b/src/test/java/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java new file mode 100644 index 0000000..eb03489 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.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; + +@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/src/test/java/cuchaz/enigma/inputs/innerClasses/D_Simple.java b/src/test/java/cuchaz/enigma/inputs/innerClasses/D_Simple.java new file mode 100644 index 0000000..0e9bf82 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/innerClasses/D_Simple.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.innerClasses; + +public class D_Simple { + + class Inner { + // nothing to do + } +} diff --git a/src/test/java/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java b/src/test/java/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java new file mode 100644 index 0000000..255434d --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.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; + +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/src/test/java/cuchaz/enigma/inputs/innerClasses/F_ClassTree.java b/src/test/java/cuchaz/enigma/inputs/innerClasses/F_ClassTree.java new file mode 100644 index 0000000..7d1dab4 --- /dev/null +++ b/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/src/test/java/cuchaz/enigma/inputs/loneClass/LoneClass.java b/src/test/java/cuchaz/enigma/inputs/loneClass/LoneClass.java new file mode 100644 index 0000000..bf264fa --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/loneClass/LoneClass.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.loneClass; + +public class LoneClass { + + private String m_name; + + public LoneClass(String name) { + m_name = name; + } + + public String getName() { + return m_name; + } +} diff --git a/src/test/java/cuchaz/enigma/inputs/translation/A_Basic.java b/src/test/java/cuchaz/enigma/inputs/translation/A_Basic.java new file mode 100644 index 0000000..26acac8 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/translation/A_Basic.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; + +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/src/test/java/cuchaz/enigma/inputs/translation/B_BaseClass.java b/src/test/java/cuchaz/enigma/inputs/translation/B_BaseClass.java new file mode 100644 index 0000000..035e329 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/translation/B_BaseClass.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.translation; + +public class B_BaseClass { + + public int f1; + public char f2; + + public int m1() { + return 5; + } + + public int m2() { + return 42; + } +} diff --git a/src/test/java/cuchaz/enigma/inputs/translation/C_SubClass.java b/src/test/java/cuchaz/enigma/inputs/translation/C_SubClass.java new file mode 100644 index 0000000..6026a8d --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/translation/C_SubClass.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * 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/src/test/java/cuchaz/enigma/inputs/translation/D_AnonymousTesting.java b/src/test/java/cuchaz/enigma/inputs/translation/D_AnonymousTesting.java new file mode 100644 index 0000000..a1827f9 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/translation/D_AnonymousTesting.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; + +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/src/test/java/cuchaz/enigma/inputs/translation/E_Bridges.java b/src/test/java/cuchaz/enigma/inputs/translation/E_Bridges.java new file mode 100644 index 0000000..769eb70 --- /dev/null +++ b/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/src/test/java/cuchaz/enigma/inputs/translation/F_ObjectMethods.java b/src/test/java/cuchaz/enigma/inputs/translation/F_ObjectMethods.java new file mode 100644 index 0000000..32c246c --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/translation/F_ObjectMethods.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; + +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/src/test/java/cuchaz/enigma/inputs/translation/G_OuterClass.java b/src/test/java/cuchaz/enigma/inputs/translation/G_OuterClass.java new file mode 100644 index 0000000..a2e0daf --- /dev/null +++ b/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/src/test/java/cuchaz/enigma/inputs/translation/H_NamelessClass.java b/src/test/java/cuchaz/enigma/inputs/translation/H_NamelessClass.java new file mode 100644 index 0000000..1b718a5 --- /dev/null +++ b/src/test/java/cuchaz/enigma/inputs/translation/H_NamelessClass.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * 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/src/test/java/cuchaz/enigma/inputs/translation/I_Generics.java b/src/test/java/cuchaz/enigma/inputs/translation/I_Generics.java new file mode 100644 index 0000000..3490f9d --- /dev/null +++ b/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 class A_Type { + } + + public List f1; + public List f2; + public Map f3; + + public class B_Generic { + public T f4; + public T m1() { + return null; + } + } + + public B_Generic f5; + public B_Generic f6; +} diff --git a/src/test/java/cuchaz/enigma/resources/translation.mappings b/src/test/java/cuchaz/enigma/resources/translation.mappings new file mode 100644 index 0000000..db78c19 --- /dev/null +++ b/src/test/java/cuchaz/enigma/resources/translation.mappings @@ -0,0 +1,41 @@ +CLASS none/a deobf/A_Basic + FIELD a f1 I + FIELD a f2 F + FIELD a f3 Ljava/lang/String; + METHOD a m1 ()V + METHOD a m2 ()I + METHOD a m3 (I)V + METHOD a m4 (I)I +CLASS none/b deobf/B_BaseClass + FIELD a f1 I + FIELD a f2 C + METHOD a m1 ()I + METHOD b m2 ()I +CLASS none/c deobf/C_SubClass + FIELD b f2 C + FIELD b f3 I + FIELD c f4 I + METHOD a m1 ()I + METHOD c m3 ()I +CLASS none/g deobf/G_OuterClass + CLASS none/g$a A_InnerClass + CLASS none/g$a$a A_InnerInnerClass + FIELD a f3 I + METHOD a m2 ()V + FIELD a f1 I + FIELD a f2 Ljava/lang/String; + METHOD a m1 ()V + CLASS none/g$b + CLASS none/g$b$a A_NamedInnerClass + FIELD a f4 I +CLASS none/h +CLASS none/i deobf/I_Generics + CLASS none/i$a A_Type + CLASS none/i$b B_Generic + FIELD a f4 Ljava/lang/Object; + METHOD a m1 ()Ljava/lang/Object; + FIELD a f1 Ljava/util/List; + FIELD b f2 Ljava/util/List; + FIELD a f3 Ljava/util/Map; + FIELD a f5 Lnone/i$b; + FIELD b f6 Lnone/i$b; -- cgit v1.2.3