diff options
Diffstat (limited to 'test')
25 files changed, 1255 insertions, 0 deletions
diff --git a/test/cuchaz/enigma/EntryFactory.java b/test/cuchaz/enigma/EntryFactory.java new file mode 100644 index 00000000..d9317ef3 --- /dev/null +++ b/test/cuchaz/enigma/EntryFactory.java | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin.\ | ||
| 3 | * | ||
| 4 | * All rights reserved. This program and the accompanying materials | ||
| 5 | * are made available under the terms of the GNU Public License v3.0 | ||
| 6 | * which accompanies this distribution, and is available at | ||
| 7 | * http://www.gnu.org/licenses/gpl.html | ||
| 8 | * | ||
| 9 | * Contributors: | ||
| 10 | * Jeff Martin - initial API and implementation | ||
| 11 | ******************************************************************************/ | ||
| 12 | package cuchaz.enigma; | ||
| 13 | |||
| 14 | import cuchaz.enigma.analysis.EntryReference; | ||
| 15 | import cuchaz.enigma.mapping.BehaviorEntry; | ||
| 16 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 17 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 18 | import cuchaz.enigma.mapping.FieldEntry; | ||
| 19 | import cuchaz.enigma.mapping.MethodEntry; | ||
| 20 | |||
| 21 | public class EntryFactory { | ||
| 22 | |||
| 23 | public static ClassEntry newClass(String name) { | ||
| 24 | return new ClassEntry(name); | ||
| 25 | } | ||
| 26 | |||
| 27 | public static FieldEntry newField(String className, String fieldName) { | ||
| 28 | return new FieldEntry(newClass(className), fieldName); | ||
| 29 | } | ||
| 30 | |||
| 31 | public static MethodEntry newMethod(String className, String methodName, String methodSignature) { | ||
| 32 | return new MethodEntry(newClass(className), methodName, methodSignature); | ||
| 33 | } | ||
| 34 | |||
| 35 | public static ConstructorEntry newConstructor(String className, String signature) { | ||
| 36 | return new ConstructorEntry(newClass(className), signature); | ||
| 37 | } | ||
| 38 | |||
| 39 | public static EntryReference<FieldEntry,BehaviorEntry> newFieldReferenceByMethod(FieldEntry fieldEntry, String callerClassName, String callerName, String callerSignature) { | ||
| 40 | return new EntryReference<FieldEntry,BehaviorEntry>(fieldEntry, "", newMethod(callerClassName, callerName, callerSignature)); | ||
| 41 | } | ||
| 42 | |||
| 43 | public static EntryReference<FieldEntry,BehaviorEntry> newFieldReferenceByConstructor(FieldEntry fieldEntry, String callerClassName, String callerSignature) { | ||
| 44 | return new EntryReference<FieldEntry,BehaviorEntry>(fieldEntry, "", newConstructor(callerClassName, callerSignature)); | ||
| 45 | } | ||
| 46 | |||
| 47 | public static EntryReference<BehaviorEntry,BehaviorEntry> newBehaviorReferenceByMethod(BehaviorEntry behaviorEntry, String callerClassName, String callerName, String callerSignature) { | ||
| 48 | return new EntryReference<BehaviorEntry,BehaviorEntry>(behaviorEntry, "", newMethod(callerClassName, callerName, callerSignature)); | ||
| 49 | } | ||
| 50 | |||
| 51 | public static EntryReference<BehaviorEntry,BehaviorEntry> newBehaviorReferenceByConstructor(BehaviorEntry behaviorEntry, String callerClassName, String callerSignature) { | ||
| 52 | return new EntryReference<BehaviorEntry,BehaviorEntry>(behaviorEntry, "", newConstructor(callerClassName, callerSignature)); | ||
| 53 | } | ||
| 54 | } | ||
diff --git a/test/cuchaz/enigma/TestDeobfuscator.java b/test/cuchaz/enigma/TestDeobfuscator.java new file mode 100644 index 00000000..129d7b25 --- /dev/null +++ b/test/cuchaz/enigma/TestDeobfuscator.java | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin.\ | ||
| 3 | * | ||
| 4 | * All rights reserved. This program and the accompanying materials | ||
| 5 | * are made available under the terms of the GNU Public License v3.0 | ||
| 6 | * which accompanies this distribution, and is available at | ||
| 7 | * http://www.gnu.org/licenses/gpl.html | ||
| 8 | * | ||
| 9 | * Contributors: | ||
| 10 | * Jeff Martin - initial API and implementation | ||
| 11 | ******************************************************************************/ | ||
| 12 | package cuchaz.enigma; | ||
| 13 | |||
| 14 | import static org.junit.Assert.*; | ||
| 15 | |||
| 16 | import java.io.IOException; | ||
| 17 | import java.util.List; | ||
| 18 | import java.util.jar.JarFile; | ||
| 19 | |||
| 20 | import org.junit.Test; | ||
| 21 | |||
| 22 | import com.google.common.collect.Lists; | ||
| 23 | |||
| 24 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 25 | |||
| 26 | public class TestDeobfuscator { | ||
| 27 | |||
| 28 | private Deobfuscator getDeobfuscator() throws IOException { | ||
| 29 | return new Deobfuscator(new JarFile("build/testLoneClass.obf.jar")); | ||
| 30 | } | ||
| 31 | |||
| 32 | @Test | ||
| 33 | public void loadJar() throws Exception { | ||
| 34 | getDeobfuscator(); | ||
| 35 | } | ||
| 36 | |||
| 37 | @Test | ||
| 38 | public void getClasses() throws Exception { | ||
| 39 | Deobfuscator deobfuscator = getDeobfuscator(); | ||
| 40 | List<ClassEntry> obfClasses = Lists.newArrayList(); | ||
| 41 | List<ClassEntry> deobfClasses = Lists.newArrayList(); | ||
| 42 | deobfuscator.getSeparatedClasses(obfClasses, deobfClasses); | ||
| 43 | assertEquals(1, obfClasses.size()); | ||
| 44 | assertEquals("none/a", obfClasses.get(0).getName()); | ||
| 45 | assertEquals(1, deobfClasses.size()); | ||
| 46 | assertEquals("cuchaz/enigma/inputs/Keep", deobfClasses.get(0).getName()); | ||
| 47 | } | ||
| 48 | |||
| 49 | @Test | ||
| 50 | public void decompileClass() throws Exception { | ||
| 51 | Deobfuscator deobfuscator = getDeobfuscator(); | ||
| 52 | deobfuscator.getSource(deobfuscator.getSourceTree("none/a")); | ||
| 53 | } | ||
| 54 | } | ||
diff --git a/test/cuchaz/enigma/TestInnerClasses.java b/test/cuchaz/enigma/TestInnerClasses.java new file mode 100644 index 00000000..63c9b719 --- /dev/null +++ b/test/cuchaz/enigma/TestInnerClasses.java | |||
| @@ -0,0 +1,89 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * | ||
| 4 | * All rights reserved. This program and the accompanying materials | ||
| 5 | * are made available under the terms of the GNU Public License v3.0 | ||
| 6 | * which accompanies this distribution, and is available at | ||
| 7 | * http://www.gnu.org/licenses/gpl.html | ||
| 8 | * | ||
| 9 | * Contributors: | ||
| 10 | * Jeff Martin - initial API and implementation | ||
| 11 | ******************************************************************************/ | ||
| 12 | package cuchaz.enigma; | ||
| 13 | |||
| 14 | import static org.hamcrest.MatcherAssert.*; | ||
| 15 | import static org.hamcrest.Matchers.*; | ||
| 16 | |||
| 17 | import java.util.jar.JarFile; | ||
| 18 | |||
| 19 | import org.junit.Test; | ||
| 20 | |||
| 21 | import cuchaz.enigma.analysis.JarIndex; | ||
| 22 | |||
| 23 | public class TestInnerClasses { | ||
| 24 | |||
| 25 | private JarIndex m_index; | ||
| 26 | private Deobfuscator m_deobfuscator; | ||
| 27 | |||
| 28 | private static final String AnonymousOuter = "none/a"; | ||
| 29 | private static final String AnonymousInner = "b"; | ||
| 30 | private static final String SimpleOuter = "none/g"; | ||
| 31 | private static final String SimpleInner = "h"; | ||
| 32 | private static final String ConstructorArgsOuter = "none/e"; | ||
| 33 | private static final String ConstructorArgsInner = "f"; | ||
| 34 | private static final String AnonymousWithScopeArgsOuter = "none/c"; | ||
| 35 | private static final String AnonymousWithScopeArgsInner = "d"; | ||
| 36 | private static final String AnonymousWithOuterAccessOuter = "none/i"; | ||
| 37 | private static final String AnonymousWithOuterAccessInner = "j"; | ||
| 38 | |||
| 39 | public TestInnerClasses() throws Exception { | ||
| 40 | m_index = new JarIndex(); | ||
| 41 | JarFile jar = new JarFile("build/testInnerClasses.obf.jar"); | ||
| 42 | m_index.indexJar(jar, true); | ||
| 43 | m_deobfuscator = new Deobfuscator(jar); | ||
| 44 | } | ||
| 45 | |||
| 46 | @Test | ||
| 47 | public void simple() { | ||
| 48 | assertThat(m_index.getOuterClass(SimpleInner), is(SimpleOuter)); | ||
| 49 | assertThat(m_index.getInnerClasses(SimpleOuter), containsInAnyOrder(SimpleInner)); | ||
| 50 | assertThat(m_index.isAnonymousClass(SimpleInner), is(false)); | ||
| 51 | decompile(SimpleOuter); | ||
| 52 | } | ||
| 53 | |||
| 54 | @Test | ||
| 55 | public void anonymous() { | ||
| 56 | assertThat(m_index.getOuterClass(AnonymousInner), is(AnonymousOuter)); | ||
| 57 | assertThat(m_index.getInnerClasses(AnonymousOuter), containsInAnyOrder(AnonymousInner)); | ||
| 58 | assertThat(m_index.isAnonymousClass(AnonymousInner), is(true)); | ||
| 59 | decompile(AnonymousOuter); | ||
| 60 | } | ||
| 61 | |||
| 62 | @Test | ||
| 63 | public void constructorArgs() { | ||
| 64 | assertThat(m_index.getOuterClass(ConstructorArgsInner), is(ConstructorArgsOuter)); | ||
| 65 | assertThat(m_index.getInnerClasses(ConstructorArgsOuter), containsInAnyOrder(ConstructorArgsInner)); | ||
| 66 | assertThat(m_index.isAnonymousClass(ConstructorArgsInner), is(false)); | ||
| 67 | decompile(ConstructorArgsOuter); | ||
| 68 | } | ||
| 69 | |||
| 70 | @Test | ||
| 71 | public void anonymousWithScopeArgs() { | ||
| 72 | assertThat(m_index.getOuterClass(AnonymousWithScopeArgsInner), is(AnonymousWithScopeArgsOuter)); | ||
| 73 | assertThat(m_index.getInnerClasses(AnonymousWithScopeArgsOuter), containsInAnyOrder(AnonymousWithScopeArgsInner)); | ||
| 74 | assertThat(m_index.isAnonymousClass(AnonymousWithScopeArgsInner), is(true)); | ||
| 75 | decompile(AnonymousWithScopeArgsOuter); | ||
| 76 | } | ||
| 77 | |||
| 78 | @Test | ||
| 79 | public void anonymousWithOuterAccess() { | ||
| 80 | assertThat(m_index.getOuterClass(AnonymousWithOuterAccessInner), is(AnonymousWithOuterAccessOuter)); | ||
| 81 | assertThat(m_index.getInnerClasses(AnonymousWithOuterAccessOuter), containsInAnyOrder(AnonymousWithOuterAccessInner)); | ||
| 82 | assertThat(m_index.isAnonymousClass(AnonymousWithOuterAccessInner), is(true)); | ||
| 83 | decompile(AnonymousWithOuterAccessOuter); | ||
| 84 | } | ||
| 85 | |||
| 86 | private void decompile(String name) { | ||
| 87 | m_deobfuscator.getSourceTree(name); | ||
| 88 | } | ||
| 89 | } | ||
diff --git a/test/cuchaz/enigma/TestJarIndexConstructorReferences.java b/test/cuchaz/enigma/TestJarIndexConstructorReferences.java new file mode 100644 index 00000000..8e3ad6d2 --- /dev/null +++ b/test/cuchaz/enigma/TestJarIndexConstructorReferences.java | |||
| @@ -0,0 +1,124 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma; | ||
| 12 | |||
| 13 | import static cuchaz.enigma.EntryFactory.*; | ||
| 14 | import static org.hamcrest.MatcherAssert.*; | ||
| 15 | import static org.hamcrest.Matchers.*; | ||
| 16 | |||
| 17 | import java.io.File; | ||
| 18 | import java.util.Collection; | ||
| 19 | import java.util.jar.JarFile; | ||
| 20 | |||
| 21 | import org.junit.Test; | ||
| 22 | |||
| 23 | import cuchaz.enigma.analysis.EntryReference; | ||
| 24 | import cuchaz.enigma.analysis.JarIndex; | ||
| 25 | import cuchaz.enigma.mapping.BehaviorEntry; | ||
| 26 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 27 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 28 | |||
| 29 | public class TestJarIndexConstructorReferences { | ||
| 30 | |||
| 31 | private JarIndex m_index; | ||
| 32 | |||
| 33 | private ClassEntry m_baseClass = new ClassEntry("none/a"); | ||
| 34 | private ClassEntry m_subClass = new ClassEntry("none/d"); | ||
| 35 | private ClassEntry m_subsubClass = new ClassEntry("none/e"); | ||
| 36 | private ClassEntry m_defaultClass = new ClassEntry("none/c"); | ||
| 37 | private ClassEntry m_callerClass = new ClassEntry("none/b"); | ||
| 38 | |||
| 39 | public TestJarIndexConstructorReferences() throws Exception { | ||
| 40 | File jarFile = new File("build/testConstructors.obf.jar"); | ||
| 41 | m_index = new JarIndex(); | ||
| 42 | m_index.indexJar(new JarFile(jarFile), false); | ||
| 43 | } | ||
| 44 | |||
| 45 | @Test | ||
| 46 | public void obfEntries() { | ||
| 47 | assertThat(m_index.getObfClassEntries(), containsInAnyOrder(newClass("cuchaz/enigma/inputs/Keep"), m_baseClass, m_subClass, m_subsubClass, m_defaultClass, m_callerClass)); | ||
| 48 | } | ||
| 49 | |||
| 50 | @Test | ||
| 51 | @SuppressWarnings("unchecked") | ||
| 52 | public void baseDefault() { | ||
| 53 | BehaviorEntry source = new ConstructorEntry(m_baseClass, "()V"); | ||
| 54 | Collection<EntryReference<BehaviorEntry,BehaviorEntry>> references = m_index.getBehaviorReferences(source); | ||
| 55 | assertThat(references, containsInAnyOrder( | ||
| 56 | newBehaviorReferenceByMethod(source, m_callerClass.getName(), "a", "()V"), | ||
| 57 | newBehaviorReferenceByConstructor(source, m_subClass.getName(), "()V"), | ||
| 58 | newBehaviorReferenceByConstructor(source, m_subClass.getName(), "(III)V") | ||
| 59 | )); | ||
| 60 | } | ||
| 61 | |||
| 62 | @Test | ||
| 63 | @SuppressWarnings("unchecked") | ||
| 64 | public void baseInt() { | ||
| 65 | BehaviorEntry source = new ConstructorEntry(m_baseClass, "(I)V"); | ||
| 66 | assertThat(m_index.getBehaviorReferences(source), containsInAnyOrder( | ||
| 67 | newBehaviorReferenceByMethod(source, m_callerClass.getName(), "b", "()V") | ||
| 68 | )); | ||
| 69 | } | ||
| 70 | |||
| 71 | @Test | ||
| 72 | @SuppressWarnings("unchecked") | ||
| 73 | public void subDefault() { | ||
| 74 | BehaviorEntry source = new ConstructorEntry(m_subClass, "()V"); | ||
| 75 | assertThat(m_index.getBehaviorReferences(source), containsInAnyOrder( | ||
| 76 | newBehaviorReferenceByMethod(source, m_callerClass.getName(), "c", "()V"), | ||
| 77 | newBehaviorReferenceByConstructor(source, m_subClass.getName(), "(I)V") | ||
| 78 | )); | ||
| 79 | } | ||
| 80 | |||
| 81 | @Test | ||
| 82 | @SuppressWarnings("unchecked") | ||
| 83 | public void subInt() { | ||
| 84 | BehaviorEntry source = new ConstructorEntry(m_subClass, "(I)V"); | ||
| 85 | assertThat(m_index.getBehaviorReferences(source), containsInAnyOrder( | ||
| 86 | newBehaviorReferenceByMethod(source, m_callerClass.getName(), "d", "()V"), | ||
| 87 | newBehaviorReferenceByConstructor(source, m_subClass.getName(), "(II)V"), | ||
| 88 | newBehaviorReferenceByConstructor(source, m_subsubClass.getName(), "(I)V") | ||
| 89 | )); | ||
| 90 | } | ||
| 91 | |||
| 92 | @Test | ||
| 93 | @SuppressWarnings("unchecked") | ||
| 94 | public void subIntInt() { | ||
| 95 | BehaviorEntry source = new ConstructorEntry(m_subClass, "(II)V"); | ||
| 96 | assertThat(m_index.getBehaviorReferences(source), containsInAnyOrder( | ||
| 97 | newBehaviorReferenceByMethod(source, m_callerClass.getName(), "e", "()V") | ||
| 98 | )); | ||
| 99 | } | ||
| 100 | |||
| 101 | @Test | ||
| 102 | public void subIntIntInt() { | ||
| 103 | BehaviorEntry source = new ConstructorEntry(m_subClass, "(III)V"); | ||
| 104 | assertThat(m_index.getBehaviorReferences(source), is(empty())); | ||
| 105 | } | ||
| 106 | |||
| 107 | @Test | ||
| 108 | @SuppressWarnings("unchecked") | ||
| 109 | public void subsubInt() { | ||
| 110 | BehaviorEntry source = new ConstructorEntry(m_subsubClass, "(I)V"); | ||
| 111 | assertThat(m_index.getBehaviorReferences(source), containsInAnyOrder( | ||
| 112 | newBehaviorReferenceByMethod(source, m_callerClass.getName(), "f", "()V") | ||
| 113 | )); | ||
| 114 | } | ||
| 115 | |||
| 116 | @Test | ||
| 117 | @SuppressWarnings("unchecked") | ||
| 118 | public void defaultConstructable() { | ||
| 119 | BehaviorEntry source = new ConstructorEntry(m_defaultClass, "()V"); | ||
| 120 | assertThat(m_index.getBehaviorReferences(source), containsInAnyOrder( | ||
| 121 | newBehaviorReferenceByMethod(source, m_callerClass.getName(), "g", "()V") | ||
| 122 | )); | ||
| 123 | } | ||
| 124 | } | ||
diff --git a/test/cuchaz/enigma/TestJarIndexInheritanceTree.java b/test/cuchaz/enigma/TestJarIndexInheritanceTree.java new file mode 100644 index 00000000..4d663972 --- /dev/null +++ b/test/cuchaz/enigma/TestJarIndexInheritanceTree.java | |||
| @@ -0,0 +1,228 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma; | ||
| 12 | |||
| 13 | import static cuchaz.enigma.EntryFactory.*; | ||
| 14 | import static org.hamcrest.MatcherAssert.*; | ||
| 15 | import static org.hamcrest.Matchers.*; | ||
| 16 | |||
| 17 | import java.util.Collection; | ||
| 18 | import java.util.Set; | ||
| 19 | import java.util.jar.JarFile; | ||
| 20 | |||
| 21 | import org.junit.Test; | ||
| 22 | |||
| 23 | import cuchaz.enigma.analysis.Access; | ||
| 24 | import cuchaz.enigma.analysis.EntryReference; | ||
| 25 | import cuchaz.enigma.analysis.JarIndex; | ||
| 26 | import cuchaz.enigma.analysis.TranslationIndex; | ||
| 27 | import cuchaz.enigma.mapping.BehaviorEntry; | ||
| 28 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 29 | import cuchaz.enigma.mapping.ConstructorEntry; | ||
| 30 | import cuchaz.enigma.mapping.FieldEntry; | ||
| 31 | import cuchaz.enigma.mapping.MethodEntry; | ||
| 32 | |||
| 33 | public class TestJarIndexInheritanceTree { | ||
| 34 | |||
| 35 | private JarIndex m_index; | ||
| 36 | |||
| 37 | private ClassEntry m_baseClass = new ClassEntry("none/a"); | ||
| 38 | private ClassEntry m_subClassA = new ClassEntry("none/b"); | ||
| 39 | private ClassEntry m_subClassAA = new ClassEntry("none/d"); | ||
| 40 | private ClassEntry m_subClassB = new ClassEntry("none/c"); | ||
| 41 | private FieldEntry m_nameField = new FieldEntry(m_baseClass, "a"); | ||
| 42 | private FieldEntry m_numThingsField = new FieldEntry(m_subClassB, "a"); | ||
| 43 | |||
| 44 | public TestJarIndexInheritanceTree() throws Exception { | ||
| 45 | m_index = new JarIndex(); | ||
| 46 | m_index.indexJar(new JarFile("build/testInheritanceTree.obf.jar"), false); | ||
| 47 | } | ||
| 48 | |||
| 49 | @Test | ||
| 50 | public void obfEntries() { | ||
| 51 | assertThat(m_index.getObfClassEntries(), containsInAnyOrder( | ||
| 52 | newClass("cuchaz/enigma/inputs/Keep"), | ||
| 53 | m_baseClass, | ||
| 54 | m_subClassA, | ||
| 55 | m_subClassAA, | ||
| 56 | m_subClassB | ||
| 57 | )); | ||
| 58 | } | ||
| 59 | |||
| 60 | @Test | ||
| 61 | public void translationIndex() { | ||
| 62 | |||
| 63 | TranslationIndex index = m_index.getTranslationIndex(); | ||
| 64 | |||
| 65 | // base class | ||
| 66 | assertThat(index.getSuperclass(m_baseClass), is(nullValue())); | ||
| 67 | assertThat(index.getAncestry(m_baseClass), is(empty())); | ||
| 68 | assertThat(index.getSubclass(m_baseClass), containsInAnyOrder( | ||
| 69 | m_subClassA, | ||
| 70 | m_subClassB | ||
| 71 | )); | ||
| 72 | |||
| 73 | // subclass a | ||
| 74 | assertThat(index.getSuperclass(m_subClassA), is(m_baseClass)); | ||
| 75 | assertThat(index.getAncestry(m_subClassA), contains(m_baseClass)); | ||
| 76 | assertThat(index.getSubclass(m_subClassA), contains(m_subClassAA)); | ||
| 77 | |||
| 78 | // subclass aa | ||
| 79 | assertThat(index.getSuperclass(m_subClassAA), is(m_subClassA)); | ||
| 80 | assertThat(index.getAncestry(m_subClassAA), contains(m_subClassA, m_baseClass)); | ||
| 81 | assertThat(index.getSubclass(m_subClassAA), is(empty())); | ||
| 82 | |||
| 83 | // subclass b | ||
| 84 | assertThat(index.getSuperclass(m_subClassB), is(m_baseClass)); | ||
| 85 | assertThat(index.getAncestry(m_subClassB), contains(m_baseClass)); | ||
| 86 | assertThat(index.getSubclass(m_subClassB), is(empty())); | ||
| 87 | } | ||
| 88 | |||
| 89 | @Test | ||
| 90 | public void access() { | ||
| 91 | assertThat(m_index.getAccess(m_nameField), is(Access.Private)); | ||
| 92 | assertThat(m_index.getAccess(m_numThingsField), is(Access.Private)); | ||
| 93 | } | ||
| 94 | |||
| 95 | @Test | ||
| 96 | public void relatedMethodImplementations() { | ||
| 97 | |||
| 98 | Set<MethodEntry> entries; | ||
| 99 | |||
| 100 | // getName() | ||
| 101 | entries = m_index.getRelatedMethodImplementations(new MethodEntry(m_baseClass, "a", "()Ljava/lang/String;")); | ||
| 102 | assertThat(entries, containsInAnyOrder( | ||
| 103 | new MethodEntry(m_baseClass, "a", "()Ljava/lang/String;"), | ||
| 104 | new MethodEntry(m_subClassAA, "a", "()Ljava/lang/String;") | ||
| 105 | )); | ||
| 106 | entries = m_index.getRelatedMethodImplementations(new MethodEntry(m_subClassAA, "a", "()Ljava/lang/String;")); | ||
| 107 | assertThat(entries, containsInAnyOrder( | ||
| 108 | new MethodEntry(m_baseClass, "a", "()Ljava/lang/String;"), | ||
| 109 | new MethodEntry(m_subClassAA, "a", "()Ljava/lang/String;") | ||
| 110 | )); | ||
| 111 | |||
| 112 | // doBaseThings() | ||
| 113 | entries = m_index.getRelatedMethodImplementations(new MethodEntry(m_baseClass, "a", "()V")); | ||
| 114 | assertThat(entries, containsInAnyOrder( | ||
| 115 | new MethodEntry(m_baseClass, "a", "()V"), | ||
| 116 | new MethodEntry(m_subClassAA, "a", "()V"), | ||
| 117 | new MethodEntry(m_subClassB, "a", "()V") | ||
| 118 | )); | ||
| 119 | entries = m_index.getRelatedMethodImplementations(new MethodEntry(m_subClassAA, "a", "()V")); | ||
| 120 | assertThat(entries, containsInAnyOrder( | ||
| 121 | new MethodEntry(m_baseClass, "a", "()V"), | ||
| 122 | new MethodEntry(m_subClassAA, "a", "()V"), | ||
| 123 | new MethodEntry(m_subClassB, "a", "()V") | ||
| 124 | )); | ||
| 125 | entries = m_index.getRelatedMethodImplementations(new MethodEntry(m_subClassB, "a", "()V")); | ||
| 126 | assertThat(entries, containsInAnyOrder( | ||
| 127 | new MethodEntry(m_baseClass, "a", "()V"), | ||
| 128 | new MethodEntry(m_subClassAA, "a", "()V"), | ||
| 129 | new MethodEntry(m_subClassB, "a", "()V") | ||
| 130 | )); | ||
| 131 | |||
| 132 | // doBThings | ||
| 133 | entries = m_index.getRelatedMethodImplementations(new MethodEntry(m_subClassB, "b", "()V")); | ||
| 134 | assertThat(entries, containsInAnyOrder(new MethodEntry(m_subClassB, "b", "()V"))); | ||
| 135 | } | ||
| 136 | |||
| 137 | @Test | ||
| 138 | @SuppressWarnings("unchecked") | ||
| 139 | public void fieldReferences() { | ||
| 140 | Collection<EntryReference<FieldEntry,BehaviorEntry>> references; | ||
| 141 | |||
| 142 | // name | ||
| 143 | references = m_index.getFieldReferences(m_nameField); | ||
| 144 | assertThat(references, containsInAnyOrder( | ||
| 145 | newFieldReferenceByConstructor(m_nameField, m_baseClass.getName(), "(Ljava/lang/String;)V"), | ||
| 146 | newFieldReferenceByMethod(m_nameField, m_baseClass.getName(), "a", "()Ljava/lang/String;") | ||
| 147 | )); | ||
| 148 | |||
| 149 | // numThings | ||
| 150 | references = m_index.getFieldReferences(m_numThingsField); | ||
| 151 | assertThat(references, containsInAnyOrder( | ||
| 152 | newFieldReferenceByConstructor(m_numThingsField, m_subClassB.getName(), "()V"), | ||
| 153 | newFieldReferenceByMethod(m_numThingsField, m_subClassB.getName(), "b", "()V") | ||
| 154 | )); | ||
| 155 | } | ||
| 156 | |||
| 157 | @Test | ||
| 158 | @SuppressWarnings("unchecked") | ||
| 159 | public void behaviorReferences() { | ||
| 160 | |||
| 161 | BehaviorEntry source; | ||
| 162 | Collection<EntryReference<BehaviorEntry,BehaviorEntry>> references; | ||
| 163 | |||
| 164 | // baseClass constructor | ||
| 165 | source = new ConstructorEntry(m_baseClass, "(Ljava/lang/String;)V"); | ||
| 166 | references = m_index.getBehaviorReferences(source); | ||
| 167 | assertThat(references, containsInAnyOrder( | ||
| 168 | newBehaviorReferenceByConstructor(source, m_subClassA.getName(), "(Ljava/lang/String;)V"), | ||
| 169 | newBehaviorReferenceByConstructor(source, m_subClassB.getName(), "()V") | ||
| 170 | )); | ||
| 171 | |||
| 172 | // subClassA constructor | ||
| 173 | source = new ConstructorEntry(m_subClassA, "(Ljava/lang/String;)V"); | ||
| 174 | references = m_index.getBehaviorReferences(source); | ||
| 175 | assertThat(references, containsInAnyOrder( | ||
| 176 | newBehaviorReferenceByConstructor(source, m_subClassAA.getName(), "()V") | ||
| 177 | )); | ||
| 178 | |||
| 179 | // baseClass.getName() | ||
| 180 | source = new MethodEntry(m_baseClass, "a", "()Ljava/lang/String;"); | ||
| 181 | references = m_index.getBehaviorReferences(source); | ||
| 182 | assertThat(references, containsInAnyOrder( | ||
| 183 | newBehaviorReferenceByMethod(source, m_subClassAA.getName(), "a", "()Ljava/lang/String;"), | ||
| 184 | newBehaviorReferenceByMethod(source, m_subClassB.getName(), "a", "()V") | ||
| 185 | )); | ||
| 186 | |||
| 187 | // subclassAA.getName() | ||
| 188 | source = new MethodEntry(m_subClassAA, "a", "()Ljava/lang/String;"); | ||
| 189 | references = m_index.getBehaviorReferences(source); | ||
| 190 | assertThat(references, containsInAnyOrder( | ||
| 191 | newBehaviorReferenceByMethod(source, m_subClassAA.getName(), "a", "()V") | ||
| 192 | )); | ||
| 193 | } | ||
| 194 | |||
| 195 | @Test | ||
| 196 | public void containsEntries() { | ||
| 197 | |||
| 198 | // classes | ||
| 199 | assertThat(m_index.containsObfClass(m_baseClass), is(true)); | ||
| 200 | assertThat(m_index.containsObfClass(m_subClassA), is(true)); | ||
| 201 | assertThat(m_index.containsObfClass(m_subClassAA), is(true)); | ||
| 202 | assertThat(m_index.containsObfClass(m_subClassB), is(true)); | ||
| 203 | |||
| 204 | // fields | ||
| 205 | assertThat(m_index.containsObfField(m_nameField), is(true)); | ||
| 206 | assertThat(m_index.containsObfField(m_numThingsField), is(true)); | ||
| 207 | |||
| 208 | // methods | ||
| 209 | // getName() | ||
| 210 | assertThat(m_index.containsObfBehavior(new MethodEntry(m_baseClass, "a", "()Ljava/lang/String;")), is(true)); | ||
| 211 | assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassA, "a", "()Ljava/lang/String;")), is(false)); | ||
| 212 | assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassAA, "a", "()Ljava/lang/String;")), is(true)); | ||
| 213 | assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassB, "a", "()Ljava/lang/String;")), is(false)); | ||
| 214 | |||
| 215 | // doBaseThings() | ||
| 216 | assertThat(m_index.containsObfBehavior(new MethodEntry(m_baseClass, "a", "()V")), is(true)); | ||
| 217 | assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassA, "a", "()V")), is(false)); | ||
| 218 | assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassAA, "a", "()V")), is(true)); | ||
| 219 | assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassB, "a", "()V")), is(true)); | ||
| 220 | |||
| 221 | // doBThings() | ||
| 222 | assertThat(m_index.containsObfBehavior(new MethodEntry(m_baseClass, "b", "()V")), is(false)); | ||
| 223 | assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassA, "b", "()V")), is(false)); | ||
| 224 | assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassAA, "b", "()V")), is(false)); | ||
| 225 | assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassB, "b", "()V")), is(true)); | ||
| 226 | |||
| 227 | } | ||
| 228 | } | ||
diff --git a/test/cuchaz/enigma/TestJarIndexLoneClass.java b/test/cuchaz/enigma/TestJarIndexLoneClass.java new file mode 100644 index 00000000..a061b72d --- /dev/null +++ b/test/cuchaz/enigma/TestJarIndexLoneClass.java | |||
| @@ -0,0 +1,169 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * | ||
| 4 | * All rights reserved. This program and the accompanying materials | ||
| 5 | * are made available under the terms of the GNU Public License v3.0 | ||
| 6 | * which accompanies this distribution, and is available at | ||
| 7 | * http://www.gnu.org/licenses/gpl.html | ||
| 8 | * | ||
| 9 | * Contributors: | ||
| 10 | * Jeff Martin - initial API and implementation | ||
| 11 | ******************************************************************************/ | ||
| 12 | package cuchaz.enigma; | ||
| 13 | |||
| 14 | import static cuchaz.enigma.EntryFactory.*; | ||
| 15 | import static org.hamcrest.MatcherAssert.*; | ||
| 16 | import static org.hamcrest.Matchers.*; | ||
| 17 | |||
| 18 | import java.util.Collection; | ||
| 19 | import java.util.Set; | ||
| 20 | import java.util.jar.JarFile; | ||
| 21 | |||
| 22 | import org.junit.Test; | ||
| 23 | |||
| 24 | import cuchaz.enigma.analysis.Access; | ||
| 25 | import cuchaz.enigma.analysis.ClassImplementationsTreeNode; | ||
| 26 | import cuchaz.enigma.analysis.ClassInheritanceTreeNode; | ||
| 27 | import cuchaz.enigma.analysis.EntryReference; | ||
| 28 | import cuchaz.enigma.analysis.JarIndex; | ||
| 29 | import cuchaz.enigma.analysis.MethodImplementationsTreeNode; | ||
| 30 | import cuchaz.enigma.analysis.MethodInheritanceTreeNode; | ||
| 31 | import cuchaz.enigma.mapping.BehaviorEntry; | ||
| 32 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 33 | import cuchaz.enigma.mapping.FieldEntry; | ||
| 34 | import cuchaz.enigma.mapping.MethodEntry; | ||
| 35 | import cuchaz.enigma.mapping.Translator; | ||
| 36 | |||
| 37 | public class TestJarIndexLoneClass { | ||
| 38 | |||
| 39 | private JarIndex m_index; | ||
| 40 | |||
| 41 | public TestJarIndexLoneClass() throws Exception { | ||
| 42 | m_index = new JarIndex(); | ||
| 43 | m_index.indexJar(new JarFile("build/testLoneClass.obf.jar"), false); | ||
| 44 | } | ||
| 45 | |||
| 46 | @Test | ||
| 47 | public void obfEntries() { | ||
| 48 | assertThat(m_index.getObfClassEntries(), containsInAnyOrder( | ||
| 49 | newClass("cuchaz/enigma/inputs/Keep"), | ||
| 50 | newClass("none/a") | ||
| 51 | )); | ||
| 52 | } | ||
| 53 | |||
| 54 | @Test | ||
| 55 | public void translationIndex() { | ||
| 56 | assertThat(m_index.getTranslationIndex().getSuperclass(new ClassEntry("none/a")), is(nullValue())); | ||
| 57 | assertThat(m_index.getTranslationIndex().getSuperclass(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(nullValue())); | ||
| 58 | assertThat(m_index.getTranslationIndex().getAncestry(new ClassEntry("none/a")), is(empty())); | ||
| 59 | assertThat(m_index.getTranslationIndex().getAncestry(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(empty())); | ||
| 60 | assertThat(m_index.getTranslationIndex().getSubclass(new ClassEntry("none/a")), is(empty())); | ||
| 61 | assertThat(m_index.getTranslationIndex().getSubclass(new ClassEntry("cuchaz/enigma/inputs/Keep")), is(empty())); | ||
| 62 | } | ||
| 63 | |||
| 64 | @Test | ||
| 65 | public void access() { | ||
| 66 | assertThat(m_index.getAccess(newField("none/a", "a")), is(Access.Private)); | ||
| 67 | assertThat(m_index.getAccess(newMethod("none/a", "a", "()Ljava/lang/String;")), is(Access.Public)); | ||
| 68 | assertThat(m_index.getAccess(newField("none/a", "b")), is(nullValue())); | ||
| 69 | } | ||
| 70 | |||
| 71 | @Test | ||
| 72 | public void classInheritance() { | ||
| 73 | ClassInheritanceTreeNode node = m_index.getClassInheritance(new Translator(), newClass("none/a")); | ||
| 74 | assertThat(node, is(not(nullValue()))); | ||
| 75 | assertThat(node.getObfClassName(), is("none/a")); | ||
| 76 | assertThat(node.getChildCount(), is(0)); | ||
| 77 | } | ||
| 78 | |||
| 79 | @Test | ||
| 80 | public void methodInheritance() { | ||
| 81 | MethodEntry source = newMethod("none/a", "a", "()Ljava/lang/String;"); | ||
| 82 | MethodInheritanceTreeNode node = m_index.getMethodInheritance(new Translator(), source); | ||
| 83 | assertThat(node, is(not(nullValue()))); | ||
| 84 | assertThat(node.getMethodEntry(), is(source)); | ||
| 85 | assertThat(node.getChildCount(), is(0)); | ||
| 86 | } | ||
| 87 | |||
| 88 | @Test | ||
| 89 | public void classImplementations() { | ||
| 90 | ClassImplementationsTreeNode node = m_index.getClassImplementations(new Translator(), newClass("none/a")); | ||
| 91 | assertThat(node, is(nullValue())); | ||
| 92 | } | ||
| 93 | |||
| 94 | @Test | ||
| 95 | public void methodImplementations() { | ||
| 96 | MethodEntry source = newMethod("none/a", "a", "()Ljava/lang/String;"); | ||
| 97 | MethodImplementationsTreeNode node = m_index.getMethodImplementations(new Translator(), source); | ||
| 98 | assertThat(node, is(nullValue())); | ||
| 99 | } | ||
| 100 | |||
| 101 | @Test | ||
| 102 | public void relatedMethodImplementations() { | ||
| 103 | Set<MethodEntry> entries = m_index.getRelatedMethodImplementations(newMethod("none/a", "a", "()Ljava/lang/String;")); | ||
| 104 | assertThat(entries, containsInAnyOrder( | ||
| 105 | newMethod("none/a", "a", "()Ljava/lang/String;") | ||
| 106 | )); | ||
| 107 | } | ||
| 108 | |||
| 109 | @Test | ||
| 110 | @SuppressWarnings("unchecked") | ||
| 111 | public void fieldReferences() { | ||
| 112 | FieldEntry source = newField("none/a", "a"); | ||
| 113 | Collection<EntryReference<FieldEntry,BehaviorEntry>> references = m_index.getFieldReferences(source); | ||
| 114 | assertThat(references, containsInAnyOrder( | ||
| 115 | newFieldReferenceByConstructor(source, "none/a", "(Ljava/lang/String;)V"), | ||
| 116 | newFieldReferenceByMethod(source, "none/a", "a", "()Ljava/lang/String;") | ||
| 117 | )); | ||
| 118 | } | ||
| 119 | |||
| 120 | @Test | ||
| 121 | public void behaviorReferences() { | ||
| 122 | assertThat(m_index.getBehaviorReferences(newMethod("none/a", "a", "()Ljava/lang/String;")), is(empty())); | ||
| 123 | } | ||
| 124 | |||
| 125 | @Test | ||
| 126 | public void innerClasses() { | ||
| 127 | assertThat(m_index.getInnerClasses("none/a"), is(empty())); | ||
| 128 | } | ||
| 129 | |||
| 130 | @Test | ||
| 131 | public void outerClass() { | ||
| 132 | assertThat(m_index.getOuterClass("a"), is(nullValue())); | ||
| 133 | } | ||
| 134 | |||
| 135 | @Test | ||
| 136 | public void isAnonymousClass() { | ||
| 137 | assertThat(m_index.isAnonymousClass("none/a"), is(false)); | ||
| 138 | } | ||
| 139 | |||
| 140 | @Test | ||
| 141 | public void interfaces() { | ||
| 142 | assertThat(m_index.getInterfaces("none/a"), is(empty())); | ||
| 143 | } | ||
| 144 | |||
| 145 | @Test | ||
| 146 | public void implementingClasses() { | ||
| 147 | assertThat(m_index.getImplementingClasses("none/a"), is(empty())); | ||
| 148 | } | ||
| 149 | |||
| 150 | @Test | ||
| 151 | public void isInterface() { | ||
| 152 | assertThat(m_index.isInterface("none/a"), is(false)); | ||
| 153 | } | ||
| 154 | |||
| 155 | @Test | ||
| 156 | public void bridgeMethods() { | ||
| 157 | assertThat(m_index.getBridgeMethod(newMethod("none/a", "a", "()Ljava/lang/String;")), is(nullValue())); | ||
| 158 | } | ||
| 159 | |||
| 160 | @Test | ||
| 161 | public void contains() { | ||
| 162 | assertThat(m_index.containsObfClass(newClass("none/a")), is(true)); | ||
| 163 | assertThat(m_index.containsObfClass(newClass("none/b")), is(false)); | ||
| 164 | assertThat(m_index.containsObfField(newField("none/a", "a")), is(true)); | ||
| 165 | assertThat(m_index.containsObfField(newField("none/a", "b")), is(false)); | ||
| 166 | assertThat(m_index.containsObfBehavior(newMethod("none/a", "a", "()Ljava/lang/String;")), is(true)); | ||
| 167 | assertThat(m_index.containsObfBehavior(newMethod("none/a", "b", "()Ljava/lang/String;")), is(false)); | ||
| 168 | } | ||
| 169 | } | ||
diff --git a/test/cuchaz/enigma/TestSourceIndex.java b/test/cuchaz/enigma/TestSourceIndex.java new file mode 100644 index 00000000..70a5ee4c --- /dev/null +++ b/test/cuchaz/enigma/TestSourceIndex.java | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * | ||
| 4 | * All rights reserved. This program and the accompanying materials | ||
| 5 | * are made available under the terms of the GNU Public License v3.0 | ||
| 6 | * which accompanies this distribution, and is available at | ||
| 7 | * http://www.gnu.org/licenses/gpl.html | ||
| 8 | * | ||
| 9 | * Contributors: | ||
| 10 | * Jeff Martin - initial API and implementation | ||
| 11 | ******************************************************************************/ | ||
| 12 | package cuchaz.enigma; | ||
| 13 | |||
| 14 | import java.util.Set; | ||
| 15 | import java.util.jar.JarFile; | ||
| 16 | |||
| 17 | import org.junit.Test; | ||
| 18 | |||
| 19 | import com.google.common.collect.Sets; | ||
| 20 | import com.strobel.decompiler.languages.java.ast.CompilationUnit; | ||
| 21 | |||
| 22 | import cuchaz.enigma.mapping.ClassEntry; | ||
| 23 | |||
| 24 | public class TestSourceIndex { | ||
| 25 | |||
| 26 | // TEMP | ||
| 27 | @Test | ||
| 28 | public void indexEverything() throws Exception { | ||
| 29 | Deobfuscator deobfuscator = new Deobfuscator(new JarFile("input/1.8.jar")); | ||
| 30 | |||
| 31 | // get all classes that aren't inner classes | ||
| 32 | Set<ClassEntry> classEntries = Sets.newHashSet(); | ||
| 33 | for (ClassEntry obfClassEntry : deobfuscator.getJarIndex().getObfClassEntries()) { | ||
| 34 | if (!obfClassEntry.isInnerClass()) { | ||
| 35 | classEntries.add(obfClassEntry); | ||
| 36 | } | ||
| 37 | } | ||
| 38 | |||
| 39 | for (ClassEntry obfClassEntry : classEntries) { | ||
| 40 | try { | ||
| 41 | CompilationUnit tree = deobfuscator.getSourceTree(obfClassEntry.getName()); | ||
| 42 | String source = deobfuscator.getSource(tree); | ||
| 43 | deobfuscator.getSourceIndex(tree, source); | ||
| 44 | } catch (Throwable t) { | ||
| 45 | throw new Error("Unable to index " + obfClassEntry, t); | ||
| 46 | } | ||
| 47 | } | ||
| 48 | } | ||
| 49 | } | ||
diff --git a/test/cuchaz/enigma/TestTokensConstructors.java b/test/cuchaz/enigma/TestTokensConstructors.java new file mode 100644 index 00000000..56424ae8 --- /dev/null +++ b/test/cuchaz/enigma/TestTokensConstructors.java | |||
| @@ -0,0 +1,135 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma; | ||
| 12 | |||
| 13 | import static cuchaz.enigma.EntryFactory.*; | ||
| 14 | import static org.hamcrest.MatcherAssert.*; | ||
| 15 | import static org.hamcrest.Matchers.*; | ||
| 16 | |||
| 17 | import java.util.jar.JarFile; | ||
| 18 | |||
| 19 | import org.junit.Test; | ||
| 20 | |||
| 21 | import cuchaz.enigma.mapping.BehaviorEntry; | ||
| 22 | |||
| 23 | public class TestTokensConstructors extends TokenChecker { | ||
| 24 | |||
| 25 | public TestTokensConstructors() throws Exception { | ||
| 26 | super(new JarFile("build/testConstructors.obf.jar")); | ||
| 27 | } | ||
| 28 | |||
| 29 | @Test | ||
| 30 | public void baseDeclarations() { | ||
| 31 | assertThat(getDeclarationToken(newConstructor("none/a", "()V")), is("a")); | ||
| 32 | assertThat(getDeclarationToken(newConstructor("none/a", "(I)V")), is("a")); | ||
| 33 | } | ||
| 34 | |||
| 35 | @Test | ||
| 36 | public void subDeclarations() { | ||
| 37 | assertThat(getDeclarationToken(newConstructor("none/d", "()V")), is("d")); | ||
| 38 | assertThat(getDeclarationToken(newConstructor("none/d", "(I)V")), is("d")); | ||
| 39 | assertThat(getDeclarationToken(newConstructor("none/d", "(II)V")), is("d")); | ||
| 40 | assertThat(getDeclarationToken(newConstructor("none/d", "(III)V")), is("d")); | ||
| 41 | } | ||
| 42 | |||
| 43 | @Test | ||
| 44 | public void subsubDeclarations() { | ||
| 45 | assertThat(getDeclarationToken(newConstructor("none/e", "(I)V")), is("e")); | ||
| 46 | } | ||
| 47 | |||
| 48 | @Test | ||
| 49 | public void defaultDeclarations() { | ||
| 50 | assertThat(getDeclarationToken(newConstructor("none/c", "()V")), nullValue()); | ||
| 51 | } | ||
| 52 | |||
| 53 | @Test | ||
| 54 | public void baseDefaultReferences() { | ||
| 55 | BehaviorEntry source = newConstructor("none/a", "()V"); | ||
| 56 | assertThat( | ||
| 57 | getReferenceTokens(newBehaviorReferenceByMethod(source, "none/b", "a", "()V")), | ||
| 58 | containsInAnyOrder("a") | ||
| 59 | ); | ||
| 60 | assertThat( | ||
| 61 | getReferenceTokens(newBehaviorReferenceByConstructor(source, "none/d", "()V")), | ||
| 62 | is(empty()) // implicit call, not decompiled to token | ||
| 63 | ); | ||
| 64 | assertThat( | ||
| 65 | getReferenceTokens(newBehaviorReferenceByConstructor(source, "none/d", "(III)V")), | ||
| 66 | is(empty()) // implicit call, not decompiled to token | ||
| 67 | ); | ||
| 68 | } | ||
| 69 | |||
| 70 | @Test | ||
| 71 | public void baseIntReferences() { | ||
| 72 | BehaviorEntry source = newConstructor("none/a", "(I)V"); | ||
| 73 | assertThat( | ||
| 74 | getReferenceTokens(newBehaviorReferenceByMethod(source, "none/b", "b", "()V")), | ||
| 75 | containsInAnyOrder("a") | ||
| 76 | ); | ||
| 77 | } | ||
| 78 | |||
| 79 | @Test | ||
| 80 | public void subDefaultReferences() { | ||
| 81 | BehaviorEntry source = newConstructor("none/d", "()V"); | ||
| 82 | assertThat( | ||
| 83 | getReferenceTokens(newBehaviorReferenceByMethod(source, "none/b", "c", "()V")), | ||
| 84 | containsInAnyOrder("d") | ||
| 85 | ); | ||
| 86 | assertThat( | ||
| 87 | getReferenceTokens(newBehaviorReferenceByConstructor(source, "none/d", "(I)V")), | ||
| 88 | containsInAnyOrder("this") | ||
| 89 | ); | ||
| 90 | } | ||
| 91 | |||
| 92 | @Test | ||
| 93 | public void subIntReferences() { | ||
| 94 | BehaviorEntry source = newConstructor("none/d", "(I)V"); | ||
| 95 | assertThat(getReferenceTokens( | ||
| 96 | newBehaviorReferenceByMethod(source, "none/b", "d", "()V")), | ||
| 97 | containsInAnyOrder("d") | ||
| 98 | ); | ||
| 99 | assertThat(getReferenceTokens( | ||
| 100 | newBehaviorReferenceByConstructor(source, "none/d", "(II)V")), | ||
| 101 | containsInAnyOrder("this") | ||
| 102 | ); | ||
| 103 | assertThat(getReferenceTokens( | ||
| 104 | newBehaviorReferenceByConstructor(source, "none/e", "(I)V")), | ||
| 105 | containsInAnyOrder("super") | ||
| 106 | ); | ||
| 107 | } | ||
| 108 | |||
| 109 | @Test | ||
| 110 | public void subIntIntReferences() { | ||
| 111 | BehaviorEntry source = newConstructor("none/d", "(II)V"); | ||
| 112 | assertThat( | ||
| 113 | getReferenceTokens(newBehaviorReferenceByMethod(source, "none/b", "e", "()V")), | ||
| 114 | containsInAnyOrder("d") | ||
| 115 | ); | ||
| 116 | } | ||
| 117 | |||
| 118 | @Test | ||
| 119 | public void subsubIntReferences() { | ||
| 120 | BehaviorEntry source = newConstructor("none/e", "(I)V"); | ||
| 121 | assertThat( | ||
| 122 | getReferenceTokens(newBehaviorReferenceByMethod(source, "none/b", "f", "()V")), | ||
| 123 | containsInAnyOrder("e") | ||
| 124 | ); | ||
| 125 | } | ||
| 126 | |||
| 127 | @Test | ||
| 128 | public void defaultConstructableReferences() { | ||
| 129 | BehaviorEntry source = newConstructor("none/c", "()V"); | ||
| 130 | assertThat( | ||
| 131 | getReferenceTokens(newBehaviorReferenceByMethod(source, "none/b", "g", "()V")), | ||
| 132 | containsInAnyOrder("c") | ||
| 133 | ); | ||
| 134 | } | ||
| 135 | } | ||
diff --git a/test/cuchaz/enigma/TokenChecker.java b/test/cuchaz/enigma/TokenChecker.java new file mode 100644 index 00000000..febea2ae --- /dev/null +++ b/test/cuchaz/enigma/TokenChecker.java | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | /******************************************************************************* | ||
| 2 | * Copyright (c) 2014 Jeff Martin. | ||
| 3 | * All rights reserved. This program and the accompanying materials | ||
| 4 | * are made available under the terms of the GNU Public License v3.0 | ||
| 5 | * which accompanies this distribution, and is available at | ||
| 6 | * http://www.gnu.org/licenses/gpl.html | ||
| 7 | * | ||
| 8 | * Contributors: | ||
| 9 | * Jeff Martin - initial API and implementation | ||
| 10 | ******************************************************************************/ | ||
| 11 | package cuchaz.enigma; | ||
| 12 | |||
| 13 | import java.io.IOException; | ||
| 14 | import java.util.Collection; | ||
| 15 | import java.util.List; | ||
| 16 | import java.util.jar.JarFile; | ||
| 17 | |||
| 18 | import com.google.common.collect.Lists; | ||
| 19 | import com.strobel.decompiler.languages.java.ast.CompilationUnit; | ||
| 20 | |||
| 21 | import cuchaz.enigma.analysis.EntryReference; | ||
| 22 | import cuchaz.enigma.analysis.SourceIndex; | ||
| 23 | import cuchaz.enigma.analysis.Token; | ||
| 24 | import cuchaz.enigma.mapping.Entry; | ||
| 25 | |||
| 26 | public class TokenChecker { | ||
| 27 | |||
| 28 | private Deobfuscator m_deobfuscator; | ||
| 29 | |||
| 30 | protected TokenChecker(JarFile jarFile) throws IOException { | ||
| 31 | m_deobfuscator = new Deobfuscator(jarFile); | ||
| 32 | } | ||
| 33 | |||
| 34 | protected String getDeclarationToken(Entry entry) { | ||
| 35 | // decompile the class | ||
| 36 | CompilationUnit tree = m_deobfuscator.getSourceTree(entry.getClassName()); | ||
| 37 | // DEBUG | ||
| 38 | // tree.acceptVisitor( new TreeDumpVisitor( new File( "tree." + entry.getClassName().replace( '/', '.' ) + ".txt" ) ), null ); | ||
| 39 | String source = m_deobfuscator.getSource(tree); | ||
| 40 | SourceIndex index = m_deobfuscator.getSourceIndex(tree, source); | ||
| 41 | |||
| 42 | // get the token value | ||
| 43 | Token token = index.getDeclarationToken(entry); | ||
| 44 | if (token == null) { | ||
| 45 | return null; | ||
| 46 | } | ||
| 47 | return source.substring(token.start, token.end); | ||
| 48 | } | ||
| 49 | |||
| 50 | @SuppressWarnings("unchecked") | ||
| 51 | protected Collection<String> getReferenceTokens(EntryReference<? extends Entry,? extends Entry> reference) { | ||
| 52 | // decompile the class | ||
| 53 | CompilationUnit tree = m_deobfuscator.getSourceTree(reference.context.getClassName()); | ||
| 54 | String source = m_deobfuscator.getSource(tree); | ||
| 55 | SourceIndex index = m_deobfuscator.getSourceIndex(tree, source); | ||
| 56 | |||
| 57 | // get the token values | ||
| 58 | List<String> values = Lists.newArrayList(); | ||
| 59 | for (Token token : index.getReferenceTokens((EntryReference<Entry,Entry>)reference)) { | ||
| 60 | values.add(source.substring(token.start, token.end)); | ||
| 61 | } | ||
| 62 | return values; | ||
| 63 | } | ||
| 64 | } | ||
diff --git a/test/cuchaz/enigma/inputs/Keep.java b/test/cuchaz/enigma/inputs/Keep.java new file mode 100644 index 00000000..390e82fb --- /dev/null +++ b/test/cuchaz/enigma/inputs/Keep.java | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | package cuchaz.enigma.inputs; | ||
| 2 | |||
| 3 | public class Keep { | ||
| 4 | public static void main(String[] args) { | ||
| 5 | System.out.println("Keep me!"); | ||
| 6 | } | ||
| 7 | } | ||
diff --git a/test/cuchaz/enigma/inputs/constructors/BaseClass.java b/test/cuchaz/enigma/inputs/constructors/BaseClass.java new file mode 100644 index 00000000..93453086 --- /dev/null +++ b/test/cuchaz/enigma/inputs/constructors/BaseClass.java | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | package cuchaz.enigma.inputs.constructors; | ||
| 2 | |||
| 3 | // none/a | ||
| 4 | public class BaseClass { | ||
| 5 | |||
| 6 | // <init>()V | ||
| 7 | public BaseClass() { | ||
| 8 | System.out.println("Default constructor"); | ||
| 9 | } | ||
| 10 | |||
| 11 | // <init>(I)V | ||
| 12 | public BaseClass(int i) { | ||
| 13 | System.out.println("Int constructor " + i); | ||
| 14 | } | ||
| 15 | } | ||
diff --git a/test/cuchaz/enigma/inputs/constructors/Caller.java b/test/cuchaz/enigma/inputs/constructors/Caller.java new file mode 100644 index 00000000..57278751 --- /dev/null +++ b/test/cuchaz/enigma/inputs/constructors/Caller.java | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | package cuchaz.enigma.inputs.constructors; | ||
| 2 | |||
| 3 | // none/b | ||
| 4 | public class Caller { | ||
| 5 | |||
| 6 | // a()V | ||
| 7 | public void callBaseDefault() { | ||
| 8 | // none/a.<init>()V | ||
| 9 | System.out.println(new BaseClass()); | ||
| 10 | } | ||
| 11 | |||
| 12 | // b()V | ||
| 13 | public void callBaseInt() { | ||
| 14 | // none/a.<init>(I)V | ||
| 15 | System.out.println(new BaseClass(5)); | ||
| 16 | } | ||
| 17 | |||
| 18 | // c()V | ||
| 19 | public void callSubDefault() { | ||
| 20 | // none/d.<init>()V | ||
| 21 | System.out.println(new SubClass()); | ||
| 22 | } | ||
| 23 | |||
| 24 | // d()V | ||
| 25 | public void callSubInt() { | ||
| 26 | // none/d.<init>(I)V | ||
| 27 | System.out.println(new SubClass(6)); | ||
| 28 | } | ||
| 29 | |||
| 30 | // e()V | ||
| 31 | public void callSubIntInt() { | ||
| 32 | // none/d.<init>(II)V | ||
| 33 | System.out.println(new SubClass(4, 2)); | ||
| 34 | } | ||
| 35 | |||
| 36 | // f()V | ||
| 37 | public void callSubSubInt() { | ||
| 38 | // none/e.<init>(I)V | ||
| 39 | System.out.println(new SubSubClass(3)); | ||
| 40 | } | ||
| 41 | |||
| 42 | // g()V | ||
| 43 | public void callDefaultConstructable() { | ||
| 44 | // none/c.<init>()V | ||
| 45 | System.out.println(new DefaultConstructable()); | ||
| 46 | } | ||
| 47 | } | ||
diff --git a/test/cuchaz/enigma/inputs/constructors/DefaultConstructable.java b/test/cuchaz/enigma/inputs/constructors/DefaultConstructable.java new file mode 100644 index 00000000..26a3ddbb --- /dev/null +++ b/test/cuchaz/enigma/inputs/constructors/DefaultConstructable.java | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | package cuchaz.enigma.inputs.constructors; | ||
| 2 | |||
| 3 | public class DefaultConstructable { | ||
| 4 | // only default constructor | ||
| 5 | } | ||
diff --git a/test/cuchaz/enigma/inputs/constructors/SubClass.java b/test/cuchaz/enigma/inputs/constructors/SubClass.java new file mode 100644 index 00000000..fecfa2b5 --- /dev/null +++ b/test/cuchaz/enigma/inputs/constructors/SubClass.java | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | package cuchaz.enigma.inputs.constructors; | ||
| 2 | |||
| 3 | // none/d extends none/a | ||
| 4 | public class SubClass extends BaseClass { | ||
| 5 | |||
| 6 | // <init>()V | ||
| 7 | public SubClass() { | ||
| 8 | // none/a.<init>()V | ||
| 9 | } | ||
| 10 | |||
| 11 | // <init>(I)V | ||
| 12 | public SubClass(int num) { | ||
| 13 | // <init>()V | ||
| 14 | this(); | ||
| 15 | System.out.println("SubClass " + num); | ||
| 16 | } | ||
| 17 | |||
| 18 | // <init>(II)V | ||
| 19 | public SubClass(int a, int b) { | ||
| 20 | // <init>(I)V | ||
| 21 | this(a + b); | ||
| 22 | } | ||
| 23 | |||
| 24 | // <init>(III)V | ||
| 25 | public SubClass(int a, int b, int c) { | ||
| 26 | // none/a.<init>()V | ||
| 27 | } | ||
| 28 | } | ||
diff --git a/test/cuchaz/enigma/inputs/constructors/SubSubClass.java b/test/cuchaz/enigma/inputs/constructors/SubSubClass.java new file mode 100644 index 00000000..ab84161b --- /dev/null +++ b/test/cuchaz/enigma/inputs/constructors/SubSubClass.java | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | package cuchaz.enigma.inputs.constructors; | ||
| 2 | |||
| 3 | // none/e extends none/d | ||
| 4 | public class SubSubClass extends SubClass { | ||
| 5 | |||
| 6 | // <init>(I)V | ||
| 7 | public SubSubClass(int i) { | ||
| 8 | // none/c.<init>(I)V | ||
| 9 | super(i); | ||
| 10 | } | ||
| 11 | } | ||
diff --git a/test/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java b/test/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java new file mode 100644 index 00000000..5b416c41 --- /dev/null +++ b/test/cuchaz/enigma/inputs/inheritanceTree/BaseClass.java | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | package cuchaz.enigma.inputs.inheritanceTree; | ||
| 2 | |||
| 3 | // none/a | ||
| 4 | public abstract class BaseClass { | ||
| 5 | |||
| 6 | // a | ||
| 7 | private String m_name; | ||
| 8 | |||
| 9 | // <init>(Ljava/lang/String;)V | ||
| 10 | protected BaseClass(String name) { | ||
| 11 | m_name = name; | ||
| 12 | } | ||
| 13 | |||
| 14 | // a()Ljava/lang/String; | ||
| 15 | public String getName() { | ||
| 16 | return m_name; | ||
| 17 | } | ||
| 18 | |||
| 19 | // a()V | ||
| 20 | public abstract void doBaseThings(); | ||
| 21 | } | ||
diff --git a/test/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java b/test/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java new file mode 100644 index 00000000..7a99d516 --- /dev/null +++ b/test/cuchaz/enigma/inputs/inheritanceTree/SubclassA.java | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | package cuchaz.enigma.inputs.inheritanceTree; | ||
| 2 | |||
| 3 | // none/b extends none/a | ||
| 4 | public abstract class SubclassA extends BaseClass { | ||
| 5 | |||
| 6 | // <init>(Ljava/lang/String;)V | ||
| 7 | protected SubclassA(String name) { | ||
| 8 | // call to none/a.<init>(Ljava/lang/String)V | ||
| 9 | super(name); | ||
| 10 | } | ||
| 11 | } | ||
diff --git a/test/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java b/test/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java new file mode 100644 index 00000000..c9485d31 --- /dev/null +++ b/test/cuchaz/enigma/inputs/inheritanceTree/SubclassB.java | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | package cuchaz.enigma.inputs.inheritanceTree; | ||
| 2 | |||
| 3 | // none/c extends none/a | ||
| 4 | public class SubclassB extends BaseClass { | ||
| 5 | |||
| 6 | // a | ||
| 7 | private int m_numThings; | ||
| 8 | |||
| 9 | // <init>()V | ||
| 10 | protected SubclassB() { | ||
| 11 | // none/a.<init>(Ljava/lang/String;)V | ||
| 12 | super("B"); | ||
| 13 | |||
| 14 | // access to a | ||
| 15 | m_numThings = 4; | ||
| 16 | } | ||
| 17 | |||
| 18 | @Override | ||
| 19 | // a()V | ||
| 20 | public void doBaseThings() { | ||
| 21 | // call to none/a.a()Ljava/lang/String; | ||
| 22 | System.out.println("Base things by B! " + getName()); | ||
| 23 | } | ||
| 24 | |||
| 25 | // b()V | ||
| 26 | public void doBThings() { | ||
| 27 | // access to a | ||
| 28 | System.out.println("" + m_numThings + " B things!"); | ||
| 29 | } | ||
| 30 | } | ||
diff --git a/test/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java b/test/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java new file mode 100644 index 00000000..afd03ac4 --- /dev/null +++ b/test/cuchaz/enigma/inputs/inheritanceTree/SubsubclassAA.java | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | package cuchaz.enigma.inputs.inheritanceTree; | ||
| 2 | |||
| 3 | // none/d extends none/b | ||
| 4 | public class SubsubclassAA extends SubclassA { | ||
| 5 | |||
| 6 | protected SubsubclassAA() { | ||
| 7 | // call to none/b.<init>(Ljava/lang/String;)V | ||
| 8 | super("AA"); | ||
| 9 | } | ||
| 10 | |||
| 11 | @Override | ||
| 12 | // a()Ljava/lang/String; | ||
| 13 | public String getName() { | ||
| 14 | // call to none/b.a()Ljava/lang/String; | ||
| 15 | return "subsub" + super.getName(); | ||
| 16 | } | ||
| 17 | |||
| 18 | @Override | ||
| 19 | // a()V | ||
| 20 | public void doBaseThings() { | ||
| 21 | // call to none/d.a()Ljava/lang/String; | ||
| 22 | System.out.println("Base things by " + getName()); | ||
| 23 | } | ||
| 24 | } | ||
diff --git a/test/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java b/test/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java new file mode 100644 index 00000000..f7118f63 --- /dev/null +++ b/test/cuchaz/enigma/inputs/innerClasses/A_Anonymous.java | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | package cuchaz.enigma.inputs.innerClasses; | ||
| 2 | |||
| 3 | public class A_Anonymous { | ||
| 4 | |||
| 5 | public void foo() { | ||
| 6 | Runnable runnable = new Runnable() { | ||
| 7 | @Override | ||
| 8 | public void run() { | ||
| 9 | // don't care | ||
| 10 | } | ||
| 11 | }; | ||
| 12 | runnable.run(); | ||
| 13 | } | ||
| 14 | } | ||
diff --git a/test/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java b/test/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java new file mode 100644 index 00000000..42fba9a8 --- /dev/null +++ b/test/cuchaz/enigma/inputs/innerClasses/B_AnonymousWithScopeArgs.java | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | package cuchaz.enigma.inputs.innerClasses; | ||
| 2 | |||
| 3 | public class B_AnonymousWithScopeArgs { | ||
| 4 | |||
| 5 | public static void foo(final D_Simple arg) { | ||
| 6 | System.out.println(new Object() { | ||
| 7 | @Override | ||
| 8 | public String toString() { | ||
| 9 | return arg.toString(); | ||
| 10 | } | ||
| 11 | }); | ||
| 12 | } | ||
| 13 | } | ||
diff --git a/test/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java b/test/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java new file mode 100644 index 00000000..8fa6c5b8 --- /dev/null +++ b/test/cuchaz/enigma/inputs/innerClasses/C_ConstructorArgs.java | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | package cuchaz.enigma.inputs.innerClasses; | ||
| 2 | |||
| 3 | @SuppressWarnings("unused") | ||
| 4 | public class C_ConstructorArgs { | ||
| 5 | |||
| 6 | class Inner { | ||
| 7 | |||
| 8 | private int a; | ||
| 9 | |||
| 10 | public Inner(int a) { | ||
| 11 | this.a = a; | ||
| 12 | } | ||
| 13 | } | ||
| 14 | |||
| 15 | Inner i; | ||
| 16 | |||
| 17 | public void foo() { | ||
| 18 | i = new Inner(5); | ||
| 19 | } | ||
| 20 | } | ||
diff --git a/test/cuchaz/enigma/inputs/innerClasses/D_Simple.java b/test/cuchaz/enigma/inputs/innerClasses/D_Simple.java new file mode 100644 index 00000000..c4fc0ef9 --- /dev/null +++ b/test/cuchaz/enigma/inputs/innerClasses/D_Simple.java | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | package cuchaz.enigma.inputs.innerClasses; | ||
| 2 | |||
| 3 | public class D_Simple { | ||
| 4 | |||
| 5 | class Inner { | ||
| 6 | // nothing to do | ||
| 7 | } | ||
| 8 | } | ||
diff --git a/test/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java b/test/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java new file mode 100644 index 00000000..e1de53cb --- /dev/null +++ b/test/cuchaz/enigma/inputs/innerClasses/E_AnonymousWithOuterAccess.java | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | package cuchaz.enigma.inputs.innerClasses; | ||
| 2 | |||
| 3 | public class E_AnonymousWithOuterAccess { | ||
| 4 | |||
| 5 | // reproduction of error case documented at: | ||
| 6 | // https://bitbucket.org/cuchaz/enigma/issue/61/stackoverflowerror-when-deobfuscating | ||
| 7 | |||
| 8 | public Object makeInner() { | ||
| 9 | outerMethod(); | ||
| 10 | return new Object() { | ||
| 11 | @Override | ||
| 12 | public String toString() { | ||
| 13 | return outerMethod(); | ||
| 14 | } | ||
| 15 | }; | ||
| 16 | } | ||
| 17 | |||
| 18 | private String outerMethod() { | ||
| 19 | return "foo"; | ||
| 20 | } | ||
| 21 | } | ||
diff --git a/test/cuchaz/enigma/inputs/loneClass/LoneClass.java b/test/cuchaz/enigma/inputs/loneClass/LoneClass.java new file mode 100644 index 00000000..18c716e9 --- /dev/null +++ b/test/cuchaz/enigma/inputs/loneClass/LoneClass.java | |||
| @@ -0,0 +1,14 @@ | |||
| 1 | package cuchaz.enigma.inputs.loneClass; | ||
| 2 | |||
| 3 | public class LoneClass { | ||
| 4 | |||
| 5 | private String m_name; | ||
| 6 | |||
| 7 | public LoneClass(String name) { | ||
| 8 | m_name = name; | ||
| 9 | } | ||
| 10 | |||
| 11 | public String getName() { | ||
| 12 | return m_name; | ||
| 13 | } | ||
| 14 | } | ||