suggest use MockDiagnose to set log level

This commit is contained in:
金戟 2021-02-16 10:47:18 +08:00
parent 9eb8682ec0
commit be53ea2d9c
5 changed files with 63 additions and 15 deletions

View File

@ -17,6 +17,7 @@ public class ConstPool {
public static final String FIELD_TARGET_CLASS = "targetClass";
public static final String MOCK_WITH = "com.alibaba.testable.core.annotation.MockWith";
public static final String MOCK_DIAGNOSE = "com.alibaba.testable.core.annotation.MockDiagnose";
public static final String MOCK_METHOD = "com.alibaba.testable.core.annotation.MockMethod";
public static final String MOCK_CONSTRUCTOR = "com.alibaba.testable.core.annotation.MockConstructor";

View File

@ -11,7 +11,7 @@ import com.alibaba.testable.agent.util.ClassUtil;
import com.alibaba.testable.agent.util.GlobalConfig;
import com.alibaba.testable.agent.util.StringUtil;
import com.alibaba.testable.core.model.ClassType;
import com.alibaba.testable.core.model.MockDiagnose;
import com.alibaba.testable.core.model.LogLevel;
import com.alibaba.testable.core.util.LogUtil;
import com.alibaba.testable.core.util.MockContextUtil;
import org.objectweb.asm.ClassReader;
@ -48,12 +48,11 @@ public class TestableClassTransformer implements ClassFileTransformer {
private static final String CLASS_OBJECT = "java/lang/Object";
/**
* Just avoid spend time to scan those surely non-user classes
* Should keep these lists as tiny as possible
* Just avoid spend time to scan those surely non-user classes Should keep these lists as tiny as possible
*/
private final String[] WHITELIST_PREFIXES = new String[] { "com/alibaba/testable/demo/" };
private final String[] BLACKLIST_PREFIXES = new String[] { "jdk/", "java/", "javax/", "com/sun/",
"org/apache/maven/", "com/alibaba/testable/", "junit/", "org/junit/", "org/testng/" };
private final String[] WHITELIST_PREFIXES = new String[] {"com/alibaba/testable/demo/"};
private final String[] BLACKLIST_PREFIXES = new String[] {"jdk/", "java/", "javax/", "com/sun/",
"org/apache/maven/", "com/alibaba/testable/", "junit/", "org/junit/", "org/testng/"};
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
@ -103,7 +102,8 @@ public class TestableClassTransformer implements ClassFileTransformer {
return;
}
try {
String dumpFile = StringUtil.joinPath(dumpDir, className.replace(SLASH, DOT).replace(DOLLAR, UNDERLINE) + ".class");
String dumpFile = StringUtil.joinPath(dumpDir,
className.replace(SLASH, DOT).replace(DOLLAR, UNDERLINE) + ".class");
LogUtil.verbose("Dump class: " + dumpFile);
FileOutputStream stream = new FileOutputStream(dumpFile);
stream.write(bytes);
@ -241,6 +241,7 @@ public class TestableClassTransformer implements ClassFileTransformer {
/**
* Read @MockWith annotation upon class to fetch mock class
*
* @param className class that need to explore
* @return name of mock class, null for not found
*/
@ -254,6 +255,7 @@ public class TestableClassTransformer implements ClassFileTransformer {
/**
* Read @MockWith annotation upon class and inner class "Mock" to fetch mock class
*
* @param className class that need to explore
* @return name of mock class, null for not found
*/
@ -283,14 +285,15 @@ public class TestableClassTransformer implements ClassFileTransformer {
/**
* Get mock class from @MockWith annotation
*
* @param cn class that may have @MockWith annotation
* @return mock class name
*/
private String parseMockWithAnnotation(ClassNode cn, ClassType expectedType) {
if (cn.visibleAnnotations != null) {
for (AnnotationNode an : cn.visibleAnnotations) {
setupDiagnose(an);
if (toDotSeparateFullClassName(an.desc).equals(ConstPool.MOCK_WITH)) {
setupDiagnose(an);
ClassType type = AnnotationUtil.getAnnotationParameter(an, FIELD_TREAT_AS, ClassType.GuessByName,
ClassType.class);
if (isExpectedType(cn.name, type, expectedType)) {
@ -316,6 +319,7 @@ public class TestableClassTransformer implements ClassFileTransformer {
/**
* Check whether any method in specified class has mock-related annotation
*
* @param className class that need to explore
* @return found annotation or not
*/
@ -324,6 +328,7 @@ public class TestableClassTransformer implements ClassFileTransformer {
if (cn == null) {
return false;
}
setupDiagnose(cn);
for (MethodNode mn : cn.methods) {
if (mn.visibleAnnotations != null) {
for (AnnotationNode an : mn.visibleAnnotations) {
@ -352,11 +357,29 @@ public class TestableClassTransformer implements ClassFileTransformer {
return cn;
}
private void setupDiagnose(ClassNode cn) {
if (cn.visibleAnnotations == null) {
return;
}
for (AnnotationNode an : cn.visibleAnnotations) {
setupDiagnose(an);
}
}
private void setupDiagnose(AnnotationNode an) {
MockDiagnose diagnose = AnnotationUtil.getAnnotationParameter(an, FIELD_DIAGNOSE, null, MockDiagnose.class);
if (diagnose != null) {
LogUtil.setLevel(diagnose == MockDiagnose.ENABLE ? LogUtil.LogLevel.LEVEL_DIAGNOSE :
(diagnose == MockDiagnose.VERBOSE ? LogUtil.LogLevel.LEVEL_VERBOSE : LogUtil.LogLevel.LEVEL_MUTE));
if (toDotSeparateFullClassName(an.desc).equals(MOCK_WITH)) {
setupDianose(an, FIELD_DIAGNOSE);
}
if (toDotSeparateFullClassName(an.desc).equals(ConstPool.MOCK_DIAGNOSE)) {
setupDianose(an, FIELD_VALUE);
}
}
private void setupDianose(AnnotationNode an, String fieldDiagnose) {
LogLevel level = AnnotationUtil.getAnnotationParameter(an, fieldDiagnose, null, LogLevel.class);
if (level != null) {
LogUtil.setLevel(level == LogLevel.ENABLE ? LogUtil.LogLevel.LEVEL_DIAGNOSE :
(level == LogLevel.VERBOSE ? LogUtil.LogLevel.LEVEL_VERBOSE : LogUtil.LogLevel.LEVEL_MUTE));
}
}

View File

@ -0,0 +1,23 @@
package com.alibaba.testable.core.annotation;
import com.alibaba.testable.core.model.LogLevel;
import java.lang.annotation.*;
/**
* Set extra mock parameter to test class
*
* @author flin
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
public @interface MockDiagnose {
/**
* switch of mock diagnose information of current test class
* @return enable or disable
*/
LogLevel value() default LogLevel.DISABLE;
}

View File

@ -1,7 +1,7 @@
package com.alibaba.testable.core.annotation;
import com.alibaba.testable.core.model.ClassType;
import com.alibaba.testable.core.model.MockDiagnose;
import com.alibaba.testable.core.model.LogLevel;
import javax.lang.model.type.NullType;
import java.lang.annotation.*;
@ -30,8 +30,9 @@ public @interface MockWith {
/**
* switch of mock diagnose information of current test class
* @deprecated to be removed in v0.6, use @MockDiagnose annotation instead
* @return enable or disable
*/
MockDiagnose diagnose() default MockDiagnose.DISABLE;
LogLevel diagnose() default LogLevel.DISABLE;
}

View File

@ -4,7 +4,7 @@ package com.alibaba.testable.core.model;
* @author flin
*/
public enum MockDiagnose {
public enum LogLevel {
/**
* Be quiet