allow modify static final field

This commit is contained in:
金戟 2021-07-14 21:29:32 +08:00
parent 93ad1fa94f
commit a78931ae81
6 changed files with 28 additions and 5 deletions

View File

@ -20,6 +20,7 @@
| mock.target.checking.enable | 是否启用Mock目标有效性的前置检查 | 可用值为:`true` / `false`,当前默认值为`false` |
| omni.constructor.enhance.enable | 是否启用`OmniConstructor`的字节码增强模式 | 可用值为:`true` / `false` |
| omni.constructor.enhance.pkgPrefix.excludes | 对特定包禁用`OmniConstructor`的字节码增强模式 | 使用`,`分隔的包路径前缀列表,例如:`com.demo.model` |
| private.access.enhance.enable | 是否启用`PrivateAccessor`的字节码增强模式 | 可用值为:`true` / `false` |
| thread.pool.enhance.enable | 是否启用基于`TransmittableThreadLocal`的Mock上下文存储 | 可用值为:`true` / `false` |
参见`demo`目录各示例项目中的`testable.properties`文件。

View File

@ -28,6 +28,7 @@ public class PropertiesParser {
private static final String DEFAULT_MOCK_SCOPE = "mock.scope.default";
private static final String ENABLE_MOCK_TARGET_CHECK = "mock.target.checking.enable";
private static final String ENABLE_OMNI_INJECT = "omni.constructor.enhance.enable";
private static final String ENABLE_FINAL_INJECT = "private.access.enhance.enable";
private static final String ENABLE_THREAD_POOL = "thread.pool.enhance.enable";
public static void parseFile(String configFilePath) {
@ -75,6 +76,8 @@ public class PropertiesParser {
GlobalConfig.enhanceOmniConstructor = Boolean.parseBoolean(v);
} else if (k.equals(ENABLE_MOCK_INJECT)) {
GlobalConfig.enhanceMock = Boolean.parseBoolean(v);
} else if (k.equals(ENABLE_FINAL_INJECT)) {
GlobalConfig.enhanceFinal = Boolean.parseBoolean(v);
} else if (k.equals(ENABLE_MOCK_TARGET_CHECK)) {
GlobalConfig.checkMockTargetExistence = Boolean.parseBoolean(v);
} else if (k.equals(ENABLE_THREAD_POOL)) {

View File

@ -0,0 +1,20 @@
package com.alibaba.testable.agent.handler;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldNode;
/**
* @author flin
*/
public class FinalFieldClassHandler extends BaseClassHandler {
@Override
protected void transform(ClassNode cn) {
if ((cn.access & ACC_INTERFACE) == 0) {
for (FieldNode field : cn.fields) {
field.access &= ~ACC_FINAL;
}
}
}
}

View File

@ -1,10 +1,7 @@
package com.alibaba.testable.agent.transformer;
import com.alibaba.testable.agent.constant.ConstPool;
import com.alibaba.testable.agent.handler.MockClassHandler;
import com.alibaba.testable.agent.handler.OmniClassHandler;
import com.alibaba.testable.agent.handler.SourceClassHandler;
import com.alibaba.testable.agent.handler.TestClassHandler;
import com.alibaba.testable.agent.handler.*;
import com.alibaba.testable.agent.handler.test.Framework;
import com.alibaba.testable.agent.model.MethodInfo;
import com.alibaba.testable.agent.util.*;
@ -55,6 +52,7 @@ public class TestableClassTransformer implements ClassFileTransformer {
}
byte[] bytes = GlobalConfig.enhanceOmniConstructor ?
new OmniClassHandler().getBytes(classFileBuffer) : classFileBuffer;
bytes = GlobalConfig.enhanceFinal ? new FinalFieldClassHandler().getBytes(bytes) : bytes;
if (GlobalConfig.enhanceMock) {
ClassNode cn = ClassUtil.getClassNode(className);
if (cn != null) {

View File

@ -35,6 +35,7 @@ public class GlobalConfig {
private static String[] pkgPrefixBlackList = null;
private static Map<String, String> mockPkgMapping = null;
public static MockScope defaultMockScope = MockScope.GLOBAL;
public static boolean enhanceFinal = false;
public static boolean enhanceMock = true;
public static boolean enhanceOmniConstructor = false;
public static boolean enhanceThreadLocal = false;

View File

@ -226,7 +226,7 @@ public class OmniConstructor {
}
private static Object createInstance(Class<?> clazz, Set<Class<?>> classPool)
throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
throws InstantiationException, IllegalAccessException, InvocationTargetException {
Constructor<?> constructor = getBestConstructor(clazz);
if (constructor == null) {
throw new ClassConstructionException("Fail to invoke constructor of " + clazz.getName());