mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-25 20:00:17 +08:00
refactor and reduce stack size
This commit is contained in:
parent
bdd99577c4
commit
65cc631d39
@ -0,0 +1,19 @@
|
||||
package com.alibaba.testable.agent.constant;
|
||||
|
||||
public class ByteCodeConst {
|
||||
|
||||
public static final byte TYPE_BYTE = 'B';
|
||||
public static final byte TYPE_CHAR = 'C';
|
||||
public static final byte TYPE_DOUBLE = 'D';
|
||||
public static final byte TYPE_FLOAT = 'F';
|
||||
public static final byte TYPE_INT = 'I';
|
||||
public static final byte TYPE_LONG = 'J';
|
||||
public static final byte TYPE_CLASS = 'L';
|
||||
public static final byte TYPE_SHORT = 'S';
|
||||
public static final byte TYPE_BOOL = 'Z';
|
||||
public static final byte TYPE_VOID = 'V';
|
||||
public static final byte PARAM_END = ')';
|
||||
public static final byte CLASS_END = ';';
|
||||
public static final byte TYPE_ARRAY = '[';
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package com.alibaba.testable.agent.handler;
|
||||
|
||||
import com.alibaba.testable.agent.constant.ByteCodeConst;
|
||||
import com.alibaba.testable.agent.constant.ConstPool;
|
||||
import com.alibaba.testable.agent.tool.ImmutablePair;
|
||||
import com.alibaba.testable.agent.util.AnnotationUtil;
|
||||
@ -92,7 +93,7 @@ public class MockClassHandler extends BaseClassWithContextHandler {
|
||||
if (targetClassName != null) {
|
||||
// must get label before method description changed
|
||||
ImmutablePair<LabelNode, LabelNode> labels = getStartAndEndLabel(mn);
|
||||
mn.desc = ClassUtil.addParameterAtBegin(mn.desc, targetClassName);
|
||||
mn.desc = MethodUtil.addParameterAtBegin(mn.desc, targetClassName);
|
||||
int parameterOffset = MethodUtil.isStaticMethod(mn) ? 0 : 1;
|
||||
mn.localVariables.add(parameterOffset, new LocalVariableNode("__self", targetClassName, null,
|
||||
labels.left, labels.right, parameterOffset));
|
||||
@ -121,7 +122,7 @@ public class MockClassHandler extends BaseClassWithContextHandler {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ClassUtil.extractParameters(mn.desc).isEmpty()) {
|
||||
if (MethodUtil.extractParameters(mn.desc).isEmpty()) {
|
||||
// for method without parameter, should manually add a ending label
|
||||
endLabel = new LabelNode(new Label());
|
||||
mn.instructions.add(endLabel);
|
||||
@ -158,14 +159,13 @@ public class MockClassHandler extends BaseClassWithContextHandler {
|
||||
|
||||
private InsnList invokeOriginalMethod(MethodNode mn) {
|
||||
InsnList il = new InsnList();
|
||||
mn.maxStack += 3;
|
||||
ImmutablePair<Type, String> target = getTargetClassAndMethodName(mn);
|
||||
il.add(new LdcInsnNode(target.left));
|
||||
il.add(new LdcInsnNode(target.right));
|
||||
il.add(duplicateParameters(mn));
|
||||
il.add(new MethodInsnNode(INVOKESTATIC, CLASS_MOCK_ASSOCIATION_UTIL, METHOD_INVOKE_ORIGIN,
|
||||
SIGNATURE_INVOKE_ORIGIN, false));
|
||||
String returnType = ClassUtil.getReturnType(mn.desc);
|
||||
String returnType = MethodUtil.getReturnType(mn.desc);
|
||||
if (VOID_RES.equals(returnType)) {
|
||||
il.add(new InsnNode(POP));
|
||||
il.add(new InsnNode(RETURN));
|
||||
@ -197,9 +197,9 @@ public class MockClassHandler extends BaseClassWithContextHandler {
|
||||
}
|
||||
}
|
||||
if (methodName.equals(CONSTRUCTOR)) {
|
||||
className = Type.getType(ClassUtil.getReturnType(mn.desc));
|
||||
className = Type.getType(MethodUtil.getReturnType(mn.desc));
|
||||
} else {
|
||||
className = Type.getType(ClassUtil.getFirstParameter(mn.desc));
|
||||
className = Type.getType(MethodUtil.getFirstParameter(mn.desc));
|
||||
}
|
||||
return ImmutablePair.of(className, methodName);
|
||||
}
|
||||
@ -233,7 +233,6 @@ public class MockClassHandler extends BaseClassWithContextHandler {
|
||||
|
||||
private void injectInvokeRecorder(MethodNode mn) {
|
||||
InsnList il = new InsnList();
|
||||
mn.maxStack += 2;
|
||||
il.add(duplicateParameters(mn));
|
||||
if (isMockForConstructor(mn)) {
|
||||
il.add(new InsnNode(ICONST_1));
|
||||
@ -243,17 +242,17 @@ public class MockClassHandler extends BaseClassWithContextHandler {
|
||||
il.add(new MethodInsnNode(INVOKESTATIC, CLASS_INVOKE_RECORD_UTIL, METHOD_RECORD_MOCK_INVOKE,
|
||||
SIGNATURE_RECORDER_METHOD_INVOKE, false));
|
||||
mn.instructions.insertBefore(mn.instructions.getFirst(), il);
|
||||
mn.maxStack += (2 + MethodUtil.getParameterTypes(mn.desc).size() * 3);
|
||||
}
|
||||
|
||||
private InsnList duplicateParameters(MethodNode mn) {
|
||||
InsnList il = new InsnList();
|
||||
List<Byte> types = ClassUtil.getParameterTypes(mn.desc);
|
||||
List<Byte> types = MethodUtil.getParameterTypes(mn.desc);
|
||||
int size = types.size();
|
||||
il.add(getIntInsn(size));
|
||||
il.add(new TypeInsnNode(ANEWARRAY, ClassUtil.CLASS_OBJECT));
|
||||
int parameterOffset = MethodUtil.isStaticMethod(mn) ? 0 : 1;
|
||||
for (int i = 0; i < size; i++) {
|
||||
mn.maxStack += 3;
|
||||
il.add(new InsnNode(DUP));
|
||||
il.add(getIntInsn(i));
|
||||
ImmutablePair<Integer, Integer> code = getLoadParameterByteCode(types.get(i));
|
||||
@ -286,17 +285,17 @@ public class MockClassHandler extends BaseClassWithContextHandler {
|
||||
|
||||
private static ImmutablePair<Integer, Integer> getLoadParameterByteCode(Byte type) {
|
||||
switch (type) {
|
||||
case ClassUtil.TYPE_BYTE:
|
||||
case ClassUtil.TYPE_CHAR:
|
||||
case ClassUtil.TYPE_SHORT:
|
||||
case ClassUtil.TYPE_INT:
|
||||
case ClassUtil.TYPE_BOOL:
|
||||
case ByteCodeConst.TYPE_BYTE:
|
||||
case ByteCodeConst.TYPE_CHAR:
|
||||
case ByteCodeConst.TYPE_SHORT:
|
||||
case ByteCodeConst.TYPE_INT:
|
||||
case ByteCodeConst.TYPE_BOOL:
|
||||
return ImmutablePair.of(ILOAD, 1);
|
||||
case ClassUtil.TYPE_DOUBLE:
|
||||
case ByteCodeConst.TYPE_DOUBLE:
|
||||
return ImmutablePair.of(DLOAD, 2);
|
||||
case ClassUtil.TYPE_FLOAT:
|
||||
case ByteCodeConst.TYPE_FLOAT:
|
||||
return ImmutablePair.of(FLOAD, 1);
|
||||
case ClassUtil.TYPE_LONG:
|
||||
case ByteCodeConst.TYPE_LONG:
|
||||
return ImmutablePair.of(LLOAD, 2);
|
||||
default:
|
||||
return ImmutablePair.of(ALOAD, 1);
|
||||
|
@ -4,6 +4,7 @@ import com.alibaba.testable.agent.model.MethodInfo;
|
||||
import com.alibaba.testable.agent.model.ModifiedInsnNodes;
|
||||
import com.alibaba.testable.agent.util.BytecodeUtil;
|
||||
import com.alibaba.testable.agent.util.ClassUtil;
|
||||
import com.alibaba.testable.agent.util.MethodUtil;
|
||||
import com.alibaba.testable.core.util.LogUtil;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.*;
|
||||
@ -115,7 +116,7 @@ public class SourceClassHandler extends BaseClassHandler {
|
||||
String nodeOwner = ClassUtil.fitCompanionClassName(node.owner);
|
||||
String nodeName = ClassUtil.fitKotlinAccessorName(node.name);
|
||||
// Kotlin accessor method will append a extra type parameter
|
||||
String nodeDesc = nodeName.equals(node.name) ? node.desc : ClassUtil.removeFirstParameter(node.desc);
|
||||
String nodeDesc = nodeName.equals(node.name) ? node.desc : MethodUtil.removeFirstParameter(node.desc);
|
||||
if (m.getClazz().equals(nodeOwner) && m.getName().equals(nodeName) && m.getDesc().equals(nodeDesc)) {
|
||||
return m;
|
||||
}
|
||||
@ -161,7 +162,7 @@ public class SourceClassHandler extends BaseClassHandler {
|
||||
}
|
||||
|
||||
private int getInitialStackLevel(MethodInsnNode instruction) {
|
||||
int stackLevel = ClassUtil.getParameterTypes((instruction).desc).size();
|
||||
int stackLevel = MethodUtil.getParameterTypes((instruction).desc).size();
|
||||
switch (instruction.getOpcode()) {
|
||||
case Opcodes.INVOKESPECIAL:
|
||||
case Opcodes.INVOKEVIRTUAL:
|
||||
@ -194,7 +195,7 @@ public class SourceClassHandler extends BaseClassHandler {
|
||||
}
|
||||
|
||||
private int stackEffectOfInvocation(String desc) {
|
||||
return ClassUtil.getParameterTypes(desc).size() - (ClassUtil.getReturnType(desc).equals(VOID_RES) ? 0 : 1);
|
||||
return MethodUtil.getParameterTypes(desc).size() - (MethodUtil.getReturnType(desc).equals(VOID_RES) ? 0 : 1);
|
||||
}
|
||||
|
||||
private ModifiedInsnNodes replaceNewOps(MethodNode mn, MethodInfo newOperatorInjectMethod,
|
||||
|
@ -6,6 +6,7 @@ import com.alibaba.testable.agent.tool.ImmutablePair;
|
||||
import com.alibaba.testable.agent.util.AnnotationUtil;
|
||||
import com.alibaba.testable.agent.util.ClassUtil;
|
||||
import com.alibaba.testable.agent.util.DiagnoseUtil;
|
||||
import com.alibaba.testable.agent.util.MethodUtil;
|
||||
import com.alibaba.testable.core.util.LogUtil;
|
||||
import com.alibaba.testable.core.util.MockAssociationUtil;
|
||||
import org.objectweb.asm.Type;
|
||||
@ -92,7 +93,7 @@ public class MockClassParser {
|
||||
String fullClassName = toDotSeparateFullClassName(an.desc);
|
||||
if (fullClassName.equals(ConstPool.MOCK_CONSTRUCTOR)) {
|
||||
LogUtil.verbose(" Mock constructor \"%s\" as \"(%s)V\" for \"%s\"", mn.name,
|
||||
ClassUtil.extractParameters(mn.desc), ClassUtil.getReturnType(mn.desc));
|
||||
MethodUtil.extractParameters(mn.desc), MethodUtil.getReturnType(mn.desc));
|
||||
addMockConstructor(methodInfos, cn, mn);
|
||||
} else if (fullClassName.equals(ConstPool.MOCK_METHOD)) {
|
||||
LogUtil.verbose(" Mock method \"%s\" as \"%s\"", mn.name, getTargetMethodDesc(mn, an));
|
||||
@ -114,7 +115,7 @@ public class MockClassParser {
|
||||
private String getTargetMethodDesc(MethodNode mn, AnnotationNode mockMethodAnnotation) {
|
||||
Type type = AnnotationUtil.getAnnotationParameter(mockMethodAnnotation, ConstPool.FIELD_TARGET_CLASS,
|
||||
null, Type.class);
|
||||
return type == null ? ClassUtil.removeFirstParameter(mn.desc) : mn.desc;
|
||||
return type == null ? MethodUtil.removeFirstParameter(mn.desc) : mn.desc;
|
||||
}
|
||||
|
||||
private MethodInfo getMethodInfo(MethodNode mn, AnnotationNode an, String targetMethod) {
|
||||
@ -131,7 +132,7 @@ public class MockClassParser {
|
||||
// "targetClass" found, use it as target class type
|
||||
String slashSeparatedName = ClassUtil.toSlashSeparatedName(targetType.getClassName());
|
||||
return new MethodInfo(slashSeparatedName, targetMethod, mn.desc, mn.name,
|
||||
ClassUtil.addParameterAtBegin(mn.desc, ClassUtil.toByteCodeClassName(slashSeparatedName)), isStatic);
|
||||
MethodUtil.addParameterAtBegin(mn.desc, ClassUtil.toByteCodeClassName(slashSeparatedName)), isStatic);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,11 +7,10 @@ import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.alibaba.testable.agent.constant.ByteCodeConst.*;
|
||||
import static com.alibaba.testable.core.constant.ConstPool.MOCK_POSTFIX;
|
||||
import static com.alibaba.testable.core.constant.ConstPool.TEST_POSTFIX;
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
@ -21,20 +20,6 @@ import static org.objectweb.asm.Opcodes.*;
|
||||
*/
|
||||
public class ClassUtil {
|
||||
|
||||
public static final byte TYPE_BYTE = 'B';
|
||||
public static final byte TYPE_CHAR = 'C';
|
||||
public static final byte TYPE_DOUBLE = 'D';
|
||||
public static final byte TYPE_FLOAT = 'F';
|
||||
public static final byte TYPE_INT = 'I';
|
||||
public static final byte TYPE_LONG = 'J';
|
||||
public static final byte TYPE_CLASS = 'L';
|
||||
public static final byte TYPE_SHORT = 'S';
|
||||
public static final byte TYPE_BOOL = 'Z';
|
||||
public static final byte TYPE_VOID = 'V';
|
||||
private static final byte PARAM_END = ')';
|
||||
private static final byte CLASS_END = ';';
|
||||
private static final byte TYPE_ARRAY = '[';
|
||||
|
||||
public static final String CLASS_OBJECT = "java/lang/Object";
|
||||
private static final String CLASS_BYTE = "java/lang/Byte";
|
||||
private static final String CLASS_CHARACTER = "java/lang/Character";
|
||||
@ -150,69 +135,6 @@ public class ClassUtil {
|
||||
return testClassName.substring(0, testClassName.length() - TEST_POSTFIX.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* parse method desc, fetch parameter types
|
||||
* @param desc method description
|
||||
* @return list of parameter types
|
||||
*/
|
||||
public static List<Byte> getParameterTypes(String desc) {
|
||||
List<Byte> parameterTypes = new ArrayList<Byte>();
|
||||
boolean travelingClass = false;
|
||||
boolean travelingArray = false;
|
||||
for (byte b : desc.getBytes()) {
|
||||
if (travelingClass) {
|
||||
if (b == CLASS_END) {
|
||||
travelingClass = false;
|
||||
travelingArray = false;
|
||||
}
|
||||
} else {
|
||||
if (isPrimaryType(b)) {
|
||||
// should treat primary array as class (issue-48)
|
||||
parameterTypes.add(travelingArray ? TYPE_CLASS : b);
|
||||
travelingArray = false;
|
||||
} else if (b == TYPE_CLASS) {
|
||||
travelingClass = true;
|
||||
parameterTypes.add(b);
|
||||
} else if (b == TYPE_ARRAY) {
|
||||
travelingArray = true;
|
||||
} else if (b == PARAM_END) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return parameterTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract parameter part of method desc
|
||||
* @param desc method description
|
||||
* @return parameter value
|
||||
*/
|
||||
public static String extractParameters(String desc) {
|
||||
int returnTypeEdge = desc.lastIndexOf(PARAM_END);
|
||||
return desc.substring(1, returnTypeEdge);
|
||||
}
|
||||
|
||||
/**
|
||||
* parse method desc, fetch return value types
|
||||
* @param desc method description
|
||||
* @return types of return value
|
||||
*/
|
||||
public static String getReturnType(String desc) {
|
||||
int returnTypeEdge = desc.lastIndexOf(PARAM_END);
|
||||
return desc.substring(returnTypeEdge + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* parse method desc, fetch first parameter type
|
||||
* @param desc method description
|
||||
* @return types of first parameter
|
||||
*/
|
||||
public static String getFirstParameter(String desc) {
|
||||
int typeEdge = desc.indexOf(CLASS_END);
|
||||
return desc.substring(1, typeEdge + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* get wrapper class of specified private type
|
||||
* @param primaryType byte code of private type
|
||||
@ -279,15 +201,6 @@ public class ClassUtil {
|
||||
return (char)TYPE_CLASS + toSlashSeparatedName(className) + (char)CLASS_END;
|
||||
}
|
||||
|
||||
/**
|
||||
* convert byte code class name to slash separated human readable name
|
||||
* @param className original name
|
||||
* @return converted name
|
||||
*/
|
||||
public static String toSlashSeparateFullClassName(String className) {
|
||||
return className.substring(1, className.length() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* convert byte code class name to dot separated human readable name
|
||||
* @param className original name
|
||||
@ -297,25 +210,6 @@ public class ClassUtil {
|
||||
return toDotSeparatedName(className).substring(1, className.length() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove first parameter from method descriptor
|
||||
* @param desc original descriptor
|
||||
* @return descriptor without first parameter
|
||||
*/
|
||||
public static String removeFirstParameter(String desc) {
|
||||
return "(" + desc.substring(desc.indexOf(";") + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* add extra parameter to the beginning of method descriptor
|
||||
* @param desc original descriptor
|
||||
* @param type byte code class name
|
||||
* @return descriptor with specified parameter at begin
|
||||
*/
|
||||
public static String addParameterAtBegin(String desc, String type) {
|
||||
return "(" + type + desc.substring(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read class from current context
|
||||
* @param className class name
|
||||
@ -335,8 +229,4 @@ public class ClassUtil {
|
||||
return "(" + (char)type.byteValue() + ")L" + objectType + ";";
|
||||
}
|
||||
|
||||
private static boolean isPrimaryType(byte b) {
|
||||
return b == TYPE_BYTE || b == TYPE_CHAR || b == TYPE_DOUBLE || b == TYPE_FLOAT
|
||||
|| b == TYPE_INT || b == TYPE_LONG || b == TYPE_SHORT || b == TYPE_BOOL;
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,107 @@ package com.alibaba.testable.agent.util;
|
||||
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alibaba.testable.agent.constant.ByteCodeConst.*;
|
||||
import static org.objectweb.asm.Opcodes.ACC_STATIC;
|
||||
|
||||
public class MethodUtil {
|
||||
|
||||
/**
|
||||
* Judge whether a method is static
|
||||
* @param mn method to check
|
||||
* @return is static or not
|
||||
*/
|
||||
public static boolean isStaticMethod(MethodNode mn) {
|
||||
return (mn.access & ACC_STATIC) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse method desc, fetch parameter types
|
||||
* @param desc method description
|
||||
* @return list of parameter types
|
||||
*/
|
||||
public static List<Byte> getParameterTypes(String desc) {
|
||||
List<Byte> parameterTypes = new ArrayList<Byte>();
|
||||
boolean travelingClass = false;
|
||||
boolean travelingArray = false;
|
||||
for (byte b : desc.getBytes()) {
|
||||
if (travelingClass) {
|
||||
if (b == CLASS_END) {
|
||||
travelingClass = false;
|
||||
travelingArray = false;
|
||||
}
|
||||
} else {
|
||||
if (isPrimaryType(b)) {
|
||||
// should treat primary array as class (issue-48)
|
||||
parameterTypes.add(travelingArray ? TYPE_CLASS : b);
|
||||
travelingArray = false;
|
||||
} else if (b == TYPE_CLASS) {
|
||||
travelingClass = true;
|
||||
parameterTypes.add(b);
|
||||
} else if (b == TYPE_ARRAY) {
|
||||
travelingArray = true;
|
||||
} else if (b == PARAM_END) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return parameterTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* extract parameter part of method desc
|
||||
* @param desc method description
|
||||
* @return parameter value
|
||||
*/
|
||||
public static String extractParameters(String desc) {
|
||||
int returnTypeEdge = desc.lastIndexOf(PARAM_END);
|
||||
return desc.substring(1, returnTypeEdge);
|
||||
}
|
||||
|
||||
/**
|
||||
* parse method desc, fetch return value types
|
||||
* @param desc method description
|
||||
* @return types of return value
|
||||
*/
|
||||
public static String getReturnType(String desc) {
|
||||
int returnTypeEdge = desc.lastIndexOf(PARAM_END);
|
||||
return desc.substring(returnTypeEdge + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* parse method desc, fetch first parameter type
|
||||
* @param desc method description
|
||||
* @return types of first parameter
|
||||
*/
|
||||
public static String getFirstParameter(String desc) {
|
||||
int typeEdge = desc.indexOf(CLASS_END);
|
||||
return desc.substring(1, typeEdge + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove first parameter from method descriptor
|
||||
* @param desc original descriptor
|
||||
* @return descriptor without first parameter
|
||||
*/
|
||||
public static String removeFirstParameter(String desc) {
|
||||
return "(" + desc.substring(desc.indexOf(";") + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* add extra parameter to the beginning of method descriptor
|
||||
* @param desc original descriptor
|
||||
* @param type byte code class name
|
||||
* @return descriptor with specified parameter at begin
|
||||
*/
|
||||
public static String addParameterAtBegin(String desc, String type) {
|
||||
return "(" + type + desc.substring(1);
|
||||
}
|
||||
|
||||
private static boolean isPrimaryType(byte b) {
|
||||
return b == TYPE_BYTE || b == TYPE_CHAR || b == TYPE_DOUBLE || b == TYPE_FLOAT
|
||||
|| b == TYPE_INT || b == TYPE_LONG || b == TYPE_SHORT || b == TYPE_BOOL;
|
||||
}
|
||||
}
|
||||
|
@ -2,39 +2,10 @@ package com.alibaba.testable.agent.util;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class ClassUtilTest {
|
||||
|
||||
@Test
|
||||
void should_able_to_get_parameter_count() {
|
||||
assertEquals(0, ClassUtil.getParameterTypes("()V").size());
|
||||
assertEquals(1, ClassUtil.getParameterTypes("(Ljava/lang/String;)V").size());
|
||||
assertEquals(6, ClassUtil.getParameterTypes("(Ljava/lang/String;IDLjava/lang/String;ZLjava/net/URL;)V").size());
|
||||
assertEquals(10, ClassUtil.getParameterTypes("(ZLjava/lang/String;IJFDCSBZ)V").size());
|
||||
assertEquals(3, ClassUtil.getParameterTypes("(Ljava/lang/String;[I[Ljava/lang/String;)V").size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_extract_parameter() {
|
||||
assertEquals("", ClassUtil.extractParameters("()I"));
|
||||
assertEquals("Ljava/lang/String;", ClassUtil.extractParameters("(Ljava/lang/String;)I"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_get_return_type() {
|
||||
assertEquals("V", ClassUtil.getReturnType("(Ljava/lang/String;)V"));
|
||||
assertEquals("I", ClassUtil.getReturnType("(Ljava/lang/String;)I"));
|
||||
assertEquals("[I", ClassUtil.getReturnType("(Ljava/lang/String;)[I"));
|
||||
assertEquals("Ljava/lang/String;", ClassUtil.getReturnType("(Ljava/lang/String;)Ljava/lang/String;"));
|
||||
assertEquals("[Ljava/lang/String;", ClassUtil.getReturnType("(Ljava/lang/String;)[Ljava/lang/String;"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_get_first_parameter() {
|
||||
assertEquals("Ljava/lang/String;", ClassUtil.getFirstParameter("(Ljava/lang/String;Ljava/lang/Object;I)V"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_convert_class_name() {
|
||||
assertEquals("Ljava/lang/String;", ClassUtil.toByteCodeClassName("java.lang.String"));
|
||||
|
@ -0,0 +1,39 @@
|
||||
package com.alibaba.testable.agent.util;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
class MethodUtilTest {
|
||||
|
||||
@Test
|
||||
void should_able_to_get_parameter_count() {
|
||||
assertEquals(0, MethodUtil.getParameterTypes("()V").size());
|
||||
assertEquals(1, MethodUtil.getParameterTypes("(Ljava/lang/String;)V").size());
|
||||
assertEquals(6, MethodUtil.getParameterTypes("(Ljava/lang/String;IDLjava/lang/String;ZLjava/net/URL;)V").size());
|
||||
assertEquals(10, MethodUtil.getParameterTypes("(ZLjava/lang/String;IJFDCSBZ)V").size());
|
||||
assertEquals(3, MethodUtil.getParameterTypes("(Ljava/lang/String;[I[Ljava/lang/String;)V").size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_extract_parameter() {
|
||||
assertEquals("", MethodUtil.extractParameters("()I"));
|
||||
assertEquals("Ljava/lang/String;", MethodUtil.extractParameters("(Ljava/lang/String;)I"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_get_return_type() {
|
||||
assertEquals("V", MethodUtil.getReturnType("(Ljava/lang/String;)V"));
|
||||
assertEquals("I", MethodUtil.getReturnType("(Ljava/lang/String;)I"));
|
||||
assertEquals("[I", MethodUtil.getReturnType("(Ljava/lang/String;)[I"));
|
||||
assertEquals("Ljava/lang/String;", MethodUtil.getReturnType("(Ljava/lang/String;)Ljava/lang/String;"));
|
||||
assertEquals("[Ljava/lang/String;", MethodUtil.getReturnType("(Ljava/lang/String;)[Ljava/lang/String;"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_able_to_get_first_parameter() {
|
||||
assertEquals("Ljava/lang/String;", MethodUtil.getFirstParameter("(Ljava/lang/String;Ljava/lang/Object;I)V"));
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user