mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-09 20:00:21 +08:00
fix an omni constructor issue caused by array-in-array type
This commit is contained in:
parent
338c7828c8
commit
db771b9c66
@ -7,7 +7,9 @@ import com.alibaba.testable.agent.util.CollectionUtil;
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.tree.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.alibaba.testable.agent.util.ClassUtil.CLASS_OBJECT;
|
||||
import static com.alibaba.testable.core.constant.ConstPool.CONSTRUCTOR;
|
||||
@ -25,10 +27,14 @@ public class OmniClassHandler extends BaseClassHandler {
|
||||
private static final String VOID_METHOD = "()V";
|
||||
private static final String ENABLE_CONFIGURATION = "Lorg/springframework/context/annotation/Configuration;";
|
||||
private static final String CLASS_ABSTRACT_COLLECTION = "java/util/AbstractCollection";
|
||||
private static final String CLASS_NUMBER = "java/lang/Number";
|
||||
|
||||
private static final String[] JUNIT_TEST_ANNOTATIONS = new String[] {
|
||||
JUnit4Framework.ANNOTATION_TEST, JUnit5Framework.ANNOTATION_TEST, JUnit5Framework.ANNOTATION_PARAMETERIZED_TEST
|
||||
};
|
||||
private static final Set<String> UNREACHABLE_CLASSES = new HashSet<String>() {{
|
||||
add(CLASS_ABSTRACT_COLLECTION); add(CLASS_NUMBER);
|
||||
}};
|
||||
|
||||
@Override
|
||||
protected void transform(ClassNode cn) {
|
||||
@ -114,7 +120,7 @@ public class OmniClassHandler extends BaseClassHandler {
|
||||
InsnList il = new InsnList();
|
||||
il.add(start);
|
||||
il.add(new VarInsnNode(ALOAD, 0));
|
||||
if (cn.superName.equals(CLASS_ABSTRACT_COLLECTION)) {
|
||||
if (UNREACHABLE_CLASSES.contains(cn.superName)) {
|
||||
il.add(new MethodInsnNode(INVOKESPECIAL, cn.superName, CONSTRUCTOR, VOID_METHOD, false));
|
||||
} else {
|
||||
il.add(new VarInsnNode(ALOAD, 1));
|
||||
|
@ -39,7 +39,8 @@ public class TestableClassTransformer implements ClassFileTransformer {
|
||||
/**
|
||||
* Just avoid spend time to scan those surely non-user classes, should keep these lists as tiny as possible
|
||||
*/
|
||||
private final String[] BLACKLIST_PREFIXES = new String[] { "sun/", "com/sun/", "javax/crypto", "org/gradle/" };
|
||||
private final String[] BLACKLIST_PREFIXES = new String[] { "sun/", "com/sun/", "javax/crypto", "java/util/logging",
|
||||
"org/gradle/" };
|
||||
|
||||
public MockClassParser mockClassParser = new MockClassParser();
|
||||
|
||||
|
@ -15,6 +15,7 @@ import static com.alibaba.testable.core.constant.ConstPool.DOLLAR;
|
||||
public class OmniConstructor {
|
||||
|
||||
private static final int INITIAL_CAPACITY = 6;
|
||||
private static final int FIRST = 1;
|
||||
|
||||
private OmniConstructor() {}
|
||||
|
||||
@ -155,7 +156,7 @@ public class OmniConstructor {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static <T> void handleCircleReference(T instance, Class<?> type, Map<Class<?>, Object> classPool)
|
||||
private static void handleCircleReference(Object instance, Class<?> type, Map<Class<?>, Object> classPool)
|
||||
throws IllegalAccessException {
|
||||
if (instance == null) {
|
||||
// don't travel null object
|
||||
@ -173,13 +174,11 @@ public class OmniConstructor {
|
||||
Class<?> fieldType = f.getType();
|
||||
if (fieldType.isArray()) {
|
||||
Class<?> componentType = fieldType.getComponentType();
|
||||
if (fieldIns != null && !componentType.isPrimitive() && !TypeUtil.isBasicType(componentType)) {
|
||||
if (fieldIns != null && !TypeUtil.isBasicType(componentType)) {
|
||||
LogUtil.verbose(classPool.size(), "Field(Array[%d]) %s", Array.getLength(fieldIns), f.getName());
|
||||
for (int i = 0; i < Math.min(Array.getLength(fieldIns), 10); i++) {
|
||||
handleCircleReference(Array.get(fieldIns, i), componentType, classPool);
|
||||
handleCircleReferenceOfArrayField(fieldIns, componentType, classPool);
|
||||
}
|
||||
}
|
||||
} else if (!fieldType.isPrimitive() && !TypeUtil.isBasicType(fieldType)) {
|
||||
} else if (!TypeUtil.isBasicType(fieldType)) {
|
||||
if (fieldIns == null && classPool.containsKey(fieldType)) {
|
||||
f.set(instance, classPool.get(fieldType));
|
||||
} else if (!classPool.containsKey(fieldType)) {
|
||||
@ -191,6 +190,22 @@ public class OmniConstructor {
|
||||
classPool.remove(type);
|
||||
}
|
||||
|
||||
private static void handleCircleReferenceOfArrayField(Object instance, Class<?> type, Map<Class<?>, Object> classPool)
|
||||
throws IllegalAccessException {
|
||||
if (type.isArray()) {
|
||||
for (int i = 0; i < Math.min(Array.getLength(instance), FIRST); i++) {
|
||||
Object arrayIns = Array.get(instance, i);
|
||||
if (arrayIns != null) {
|
||||
handleCircleReferenceOfArrayField(arrayIns, arrayIns.getClass().getComponentType(), classPool);
|
||||
}
|
||||
}
|
||||
} else if (!classPool.containsKey(type)) {
|
||||
for (int i = 0; i < Math.min(Array.getLength(instance), FIRST); i++) {
|
||||
handleCircleReference(Array.get(instance, i), type, classPool);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Object createInstance(Class<?> clazz, Set<Class<?>> classPool)
|
||||
throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
||||
Constructor<?> constructor = getBestConstructor(clazz);
|
||||
|
@ -105,10 +105,10 @@ public class TypeUtil {
|
||||
* @param clazz type to check
|
||||
*/
|
||||
public static boolean isBasicType(Class<?> clazz) {
|
||||
return clazz.isEnum() || clazz.equals(Integer.class) || clazz.equals(Short.class) || clazz.equals(Long.class)
|
||||
|| clazz.equals(Byte.class) || clazz.equals(Character.class) || clazz.equals(Float.class)
|
||||
|| clazz.equals(Double.class) || clazz.equals(Boolean.class) || clazz.equals(Class.class)
|
||||
|| clazz.equals(String.class) || clazz.equals(Date.class);
|
||||
return clazz.isPrimitive() || clazz.isEnum() || clazz.equals(Integer.class) || clazz.equals(Short.class)
|
||||
|| clazz.equals(Long.class) || clazz.equals(Byte.class) || clazz.equals(Character.class)
|
||||
|| clazz.equals(Float.class) || clazz.equals(Double.class) || clazz.equals(Boolean.class)
|
||||
|| clazz.equals(Class.class) || clazz.equals(String.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user