feat: parse mock class considering MockContainer annotation

This commit is contained in:
金戟
2022-11-21 00:41:27 +08:00
parent db91a0ea34
commit e52538acf3
4 changed files with 35 additions and 13 deletions

View File

@@ -14,12 +14,12 @@ public class DemoMultipleInherit {
return "gin";
}
private String suffix() {
private String suffix(int some, String more, Object[] parameters) {
return "_al";
}
public String entry() {
return prefix() + middle() + suffix();
return prefix() + middle() + suffix(0, null, null);
}
}

View File

@@ -24,7 +24,7 @@ class DemoMultipleInheritTest {
public static class SuffixMock {
@MockInvoke(targetClass = DemoMultipleInherit.class)
private String suffix() {
private String suffix(int some, String more, Object[] parameters) {
return "_it";
}
}

View File

@@ -85,11 +85,8 @@ public class MockClassHandler extends BaseClassWithContextHandler {
}
}
}
for (int i = 0; i < inheritedTypes.size(); i++) {
String className = inheritedTypes.get(i).getClassName();
String fieldName = INHERITED_REF + i;
cn.fields.add(new FieldNode(ACC_PRIVATE | ACC_FINAL, fieldName,
ClassUtil.toByteCodeClassName(className), null, null));
for (Type inheritedType : inheritedTypes) {
String className = inheritedType.getClassName();
ClassNode inheritedClassNode = ClassUtil.getClassNode(className);
if (inheritedClassNode == null) {
throw new IllegalArgumentException("Failed to load class " + className);
@@ -104,14 +101,14 @@ public class MockClassHandler extends BaseClassWithContextHandler {
Type targetClass = AnnotationUtil.getAnnotationParameter(an, FIELD_TARGET_CLASS, null, Type.class);
String targetMethod = AnnotationUtil.getAnnotationParameter(an, FIELD_TARGET_METHOD, null, String.class);
String desc = (targetClass == null) ? mn.desc :
MethodUtil.addParameterAtBegin(mn.desc, ClassUtil.toByteCodeClassName(targetClass.getClassName()));
MethodUtil.addParameterAtBegin(mn.desc, ClassUtil.toByteCodeClassName(targetClass.getClassName()));
String name = (targetMethod == null) ? mn.name : targetMethod;
MethodNode mockMethod = new MethodNode(ACC_PUBLIC, name, desc, null, null);
List<Byte> parameters = MethodUtil.getParameterTypes(mn.desc);
int maxStack = 2;
InsnList il = new InsnList();
il.add(new VarInsnNode(ALOAD, 0));
il.add(new FieldInsnNode(GETFIELD, ClassUtil.toSlashSeparatedName(cn.name), fieldName, ClassUtil.toByteCodeClassName(className)));
il.add(new MethodInsnNode(INVOKESTATIC, ClassUtil.toSlashSeparatedName(className),
GET_TESTABLE_REF, VOID_ARGS + ClassUtil.toByteCodeClassName(className), false));
il.add(new VarInsnNode(ALOAD, 1));
for (int pi = 2; pi < parameters.size() + 2; pi++) {
ImmutablePair<Integer, Integer> codeAndStack = BytecodeUtil.getLoadParameterByteCode(parameters.get(pi - 2));

View File

@@ -13,11 +13,11 @@ import org.objectweb.asm.tree.InnerClassNode;
import org.objectweb.asm.tree.MethodNode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.alibaba.testable.agent.constant.ByteCodeConst.TYPE_CLASS;
import static com.alibaba.testable.agent.constant.ConstPool.CLASS_OBJECT;
import static com.alibaba.testable.agent.constant.ConstPool.KOTLIN_POSTFIX_COMPANION;
import static com.alibaba.testable.agent.constant.ConstPool.*;
import static com.alibaba.testable.agent.util.ClassUtil.toJavaStyleClassName;
import static com.alibaba.testable.agent.util.MethodUtil.isStatic;
import static com.alibaba.testable.core.constant.ConstPool.CONSTRUCTOR;
@@ -39,6 +39,7 @@ public class MockClassParser {
for (MethodNode mn : getAllMethods(cn)) {
addMethodWithAnnotationCheck(methodInfos, cn, mn);
}
handleMockContainerInherits(methodInfos, cn);
return methodInfos;
}
@@ -92,6 +93,30 @@ public class MockClassParser {
return mns;
}
/**
* Take care of @MockContainer annotation
*/
private void handleMockContainerInherits(List<MethodInfo> methodInfos, ClassNode cn) {
if (cn.visibleAnnotations != null) {
for (AnnotationNode an : cn.visibleAnnotations) {
if ((ClassUtil.toByteCodeClassName(ConstPool.MOCK_CONTAINER)).equals(an.desc)) {
for (Object st : AnnotationUtil.getAnnotationParameter(an, FIELD_INHERITS,
Collections.<Type>emptyList(), List.class)) {
String superClassName = ((Type)st).getClassName();
ClassNode superCn = ClassUtil.getClassNode(superClassName);
if (superCn == null) {
LogUtil.warn("failed to load class '%s' inherited by '%s'", superClassName, cn.name);
continue;
}
for (MethodNode mn : getAllMethods(superCn)) {
addMethodWithAnnotationCheck(methodInfos, cn, mn);
}
}
}
}
}
}
private void addMethodWithAnnotationCheck(List<MethodInfo> methodInfos, ClassNode cn, MethodNode mn) {
if (mn.visibleAnnotations == null) {
return;