Commit 240cacb4 authored by ascrutae's avatar ascrutae
Browse files

add plugin test cases

parent dfa0eead
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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>
+121 −0
Original line number Diff line number Diff line
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
+69 −0
Original line number Diff line number Diff line
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;
                    }
                }
        };
    }
}
+44 −0
Original line number Diff line number Diff line
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]);
    }
}
+36 −0
Original line number Diff line number Diff line
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;
                    }
                }
        };
    }
}
Loading