提交 240cacb4 编写于 作者: A ascrutae

add plugin test cases

上级 dfa0eead
......@@ -40,6 +40,12 @@
<artifactId>byte-buddy</artifactId>
<version>1.5.7</version>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>1.5.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
......
package com.a.eye.skywalking.api.plugin;
import com.a.eye.skywalking.api.plugin.utility.ClassFileExtraction;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ByteArrayClassLoader;
import net.bytebuddy.dynamic.loading.PackageDefinitionStrategy;
import net.bytebuddy.matcher.ElementMatchers;
import org.hamcrest.CoreMatchers;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.lang.instrument.ClassFileTransformer;
import static net.bytebuddy.matcher.ElementMatchers.is;
import static net.bytebuddy.matcher.ElementMatchers.none;
import static org.hamcrest.MatcherAssert.assertThat;
@RunWith(PowerMockRunner.class)
@PrepareForTest({})
public class AbstractClassEnhancePluginDefineTest {
static final String WEAVE_CLASS = "com.a.eye.skywalking.api.plugin.MockTargetObject";
static final String INTERCEPTOR_CLASS = "com.a.eye.skywalking.api.plugin.MockPluginInterceptor";
static final String WEAVE_INSTANCE_METHOD_NAME = "targetInstanceMethod";
static final String WEAVE_INSTANCE_WITH_EXCEPTION_METHOD_NAME = "targetInstanceMethodWithException";
static final String WEAVE_STATIC_METHOD_NAME = "targetStaticMethod";
private ClassLoader classLoader;
@Before
public void setUp() throws Exception {
classLoader = new ByteArrayClassLoader.ChildFirst(getClass().getClassLoader(),
ClassFileExtraction.of(MockTargetObject.class),
null,
ByteArrayClassLoader.PersistenceHandler.MANIFEST,
PackageDefinitionStrategy.NoOp.INSTANCE);
}
@Test
public void weaveInstanceMethod() throws Exception {
ByteBuddyAgent.install();
ClassFileTransformer classFileTransformer = new AgentBuilder.Default()
.with(AgentBuilder.PoolStrategy.Default.FAST)
.ignore(none())
.type(ElementMatchers.is(MockTargetObject.class), ElementMatchers.is(classLoader)).transform(new MockTargetObjectTransformer())
.installOnByteBuddyAgent();
try {
Class<?> type = classLoader.loadClass(MockTargetObject.class.getName());
assertThat(type.getDeclaredMethod(WEAVE_INSTANCE_METHOD_NAME).invoke(type.getDeclaredConstructor(String.class).newInstance("a"))
, CoreMatchers.<Object>is(WEAVE_INSTANCE_METHOD_NAME + "a"));
} finally {
ByteBuddyAgent.getInstrumentation().removeTransformer(classFileTransformer);
}
}
@Test(expected = RuntimeException.class)
public void weaveInstanceMethodWITEXCEPTION() throws Exception {
ByteBuddyAgent.install();
ClassFileTransformer classFileTransformer = new AgentBuilder.Default()
.with(AgentBuilder.PoolStrategy.Default.FAST)
.ignore(none())
.type(ElementMatchers.is(MockTargetObject.class), ElementMatchers.is(classLoader)).transform(new MockTargetObjectTransformer())
.installOnByteBuddyAgent();
try {
Class<?> type = classLoader.loadClass(MockTargetObject.class.getName());
type.getDeclaredMethod(WEAVE_INSTANCE_WITH_EXCEPTION_METHOD_NAME).invoke(type.getDeclaredConstructor(String.class).newInstance("a"));
} finally {
ByteBuddyAgent.getInstrumentation().removeTransformer(classFileTransformer);
}
}
@Test
public void weaveStaticMethod() throws Exception {
ByteBuddyAgent.install();
ClassFileTransformer classFileTransformer = new AgentBuilder.Default()
.with(AgentBuilder.PoolStrategy.Default.FAST)
.ignore(none())
.type(ElementMatchers.is(MockTargetObject.class), ElementMatchers.is(classLoader)).transform(new MockTargetObjectTransformer())
.installOnByteBuddyAgent();
try {
Class<?> type = classLoader.loadClass(MockTargetObject.class.getName());
assertThat(type.getDeclaredMethod(WEAVE_STATIC_METHOD_NAME).invoke(type), CoreMatchers.<Object>is(WEAVE_STATIC_METHOD_NAME + "_STATIC"));
} finally {
ByteBuddyAgent.getInstrumentation().removeTransformer(classFileTransformer);
}
}
public static class MockTargetObjectTransformer implements AgentBuilder.Transformer {
@Override
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader) {
try {
DynamicType.Builder newBuilder = transformInstanceMethod(builder);
return transformStaticMethod(newBuilder);
} catch (Exception exception) {
throw new AssertionError(exception);
}
}
private DynamicType.Builder<?> transformStaticMethod(DynamicType.Builder newBuilder) {
MockPluginStaticMethodInstrumentation staticMethodInstrumentation = new MockPluginStaticMethodInstrumentation();
return staticMethodInstrumentation.define(WEAVE_CLASS, newBuilder);
}
private DynamicType.Builder transformInstanceMethod(DynamicType.Builder<?> builder) {
MockPluginInstanceMethodInstrumentation instrumentation = new MockPluginInstanceMethodInstrumentation();
return instrumentation.define(WEAVE_CLASS, builder);
}
}
}
\ No newline at end of file
package com.a.eye.skywalking.api.plugin;
import com.a.eye.skywalking.api.plugin.bytebuddy.AllObjectDefaultMethodsMatch;
import com.a.eye.skywalking.api.plugin.interceptor.ConstructorInterceptPoint;
import com.a.eye.skywalking.api.plugin.interceptor.InstanceMethodsInterceptPoint;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import static com.a.eye.skywalking.api.plugin.AbstractClassEnhancePluginDefineTest.INTERCEPTOR_CLASS;
import static com.a.eye.skywalking.api.plugin.AbstractClassEnhancePluginDefineTest.WEAVE_CLASS;
import static com.a.eye.skywalking.api.plugin.AbstractClassEnhancePluginDefineTest.WEAVE_INSTANCE_METHOD_NAME;
import static com.a.eye.skywalking.api.plugin.AbstractClassEnhancePluginDefineTest.WEAVE_INSTANCE_WITH_EXCEPTION_METHOD_NAME;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.not;
import static net.bytebuddy.matcher.ElementMatchers.takesArgument;
public class MockPluginInstanceMethodInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
@Override
protected String enhanceClassName() {
return WEAVE_CLASS;
}
@Override
protected ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
return new ConstructorInterceptPoint[]{
new ConstructorInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getConstructorMatcher() {
return takesArgument(0, String.class);
}
@Override
public String getConstructorInterceptor() {
return INTERCEPTOR_CLASS;
}
}
};
}
@Override
protected InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
return new InstanceMethodsInterceptPoint[]{
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(WEAVE_INSTANCE_METHOD_NAME).and(not(AllObjectDefaultMethodsMatch.INSTANCE));
}
@Override
public String getMethodsInterceptor() {
return INTERCEPTOR_CLASS;
}
},
new InstanceMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(WEAVE_INSTANCE_WITH_EXCEPTION_METHOD_NAME);
}
@Override
public String getMethodsInterceptor() {
return INTERCEPTOR_CLASS;
}
}
};
}
}
package com.a.eye.skywalking.api.plugin;
import com.a.eye.skywalking.api.plugin.interceptor.EnhancedClassInstanceContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.ConstructorInvokeContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceConstructorInterceptor;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodInvokeContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInterceptResult;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.MethodInvokeContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.StaticMethodInvokeContext;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.StaticMethodsAroundInterceptor;
public class MockPluginInterceptor implements InstanceMethodsAroundInterceptor, StaticMethodsAroundInterceptor, InstanceConstructorInterceptor {
@Override
public void beforeMethod(StaticMethodInvokeContext interceptorContext, MethodInterceptResult result) {
}
@Override
public Object afterMethod(StaticMethodInvokeContext interceptorContext, Object ret) {
return ret + "_STATIC";
}
@Override
public void handleMethodException(Throwable t, MethodInvokeContext interceptorContext) {
}
@Override
public void beforeMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, MethodInterceptResult result) {
}
@Override
public Object afterMethod(EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext, Object ret) {
return ret + String.valueOf(context.get("VALUE"));
}
@Override
public void handleMethodException(Throwable t, EnhancedClassInstanceContext context, InstanceMethodInvokeContext interceptorContext) {
}
@Override
public void onConstruct(EnhancedClassInstanceContext context, ConstructorInvokeContext interceptorContext) {
context.set("VALUE" , interceptorContext.allArguments()[0]);
}
}
package com.a.eye.skywalking.api.plugin;
import com.a.eye.skywalking.api.plugin.interceptor.StaticMethodsInterceptPoint;
import com.a.eye.skywalking.api.plugin.interceptor.enhance.ClassStaticMethodsEnhancePluginDefine;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.matcher.ElementMatcher;
import static com.a.eye.skywalking.api.plugin.AbstractClassEnhancePluginDefineTest.INTERCEPTOR_CLASS;
import static com.a.eye.skywalking.api.plugin.AbstractClassEnhancePluginDefineTest.WEAVE_CLASS;
import static com.a.eye.skywalking.api.plugin.AbstractClassEnhancePluginDefineTest.WEAVE_STATIC_METHOD_NAME;
import static net.bytebuddy.matcher.ElementMatchers.named;
public class MockPluginStaticMethodInstrumentation extends ClassStaticMethodsEnhancePluginDefine {
@Override
protected String enhanceClassName() {
return WEAVE_CLASS;
}
@Override
protected StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
return new StaticMethodsInterceptPoint[]{
new StaticMethodsInterceptPoint() {
@Override
public ElementMatcher<MethodDescription> getMethodsMatcher() {
return named(WEAVE_STATIC_METHOD_NAME);
}
@Override
public String getMethodsInterceptor() {
return INTERCEPTOR_CLASS;
}
}
};
}
}
package com.a.eye.skywalking.api.plugin;
public class MockTargetObject {
private String value;
public MockTargetObject(String value) {
this.value = value;
}
public String targetInstanceMethod() {
return "targetInstanceMethod";
}
public String targetInstanceMethodWithException() {
throw new RuntimeException("test exception");
}
public static String targetStaticMethod() {
return "targetStaticMethod";
}
}
package com.a.eye.skywalking.api.plugin.utility;
import net.bytebuddy.ClassFileVersion;
import net.bytebuddy.asm.AsmVisitorWrapper;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.auxiliary.AuxiliaryType;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.jar.asm.ClassReader;
import net.bytebuddy.jar.asm.ClassWriter;
import net.bytebuddy.pool.TypePool;
import org.junit.Test;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
public class ClassFileExtraction {
private static final int CA = 0xCA, FE = 0xFE, BA = 0xBA, BE = 0xBE;
public static Map<String, byte[]> of(Class<?>... type) throws IOException {
Map<String, byte[]> result = new HashMap<String, byte[]>();
for (Class<?> aType : type) {
result.put(aType.getName(), extract(aType));
}
return result;
}
public static byte[] extract(Class<?> type, AsmVisitorWrapper asmVisitorWrapper) throws IOException {
ClassReader classReader = new ClassReader(type.getName());
ClassWriter classWriter = new ClassWriter(classReader, AsmVisitorWrapper.NO_FLAGS);
classReader.accept(asmVisitorWrapper.wrap(new TypeDescription.ForLoadedType(type),
classWriter,
new IllegalContext(),
TypePool.Empty.INSTANCE,
AsmVisitorWrapper.NO_FLAGS,
AsmVisitorWrapper.NO_FLAGS), AsmVisitorWrapper.NO_FLAGS);
return classWriter.toByteArray();
}
public static byte[] extract(Class<?> type) throws IOException {
return extract(type, new AsmVisitorWrapper.Compound());
}
@Test
public void testClassFileExtraction() throws Exception {
byte[] binaryFoo = extract(Foo.class);
assertThat(binaryFoo.length > 4, is(true));
assertThat(binaryFoo[0], is(new Integer(CA).byteValue()));
assertThat(binaryFoo[1], is(new Integer(FE).byteValue()));
assertThat(binaryFoo[2], is(new Integer(BA).byteValue()));
assertThat(binaryFoo[3], is(new Integer(BE).byteValue()));
}
private static class Foo {
/* empty */
}
private static class IllegalContext implements Implementation.Context {
@Override
public TypeDescription register(AuxiliaryType auxiliaryType) {
throw new AssertionError("Did not expect method call");
}
@Override
public FieldDescription.InDefinedShape cache(StackManipulation fieldValue, TypeDescription fieldType) {
throw new AssertionError("Did not expect method call");
}
@Override
public TypeDescription getInstrumentedType() {
throw new AssertionError("Did not expect method call");
}
@Override
public ClassFileVersion getClassFileVersion() {
throw new AssertionError("Did not expect method call");
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册