/******************************************************************************* * Copyright (c) 2014 Jeff Martin. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * Jeff Martin - initial API and implementation ******************************************************************************/ package cuchaz.enigma; import static cuchaz.enigma.EntryFactory.*; import static org.hamcrest.MatcherAssert.*; import static org.hamcrest.Matchers.*; import java.util.Collection; import java.util.Set; import java.util.jar.JarFile; import org.junit.Test; import cuchaz.enigma.analysis.Access; import cuchaz.enigma.analysis.EntryReference; import cuchaz.enigma.analysis.JarIndex; import cuchaz.enigma.analysis.TranslationIndex; import cuchaz.enigma.mapping.BehaviorEntry; import cuchaz.enigma.mapping.ClassEntry; import cuchaz.enigma.mapping.ConstructorEntry; import cuchaz.enigma.mapping.FieldEntry; import cuchaz.enigma.mapping.MethodEntry; public class TestJarIndexInheritanceTree { private JarIndex m_index; private ClassEntry m_baseClass = new ClassEntry("none/a"); private ClassEntry m_subClassA = new ClassEntry("none/b"); private ClassEntry m_subClassAA = new ClassEntry("none/d"); private ClassEntry m_subClassB = new ClassEntry("none/c"); private FieldEntry m_nameField = new FieldEntry(m_baseClass, "a"); private FieldEntry m_numThingsField = new FieldEntry(m_subClassB, "a"); public TestJarIndexInheritanceTree() throws Exception { m_index = new JarIndex(); m_index.indexJar(new JarFile("build/libs/testInheritanceTree.obf.jar"), false); } @Test public void obfEntries() { assertThat(m_index.getObfClassEntries(), containsInAnyOrder( newClass("cuchaz/enigma/inputs/Keep"), m_baseClass, m_subClassA, m_subClassAA, m_subClassB )); } @Test public void translationIndex() { TranslationIndex index = m_index.getTranslationIndex(); // base class assertThat(index.getSuperclassName(m_baseClass.getName()), is(nullValue())); assertThat(index.getAncestry(m_baseClass.getName()), is(empty())); assertThat(index.getSubclassNames(m_baseClass.getName()), containsInAnyOrder( m_subClassA.getName(), m_subClassB.getName() )); // subclass a assertThat(index.getSuperclassName(m_subClassA.getName()), is(m_baseClass.getName())); assertThat(index.getAncestry(m_subClassA.getName()), contains(m_baseClass.getName())); assertThat(index.getSubclassNames(m_subClassA.getName()), contains(m_subClassAA.getName())); // subclass aa assertThat(index.getSuperclassName(m_subClassAA.getName()), is(m_subClassA.getName())); assertThat(index.getAncestry(m_subClassAA.getName()), contains(m_subClassA.getName(), m_baseClass.getName())); assertThat(index.getSubclassNames(m_subClassAA.getName()), is(empty())); // subclass b assertThat(index.getSuperclassName(m_subClassB.getName()), is(m_baseClass.getName())); assertThat(index.getAncestry(m_subClassB.getName()), contains(m_baseClass.getName())); assertThat(index.getSubclassNames(m_subClassB.getName()), 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(new MethodEntry(m_baseClass, "a", "()Ljava/lang/String;")); assertThat(entries, containsInAnyOrder( new MethodEntry(m_baseClass, "a", "()Ljava/lang/String;"), new MethodEntry(m_subClassAA, "a", "()Ljava/lang/String;") )); entries = m_index.getRelatedMethodImplementations(new MethodEntry(m_subClassAA, "a", "()Ljava/lang/String;")); assertThat(entries, containsInAnyOrder( new MethodEntry(m_baseClass, "a", "()Ljava/lang/String;"), new MethodEntry(m_subClassAA, "a", "()Ljava/lang/String;") )); // doBaseThings() entries = m_index.getRelatedMethodImplementations(new MethodEntry(m_baseClass, "a", "()V")); assertThat(entries, containsInAnyOrder( new MethodEntry(m_baseClass, "a", "()V"), new MethodEntry(m_subClassAA, "a", "()V"), new MethodEntry(m_subClassB, "a", "()V") )); entries = m_index.getRelatedMethodImplementations(new MethodEntry(m_subClassAA, "a", "()V")); assertThat(entries, containsInAnyOrder( new MethodEntry(m_baseClass, "a", "()V"), new MethodEntry(m_subClassAA, "a", "()V"), new MethodEntry(m_subClassB, "a", "()V") )); entries = m_index.getRelatedMethodImplementations(new MethodEntry(m_subClassB, "a", "()V")); assertThat(entries, containsInAnyOrder( new MethodEntry(m_baseClass, "a", "()V"), new MethodEntry(m_subClassAA, "a", "()V"), new MethodEntry(m_subClassB, "a", "()V") )); // doBThings entries = m_index.getRelatedMethodImplementations(new MethodEntry(m_subClassB, "b", "()V")); assertThat(entries, containsInAnyOrder(new MethodEntry(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 = new ConstructorEntry(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 = new ConstructorEntry(m_subClassA, "(Ljava/lang/String;)V"); references = m_index.getBehaviorReferences(source); assertThat(references, containsInAnyOrder( newBehaviorReferenceByConstructor(source, m_subClassAA.getName(), "()V") )); // baseClass.getName() source = new MethodEntry(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 = new MethodEntry(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(new MethodEntry(m_baseClass, "a", "()Ljava/lang/String;")), is(true)); assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassA, "a", "()Ljava/lang/String;")), is(false)); assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassAA, "a", "()Ljava/lang/String;")), is(true)); assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassB, "a", "()Ljava/lang/String;")), is(false)); // doBaseThings() assertThat(m_index.containsObfBehavior(new MethodEntry(m_baseClass, "a", "()V")), is(true)); assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassA, "a", "()V")), is(false)); assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassAA, "a", "()V")), is(true)); assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassB, "a", "()V")), is(true)); // doBThings() assertThat(m_index.containsObfBehavior(new MethodEntry(m_baseClass, "b", "()V")), is(false)); assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassA, "b", "()V")), is(false)); assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassAA, "b", "()V")), is(false)); assertThat(m_index.containsObfBehavior(new MethodEntry(m_subClassB, "b", "()V")), is(true)); } }