package com.tns;
import com.tns.bindings.AnnotationDescriptor;
import com.tns.bindings.Dump;
import com.tns.bindings.desc.ClassDescriptor;
import com.tns.bindings.desc.MethodDescriptor;
import com.tns.bindings.desc.reflection.ClassInfo;
import com.tns.bindings.desc.reflection.MethodInfo;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.ow2.asmdex.ApplicationWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
public class DumpMethodTests {
private Dump dump;
private static HashMap<String, MethodDescriptor> nameToMethodDescriptor;
private static ClassDescriptor testClassDescriptor;
private static ApplicationWriter aw = new ApplicationWriter();
private static HashSet<String> methodOverrides;
private static HashSet<ClassDescriptor> overridenInterfaces;
@Before
public void instanceSetUp() {
this.dump = new Dump();
}
@BeforeClass
public static void setUp() {
nameToMethodDescriptor = new HashMap<>();
Method[] testClassMethods = TestClass.class.getDeclaredMethods();
for (int i = 0; i < testClassMethods.length; i++) {
MethodDescriptor md = new MethodInfo(testClassMethods[i]);
nameToMethodDescriptor.put(md.getName(), md);
}
try {
MethodDescriptor ctor = new MethodInfo(TestClass.class.getDeclaredConstructor(new Class[0]));
nameToMethodDescriptor.put("constructor", ctor);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
testClassDescriptor = new ClassInfo(TestClass.class);
aw.visit();
methodOverrides = new HashSet<String>();
methodOverrides.add("TestMethod");
methodOverrides.add("TestMethod1");
overridenInterfaces = new HashSet<ClassDescriptor>();
overridenInterfaces.add(new ClassInfo(Interface1.class));
}
@Test
public void getDexMethodDescriptor_method_returns_correct_result() throws NoSuchMethodException {
MethodDescriptor mi = nameToMethodDescriptor.get("TestMethod");
String result = this.dump.getDexMethodDescriptor(mi);
String expected = "VLjava/lang/String;Ljava/lang/Integer;Ljava/lang/Object;";
Assert.assertEquals(expected, result);
}
@Test
public void getMethodOverloadDescriptor_method_returns_correct_result() throws NoSuchMethodException {
MethodDescriptor mi = nameToMethodDescriptor.get("TestMethod");
String result = this.dump.getMethodOverloadDescriptor(mi);
String expected = "Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Object;";
Assert.assertEquals(expected, result);
}
@Test
public void getDexConstructorDescriptor_method_returns_correct_result() throws NoSuchMethodException {
MethodDescriptor mi = nameToMethodDescriptor.get("constructor");
String result = this.dump.getDexConstructorDescriptor(mi);
String expected = "V";
Assert.assertEquals(expected, result);
}
@Test
public void getAsmDescriptor_method_returns_correct_result() throws NoSuchMethodException {
String result = this.dump.getAsmDescriptor(testClassDescriptor);
String expected = "Lcom/tns/TestClass;";
Assert.assertEquals(expected, result);
}
@Test
public void getClassSignatureOfType_method_returns_correct_result() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
final Object[] params = {testClassDescriptor };
Method m = Dump.class.getDeclaredMethod("getClassSignatureOfType", ClassDescriptor.class);
m.setAccessible(true);
String result = (String)m.invoke(this.dump.getClass(), params);
String expected = "Lcom/tns/TestClass;";
Assert.assertEquals(expected, result);
}
@Test
public void getMethodSignature_method_returns_correct_result() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method m = Dump.class.getDeclaredMethod("getMethodSignature", MethodDescriptor.class);
m.setAccessible(true);
MethodDescriptor md = nameToMethodDescriptor.get("TestMethodNoParams");
final Object[] params = {md};
String result = (String)m.invoke(this.dump, params);
String expected = "TestMethodNoParams()";
MethodDescriptor md1 = nameToMethodDescriptor.get("TestMethod1");
final Object[] params1 = {md1};
String result1 = (String)m.invoke(this.dump, params1);
String expected1 = "TestMethod1(java.lang.String)";
Assert.assertEquals(expected1, result1);
Assert.assertEquals(expected, result);
}
@Test
public void collectAbstractMethods_method_returns_correct_result() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method m = Dump.class.getDeclaredMethod("collectAbstractMethods", ClassDescriptor.class, List.class);
m.setAccessible(true);
MethodDescriptor md = nameToMethodDescriptor.get("TestMethodNoParams");
Object[] params= new Object[2];
params[0] = new ClassInfo(Interface1.class);
ArrayList<MethodDescriptor> mds = new ArrayList<>();
params[1] = mds;
m.invoke(this.dump, params);
Assert.assertTrue(mds.size() > 0);
String expected = mds.get(0).getName();
String result = "methodFromInterface";
Assert.assertEquals(expected, result);
}
@Test
public void getSupportedMethods_method_returns_correct_result() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method m = Dump.class.getDeclaredMethod("getSupportedMethods", ClassDescriptor.class, HashSet.class, HashSet.class);
m.setAccessible(true);
Object[] params= new Object[3];
params[0] = testClassDescriptor;
HashSet<String> methodOverrides = new HashSet<>();
methodOverrides.add("TestMethod");
methodOverrides.add("NonExistentMethod"); //will be ignored because it's not part of TestClass.class
params[1] = methodOverrides;
HashSet<ClassDescriptor> interfacesToImplement = new HashSet<>();
interfacesToImplement.add(new ClassInfo(Interface1.class));
params[2] = interfacesToImplement;
MethodDescriptor[] methodDescriptors = (MethodDescriptor[])m.invoke(this.dump, params);
Assert.assertTrue(methodDescriptors.length == 2);
String interfaceMethodName = methodDescriptors[0].getName();
String TestMethodName= methodDescriptors[1].getName();
String expectedInterfaceName = "methodFromInterface";
String expectedTestMethodName = "TestMethod";
Assert.assertEquals(expectedInterfaceName, interfaceMethodName);
Assert.assertEquals(expectedTestMethodName, TestMethodName);
}
@Test
public void isMethodSupported_method_returns_correct_result() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
Method m = Dump.class.getDeclaredMethod("isMethodSupported", MethodDescriptor.class, HashMap.class);
m.setAccessible(true);
Object[] params= new Object[2];
params[0] = nameToMethodDescriptor.get("TestMethodNoParams");
HashMap<String, MethodDescriptor> finalMethods = new HashMap<>();
params[1] = finalMethods;
boolean isSupportedMethod = (boolean)m.invoke(Dump.class, params);
Assert.assertTrue(isSupportedMethod);
MethodInfo mi = null;
for (Method m1: AbstractClass.class.getDeclaredMethods()) {
if (m1.getName().equals("PrivateMethod")) {
mi = new MethodInfo(m1);
break;
}
}
params[0] = mi;
isSupportedMethod = (boolean)m.invoke(Dump.class, params);
Assert.assertFalse(isSupportedMethod);
}
}