mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-10 20:30:11 +08:00
support targetMethod parameter of TestableInject annotation
This commit is contained in:
parent
64227f1ed0
commit
c869caa0c9
@ -39,7 +39,7 @@ public class SourceClassHandler extends BaseClassHandler {
|
||||
for (MethodNode m : cn.methods) {
|
||||
// record all member method names
|
||||
if (!ConstPool.CONSTRUCTOR.equals(m.name)) {
|
||||
methods.add(new MethodInfo(cn.name, m.name, m.desc));
|
||||
methods.add(new MethodInfo(cn.name, m.name, null, m.desc));
|
||||
}
|
||||
}
|
||||
// member methods which has injection stub
|
||||
@ -59,18 +59,23 @@ public class SourceClassHandler extends BaseClassHandler {
|
||||
private void transformMethod(ClassNode cn, MethodNode mn, Set<MethodInfo> memberInjectMethods,
|
||||
Set<MethodInfo> newOperatorInjectMethods) {
|
||||
AbstractInsnNode[] instructions = mn.instructions.toArray();
|
||||
List<MethodInfo> memberInjectMethodList = new ArrayList<MethodInfo>(memberInjectMethods);
|
||||
int i = 0;
|
||||
do {
|
||||
if (invokeOps.contains(instructions[i].getOpcode())) {
|
||||
MethodInsnNode node = (MethodInsnNode)instructions[i];
|
||||
if (memberInjectMethods.contains(new MethodInfo(node.owner, node.name, node.desc))) {
|
||||
// it's a member method of current class and an inject method for it exist
|
||||
int index = memberInjectMethodList.indexOf(new MethodInfo(node.owner, node.name, null, node.desc));
|
||||
if (index >= 0) {
|
||||
// it's a member method and an inject method for it exist
|
||||
int rangeStart = getMemberMethodStart(instructions, i);
|
||||
if (rangeStart >= 0) {
|
||||
if (cn.name.equals(node.owner)) {
|
||||
// member method of current class
|
||||
instructions = replaceMemberCallOps(cn, mn, instructions, rangeStart, i);
|
||||
} else {
|
||||
instructions = replaceCommonCallOps(cn, mn, instructions, node.owner, rangeStart, i);
|
||||
// member method of other class
|
||||
String method = memberInjectMethodList.get(index).getSubstitutionMethod();
|
||||
instructions = replaceCommonCallOps(cn, mn, instructions, node.owner, method, rangeStart, i);
|
||||
}
|
||||
i = rangeStart;
|
||||
}
|
||||
@ -168,14 +173,14 @@ public class SourceClassHandler extends BaseClassHandler {
|
||||
}
|
||||
|
||||
private AbstractInsnNode[] replaceCommonCallOps(ClassNode cn, MethodNode mn, AbstractInsnNode[] instructions,
|
||||
String ownerClass, int start, int end) {
|
||||
String ownerClass, String substitutionMethod, int start, int end) {
|
||||
mn.maxStack++;
|
||||
MethodInsnNode method = (MethodInsnNode)instructions[end];
|
||||
String testClassName = ClassUtil.getTestClassName(cn.name);
|
||||
mn.instructions.insertBefore(instructions[start], new FieldInsnNode(GETSTATIC, testClassName,
|
||||
ConstPool.TESTABLE_INJECT_REF, ClassUtil.toByteCodeClassName(testClassName)));
|
||||
mn.instructions.insertBefore(instructions[end], new MethodInsnNode(INVOKEVIRTUAL, testClassName,
|
||||
method.name, addFirstParameter(method.desc, ownerClass), false));
|
||||
substitutionMethod, addFirstParameter(method.desc, ownerClass), false));
|
||||
mn.instructions.remove(instructions[end]);
|
||||
return mn.instructions.toArray();
|
||||
}
|
||||
|
@ -5,13 +5,28 @@ package com.alibaba.testable.agent.model;
|
||||
*/
|
||||
public class MethodInfo {
|
||||
|
||||
/**
|
||||
* name of the class this method belongs to
|
||||
*/
|
||||
private final String clazz;
|
||||
/**
|
||||
* name of the method
|
||||
*/
|
||||
private final String name;
|
||||
/**
|
||||
* name of the substitution method
|
||||
* Note: this field do NOT join the `equals()` or `hashCode()` calculation
|
||||
*/
|
||||
private final String substitutionMethod;
|
||||
/**
|
||||
* parameter and return value of the method
|
||||
*/
|
||||
private final String desc;
|
||||
|
||||
public MethodInfo(String clazz, String name, String desc) {
|
||||
public MethodInfo(String clazz, String name, String substitutionMethod, String desc) {
|
||||
this.clazz = clazz;
|
||||
this.name = name;
|
||||
this.substitutionMethod = substitutionMethod;
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
@ -23,6 +38,10 @@ public class MethodInfo {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getSubstitutionMethod() {
|
||||
return substitutionMethod;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
@ -86,12 +86,15 @@ public class TestableClassTransformer implements ClassFileTransformer {
|
||||
String targetClass = getAnnotationParameter(an, TARGET_CLASS, sourceClassName);
|
||||
String targetMethod = getAnnotationParameter(an, TARGET_METHOD, mn.name);
|
||||
if (sourceClassName.equals(targetClass)) {
|
||||
methodInfos.add(new MethodInfo(toSlashSeparatedName(targetClass), targetMethod, mn.desc));
|
||||
// member method of the source class
|
||||
methodInfos.add(new MethodInfo(
|
||||
toSlashSeparatedName(targetClass), targetMethod, null, mn.desc));
|
||||
} else {
|
||||
// member method of a common class
|
||||
ImmutablePair<String, String> methodDescPair = extractFirstParameter(mn.desc);
|
||||
if (methodDescPair != null && methodDescPair.left.equals(ClassUtil.toByteCodeClassName(targetClass))) {
|
||||
methodInfos.add(new MethodInfo(
|
||||
toSlashSeparatedName(targetClass), targetMethod, methodDescPair.right));
|
||||
toSlashSeparatedName(targetClass), targetMethod, mn.name, methodDescPair.right));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user