You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by xi...@apache.org on 2021/01/07 15:24:59 UTC

[shardingsphere] branch master updated: add unit test for agent core (#8929)

This is an automated email from the ASF dual-hosted git repository.

xiaoyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git


The following commit(s) were added to refs/heads/master by this push:
     new 48d8904  add unit test for agent core (#8929)
48d8904 is described below

commit 48d89044d4289eb3c75ab20fde9a550337142c6a
Author: Daming <zt...@foxmail.com>
AuthorDate: Thu Jan 7 23:24:20 2021 +0800

    add unit test for agent core (#8929)
    
    * add unit test for agent core
    
    * revert
    
    * revert
    
    * fix checkstyle
    
    * fix
    
    * fix checkstyle
    
    * fix checkstyle
    
    * test
    
    * test
    
    * fix checkstyle
    
    * fix checkstyle
    
    * fix checkstyle
    
    * fix test
    
    Co-authored-by: zhuanghaochao <zh...@yy.com>
---
 .../shardingsphere-agent-core/pom.xml              |   7 ++
 .../transformer/ShardingSphereTransformerTest.java | 119 ++++++++++++++++++++
 .../agent/core/mock/ConstructorMaterial.java       |  35 ++++++
 .../agent/core/mock/InstanceMaterial.java          |  50 +++++++++
 .../shardingsphere/agent/core/mock/Material.java   |  80 ++++++++++++++
 .../agent/core/mock/StaticMaterial.java            |  50 +++++++++
 .../agent/core/mock/advice/MockConstructor.java    |  48 +++++++++
 .../core/mock/advice/MockMethodAroundAdvice.java   |  59 ++++++++++
 .../mock/advice/MockStaticMethodAroundAdvice.java  |  57 ++++++++++
 .../ConstructorMethodInterceptorTest.java          |  97 +++++++++++++++++
 .../interceptor/MethodAroundInterceptorTest.java   | 120 +++++++++++++++++++++
 .../core/plugin/interceptor/MockClassLoader.java   |  22 ++++
 .../StaticMethodAroundInterceptorTest.java         | 111 +++++++++++++++++++
 .../agent/core/plugin/loader/PluginLoaderTest.java |  93 ++++++++++++++++
 14 files changed, 948 insertions(+)

diff --git a/shardingsphere-agent/shardingsphere-agent-core/pom.xml b/shardingsphere-agent/shardingsphere-agent-core/pom.xml
index abf28e2..e74bc4c 100644
--- a/shardingsphere-agent/shardingsphere-agent-core/pom.xml
+++ b/shardingsphere-agent/shardingsphere-agent-core/pom.xml
@@ -44,6 +44,13 @@
     <build>
         <plugins>
             <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <reuseForks>false</reuseForks>
+                </configuration>
+            </plugin>
+            <plugin>
                 <artifactId>maven-shade-plugin</artifactId>
                 <executions>
                     <execution>
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/bytebuddy/transformer/ShardingSphereTransformerTest.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/bytebuddy/transformer/ShardingSphereTransformerTest.java
new file mode 100644
index 0000000..9328926
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/bytebuddy/transformer/ShardingSphereTransformerTest.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.bytebuddy.transformer;
+
+import com.google.common.collect.Maps;
+import lombok.SneakyThrows;
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.agent.ByteBuddyAgent;
+import net.bytebuddy.agent.builder.AgentBuilder;
+import net.bytebuddy.agent.builder.ResettableClassFileTransformer;
+import net.bytebuddy.dynamic.scaffold.TypeValidation;
+import net.bytebuddy.matcher.ElementMatchers;
+import org.apache.shardingsphere.agent.api.point.PluginInterceptorPoint;
+import org.apache.shardingsphere.agent.core.bytebuddy.listener.LoggingListener;
+import org.apache.shardingsphere.agent.core.mock.Material;
+import org.apache.shardingsphere.agent.core.mock.advice.MockConstructor;
+import org.apache.shardingsphere.agent.core.mock.advice.MockMethodAroundAdvice;
+import org.apache.shardingsphere.agent.core.mock.advice.MockStaticMethodAroundAdvice;
+import org.apache.shardingsphere.agent.core.plugin.loader.PluginLoader;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.internal.util.reflection.FieldReader;
+import org.mockito.internal.util.reflection.FieldSetter;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertThat;
+
+public final class ShardingSphereTransformerTest {
+    
+    private static final PluginLoader PLUGIN_LOADER = PluginLoader.getInstance();
+    
+    private static ResettableClassFileTransformer byteBuddyAgent;
+    
+    private final List<String> queue = new LinkedList<>();
+    
+    @BeforeClass
+    @SneakyThrows
+    public static void setup() {
+        ByteBuddyAgent.install();
+        FieldReader objectPoolReader = new FieldReader(PLUGIN_LOADER, PLUGIN_LOADER.getClass().getDeclaredField("objectPool"));
+        Map<String, Object> objectPool = (Map<String, Object>) objectPoolReader.read();
+        objectPool.put(MockConstructor.class.getTypeName(), new MockConstructor());
+        objectPool.put(MockMethodAroundAdvice.class.getTypeName(), new MockMethodAroundAdvice());
+        objectPool.put(MockStaticMethodAroundAdvice.class.getTypeName(), new MockStaticMethodAroundAdvice());
+        Map<String, PluginInterceptorPoint> interceptorPointMap = Maps.newHashMap();
+        PluginInterceptorPoint interceptorPoint = PluginInterceptorPoint.intercept("org.apache.shardingsphere.agent.core.mock.Material")
+                .aroundInstanceMethod(ElementMatchers.named("mock"))
+                .implement(MockMethodAroundAdvice.class.getTypeName())
+                .build()
+                .aroundClassStaticMethod(ElementMatchers.named("staticMock"))
+                .implement(MockStaticMethodAroundAdvice.class.getTypeName())
+                .build()
+                .onConstructor(ElementMatchers.takesArguments(1))
+                .implement(MockConstructor.class.getTypeName())
+                .build()
+                .install();
+        interceptorPointMap.put(interceptorPoint.getClassNameOfTarget(), interceptorPoint);
+        FieldSetter.setField(PLUGIN_LOADER, PLUGIN_LOADER.getClass().getDeclaredField("interceptorPointMap"), interceptorPointMap);
+        byteBuddyAgent = new AgentBuilder.Default().with(new ByteBuddy().with(TypeValidation.ENABLED))
+                .ignore(ElementMatchers.isSynthetic()).or(ElementMatchers.nameStartsWith("org.apache.shardingsphere.agent.")
+                        .and(ElementMatchers.not(ElementMatchers.nameStartsWith("org.apache.shardingsphere.agent.core.mock"))))
+                .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
+                .with(new LoggingListener())
+                .type(PLUGIN_LOADER.typeMatcher())
+                .transform(new ShardingSphereTransformer(PLUGIN_LOADER))
+                .asTerminalTransformation()
+                .installOnByteBuddyAgent();
+    }
+    
+    @Test
+    public void assertInstanceMethod() {
+        assertThat(new Material().mock(queue), is("invocation"));
+        assertArrayEquals(new String[]{"before", "on", "after"}, queue.toArray());
+    }
+    
+    @Test
+    public void assertStaticMethod() {
+        assertThat(Material.staticMock(queue), is("static invocation"));
+        assertArrayEquals(new String[]{"before", "on", "after"}, queue.toArray());
+    }
+    
+    @Test
+    public void assertConstructor() {
+        new Material(queue);
+        assertArrayEquals(new String[]{"constructor", "on constructor"}, queue.toArray());
+    }
+    
+    @After
+    public void cleanup() {
+        queue.clear();
+    }
+    
+    @AfterClass
+    public static void destroy() {
+        byteBuddyAgent.reset(ByteBuddyAgent.getInstrumentation(), AgentBuilder.RedefinitionStrategy.RETRANSFORMATION);
+    }
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/ConstructorMaterial.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/ConstructorMaterial.java
new file mode 100644
index 0000000..3992d6e
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/ConstructorMaterial.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.mock;
+
+import java.util.List;
+
+/**
+ * Have to redefine this class dynamic, so never add `final` modifier.
+ */
+public class ConstructorMaterial {
+    
+    public ConstructorMaterial() {
+    
+    }
+
+    public ConstructorMaterial(final List<String> queue) {
+        queue.add("constructor");
+    }
+    
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/InstanceMaterial.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/InstanceMaterial.java
new file mode 100644
index 0000000..b894ecf
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/InstanceMaterial.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.mock;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Have to redefine this class dynamic, so never add `final` modifier.
+ */
+public class InstanceMaterial {
+    
+    /**
+     * Mock method for testing.
+     *
+     * @param queue collector
+     * @return result
+     */
+    public String mock(final List<String> queue) {
+        queue.add("on");
+        return "invocation";
+    }
+    
+    /**
+     * Mock method for testing with exception.
+     *
+     * @param queue collector
+     * @return result
+     * @throws IOException io exception
+     */
+    public String mockWithException(final List<String> queue) throws IOException {
+        throw new IOException();
+    }
+    
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/Material.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/Material.java
new file mode 100644
index 0000000..4e1ac01
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/Material.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.mock;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Have to redefine this class dynamic, so never add `final` modifier.
+ */
+public class Material {
+    
+    public Material() {
+    
+    }
+    
+    public Material(final List<String> queue) {
+        queue.add("constructor");
+    }
+    
+    /**
+     * Mock method for testing.
+     *
+     * @param queue collector
+     * @return result
+     */
+    public String mock(final List<String> queue) {
+        queue.add("on");
+        return "invocation";
+    }
+    
+    /**
+     * Mock method for testing with exception.
+     *
+     * @param queue collector
+     * @return result
+     * @throws IOException io exception
+     */
+    public String mockWithException(final List<String> queue) throws IOException {
+        throw new IOException();
+    }
+    
+    /**
+     * Mock static method for testing.
+     *
+     * @param queue collector
+     * @return result
+     */
+    public static String staticMock(final List<String> queue) {
+        queue.add("on");
+        return "static invocation";
+    }
+    
+    /**
+     * Mock static method for testing with exception.
+     *
+     * @param queue collector
+     * @return result
+     * @throws IOException io exception
+     */
+    public static String staticMockWithException(final List<String> queue) throws IOException {
+        throw new IOException();
+    }
+    
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/StaticMaterial.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/StaticMaterial.java
new file mode 100644
index 0000000..fe7a358
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/StaticMaterial.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.mock;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Have to redefine this class dynamic, so never add `final` modifier.
+ */
+public class StaticMaterial {
+
+    /**
+     * Mock static method for testing.
+     *
+     * @param queue collector
+     * @return result
+     */
+    public static String staticMock(final List<String> queue) {
+        queue.add("on");
+        return "static invocation";
+    }
+    
+    /**
+     * Mock static method for testing with exception.
+     *
+     * @param queue collector
+     * @return result
+     * @throws IOException io exception
+     */
+    public static String staticMockWithException(final List<String> queue) throws IOException {
+        throw new IOException();
+    }
+    
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/advice/MockConstructor.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/advice/MockConstructor.java
new file mode 100644
index 0000000..88e2e49
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/advice/MockConstructor.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.mock.advice;
+
+import org.apache.shardingsphere.agent.api.advice.ConstructorAdvice;
+import org.apache.shardingsphere.agent.api.advice.TargetObject;
+
+import java.util.List;
+
+public final class MockConstructor implements ConstructorAdvice {
+    
+    private final List<String> queue;
+    
+    public MockConstructor() {
+        this(null);
+    }
+    
+    public MockConstructor(final List<String> queue) {
+        this.queue = queue;
+    }
+    
+    @Override
+    public void onConstructor(final TargetObject target, final Object[] args) {
+        final List<String> list;
+        if (queue == null) {
+            list = (List<String>) args[0];
+        } else {
+            list = queue;
+        }
+        list.add("on constructor");
+    }
+    
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/advice/MockMethodAroundAdvice.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/advice/MockMethodAroundAdvice.java
new file mode 100644
index 0000000..da42483
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/advice/MockMethodAroundAdvice.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (final ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, final Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.mock.advice;
+
+import org.apache.shardingsphere.agent.api.advice.MethodAroundAdvice;
+import org.apache.shardingsphere.agent.api.advice.TargetObject;
+import org.apache.shardingsphere.agent.api.result.MethodInvocationResult;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+public final class MockMethodAroundAdvice implements MethodAroundAdvice {
+    
+    private final boolean rebase;
+    
+    public MockMethodAroundAdvice() {
+        this(false);
+    }
+    
+    public MockMethodAroundAdvice(final boolean rebase) {
+        this.rebase = rebase;
+    }
+    
+    @Override
+    public void beforeMethod(final TargetObject target, final Method method, final Object[] args, final MethodInvocationResult result) {
+        List<String> queue = (List<String>) args[0];
+        queue.add("before");
+        if (rebase) {
+            result.rebase("rebase invocation method");
+        }
+    }
+    
+    @Override
+    public void afterMethod(final TargetObject target, final Method method, final Object[] args, final MethodInvocationResult result) {
+        List<String> queue = (List<String>) args[0];
+        queue.add("after");
+    }
+    
+    @Override
+    public void onThrowing(final TargetObject target, final Method method, final Object[] args, final Throwable throwable) {
+        List<String> queue = (List<String>) args[0];
+        queue.add("exception");
+    }
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/advice/MockStaticMethodAroundAdvice.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/advice/MockStaticMethodAroundAdvice.java
new file mode 100644
index 0000000..ae12d66
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/mock/advice/MockStaticMethodAroundAdvice.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (final ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, final Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.mock.advice;
+
+import lombok.RequiredArgsConstructor;
+import org.apache.shardingsphere.agent.api.advice.StaticMethodAroundAdvice;
+import org.apache.shardingsphere.agent.api.result.MethodInvocationResult;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+@RequiredArgsConstructor
+public final class MockStaticMethodAroundAdvice implements StaticMethodAroundAdvice {
+    
+    private final boolean rebase;
+    
+    public MockStaticMethodAroundAdvice() {
+        this(false);
+    }
+    
+    @Override
+    public void beforeMethod(final Class<?> clazz, final Method method, final Object[] args, final MethodInvocationResult result) {
+        List<String> queue = (List<String>) args[0];
+        queue.add("before");
+        if (rebase) {
+            result.rebase("rebase static invocation method");
+        }
+    }
+    
+    @Override
+    public void afterMethod(final Class<?> clazz, final Method method, final Object[] args, final MethodInvocationResult result) {
+        List<String> queue = (List<String>) args[0];
+        queue.add("after");
+    }
+    
+    @Override
+    public void onThrowing(final Class<?> clazz, final Method method, final Object[] args, final Throwable throwable) {
+        List<String> queue = (List<String>) args[0];
+        queue.add("exception");
+    }
+    
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/interceptor/ConstructorMethodInterceptorTest.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/interceptor/ConstructorMethodInterceptorTest.java
new file mode 100644
index 0000000..29a3080
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/interceptor/ConstructorMethodInterceptorTest.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (final ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, final Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.plugin.interceptor;
+
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.agent.ByteBuddyAgent;
+import net.bytebuddy.agent.builder.AgentBuilder;
+import net.bytebuddy.agent.builder.ResettableClassFileTransformer;
+import net.bytebuddy.dynamic.scaffold.TypeValidation;
+import net.bytebuddy.implementation.FieldAccessor;
+import net.bytebuddy.implementation.MethodDelegation;
+import net.bytebuddy.implementation.SuperMethodCall;
+import net.bytebuddy.jar.asm.Opcodes;
+import net.bytebuddy.matcher.ElementMatchers;
+import org.apache.shardingsphere.agent.api.advice.TargetObject;
+import org.apache.shardingsphere.agent.core.bytebuddy.listener.LoggingListener;
+import org.apache.shardingsphere.agent.core.mock.ConstructorMaterial;
+import org.apache.shardingsphere.agent.core.mock.advice.MockConstructor;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertTrue;
+
+public final class ConstructorMethodInterceptorTest {
+    
+    private static final String EXTRA_DATA = "_$EXTRA_DATA$_";
+    
+    private static final List<String> QUEUE = new LinkedList<>();
+    
+    private static ResettableClassFileTransformer byteBuddyAgent;
+    
+    @BeforeClass
+    public static void setup() {
+        ByteBuddyAgent.install();
+        byteBuddyAgent = new AgentBuilder.Default()
+                .with(new ByteBuddy().with(TypeValidation.ENABLED))
+                .ignore(ElementMatchers.isSynthetic())
+                .with(new LoggingListener())
+                .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
+                .type(ElementMatchers.named("org.apache.shardingsphere.agent.core.mock.ConstructorMaterial"))
+                .transform((builder, typeDescription, classLoader, module) -> {
+                    if ("org.apache.shardingsphere.agent.core.mock.ConstructorMaterial".equals(typeDescription.getTypeName())) {
+                        return builder.defineField(EXTRA_DATA, Object.class, Opcodes.ACC_PRIVATE | Opcodes.ACC_VOLATILE)
+                                .implement(TargetObject.class)
+                                .intercept(FieldAccessor.ofField(EXTRA_DATA))
+                                .constructor(ElementMatchers.isConstructor())
+                                .intercept(SuperMethodCall.INSTANCE.andThen(MethodDelegation.withDefaultConfiguration().to(new ConstructorMethodInterceptor(new MockConstructor(QUEUE)))));
+                    }
+                    return builder;
+                })
+                .asTerminalTransformation()
+                .installOnByteBuddyAgent();
+    }
+    
+    @Test
+    public void assertNoArgConstructor() {
+        Object material = new ConstructorMaterial();
+        assertTrue(material instanceof TargetObject);
+    }
+    
+    @Test
+    public void assertConstructor() {
+        new ConstructorMaterial(QUEUE);
+        assertArrayEquals(new String[]{"constructor", "on constructor"}, QUEUE.toArray());
+    }
+    
+    @After
+    public void cleanup() {
+        QUEUE.clear();
+    }
+    
+    @AfterClass
+    public static void destroy() {
+        byteBuddyAgent.reset(ByteBuddyAgent.getInstrumentation(), AgentBuilder.RedefinitionStrategy.RETRANSFORMATION);
+    }
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/interceptor/MethodAroundInterceptorTest.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/interceptor/MethodAroundInterceptorTest.java
new file mode 100644
index 0000000..a608e87
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/interceptor/MethodAroundInterceptorTest.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (final ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, final Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.plugin.interceptor;
+
+import com.google.common.collect.Lists;
+import lombok.RequiredArgsConstructor;
+import lombok.SneakyThrows;
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.agent.ByteBuddyAgent;
+import net.bytebuddy.agent.builder.AgentBuilder;
+import net.bytebuddy.agent.builder.ResettableClassFileTransformer;
+import net.bytebuddy.dynamic.scaffold.TypeValidation;
+import net.bytebuddy.implementation.FieldAccessor;
+import net.bytebuddy.implementation.MethodDelegation;
+import net.bytebuddy.jar.asm.Opcodes;
+import net.bytebuddy.matcher.ElementMatchers;
+import org.apache.shardingsphere.agent.api.advice.TargetObject;
+import org.apache.shardingsphere.agent.core.mock.InstanceMaterial;
+import org.apache.shardingsphere.agent.core.mock.advice.MockMethodAroundAdvice;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertThat;
+
+@RunWith(Parameterized.class)
+@RequiredArgsConstructor
+public final class MethodAroundInterceptorTest {
+    
+    private static final String EXTRA_DATA = "_$EXTRA_DATA$_";
+    
+    private static ResettableClassFileTransformer byteBuddyAgent;
+    
+    private final boolean rebase;
+    
+    private final String methodName;
+    
+    private final String result;
+    
+    private final String[] expected;
+    
+    @Parameterized.Parameters
+    public static Collection<Object[]> data() {
+        return Lists.newArrayList(
+                new Object[]{false, "mock", "invocation", new String[]{"before", "on", "after"}},
+                new Object[]{true, "mock", "rebase invocation method", new String[]{"before", "after"}},
+                new Object[]{false, "mockWithException", null, new String[]{"before", "exception", "after"}}
+        );
+    }
+    
+    @BeforeClass
+    public static void setup() {
+        ByteBuddyAgent.install();
+        byteBuddyAgent = new AgentBuilder.Default().with(new ByteBuddy().with(TypeValidation.ENABLED))
+                .with(new ByteBuddy())
+                .type(ElementMatchers.named("org.apache.shardingsphere.agent.core.mock.InstanceMaterial"))
+                .transform((builder, typeDescription, classLoader, module) -> {
+                    if ("org.apache.shardingsphere.agent.core.mock.InstanceMaterial".equals(typeDescription.getTypeName())) {
+                        return builder.defineField(EXTRA_DATA, Object.class, Opcodes.ACC_PRIVATE | Opcodes.ACC_VOLATILE)
+                                .implement(TargetObject.class)
+                                .intercept(FieldAccessor.ofField(EXTRA_DATA));
+                    }
+                    return builder;
+                }).asTerminalTransformation()
+                .installOnByteBuddyAgent();
+    }
+    
+    @Test
+    @SneakyThrows
+    public void assertInterceptedMethod() {
+        InstanceMaterial material = new ByteBuddy()
+                .subclass(InstanceMaterial.class)
+                .method(ElementMatchers.named(methodName))
+                .intercept(MethodDelegation.withDefaultConfiguration().to(new MethodAroundInterceptor(new MockMethodAroundAdvice(rebase))))
+                .make()
+                .load(new MockClassLoader())
+                .getLoaded()
+                .newInstance();
+        List<String> queue = new LinkedList<>();
+        if ("mockWithException".equals(methodName)) {
+            try {
+                material.mockWithException(queue);
+            } catch (IOException ignore) {
+            }
+        } else {
+            assertThat(material.mock(queue), is(result));
+        }
+        assertArrayEquals(expected, queue.toArray());
+    }
+    
+    @AfterClass
+    public static void destroy() {
+        byteBuddyAgent.reset(ByteBuddyAgent.getInstrumentation(), AgentBuilder.RedefinitionStrategy.RETRANSFORMATION);
+    }
+    
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/interceptor/MockClassLoader.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/interceptor/MockClassLoader.java
new file mode 100644
index 0000000..a49928a
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/interceptor/MockClassLoader.java
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (final ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, final Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.plugin.interceptor;
+
+public final class MockClassLoader extends ClassLoader {
+
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/interceptor/StaticMethodAroundInterceptorTest.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/interceptor/StaticMethodAroundInterceptorTest.java
new file mode 100644
index 0000000..f5c78e7
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/interceptor/StaticMethodAroundInterceptorTest.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (final ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, final Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.plugin.interceptor;
+
+import com.google.common.collect.Lists;
+import lombok.RequiredArgsConstructor;
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.agent.ByteBuddyAgent;
+import net.bytebuddy.agent.builder.AgentBuilder;
+import net.bytebuddy.agent.builder.ResettableClassFileTransformer;
+import net.bytebuddy.dynamic.scaffold.TypeValidation;
+import net.bytebuddy.implementation.FieldAccessor;
+import net.bytebuddy.implementation.MethodDelegation;
+import net.bytebuddy.jar.asm.Opcodes;
+import net.bytebuddy.matcher.ElementMatchers;
+import org.apache.shardingsphere.agent.api.advice.TargetObject;
+import org.apache.shardingsphere.agent.core.mock.StaticMaterial;
+import org.apache.shardingsphere.agent.core.mock.advice.MockStaticMethodAroundAdvice;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertThat;
+
+@RunWith(Parameterized.class)
+@RequiredArgsConstructor
+public final class StaticMethodAroundInterceptorTest {
+    
+    private static final String EXTRA_DATA = "_$EXTRA_DATA$_";
+    
+    private static ResettableClassFileTransformer byteBuddyAgent;
+    
+    private final String methodName;
+    
+    private final String result;
+    
+    private final String[] expected;
+    
+    @Parameterized.Parameters
+    public static Collection<Object[]> data() {
+        return Lists.newArrayList(
+                new Object[]{"staticMock", "rebase static invocation method", new String[]{"before", "after"}},
+                new Object[]{"staticMockWithException", null, new String[]{"before", "exception", "after"}}
+        );
+    }
+    
+    @BeforeClass
+    public static void setup() {
+        ByteBuddyAgent.install();
+        byteBuddyAgent = new AgentBuilder.Default().with(new ByteBuddy().with(TypeValidation.ENABLED))
+                .with(new ByteBuddy())
+                .type(ElementMatchers.named("org.apache.shardingsphere.agent.core.mock.StaticMaterial"))
+                .transform((builder, typeDescription, classLoader, module) -> {
+                    if ("org.apache.shardingsphere.agent.core.mock.StaticMaterial".equals(typeDescription.getTypeName())) {
+                        return builder.defineField(EXTRA_DATA, Object.class, Opcodes.ACC_PRIVATE | Opcodes.ACC_VOLATILE)
+                                .implement(TargetObject.class)
+                                .intercept(FieldAccessor.ofField(EXTRA_DATA))
+                                .method(ElementMatchers.named("staticMockWithException"))
+                                .intercept(MethodDelegation.withDefaultConfiguration().to(new StaticMethodAroundInterceptor(new MockStaticMethodAroundAdvice(false))))
+                                .method(ElementMatchers.named("staticMock"))
+                                .intercept(MethodDelegation.withDefaultConfiguration().to(new StaticMethodAroundInterceptor(new MockStaticMethodAroundAdvice(true))));
+                    }
+                    return builder;
+                })
+                .asTerminalTransformation()
+                .installOnByteBuddyAgent();
+    }
+    
+    @Test
+    public void assertInterceptedMethod() {
+        List<String> queue = new LinkedList<>();
+        if ("staticMockWithException".equals(methodName)) {
+            try {
+                StaticMaterial.staticMockWithException(queue);
+            } catch (IOException ignore) {
+            }
+        } else {
+            assertThat(StaticMaterial.staticMock(queue), is(result));
+        }
+        assertArrayEquals(expected, queue.toArray());
+    }
+    
+    @AfterClass
+    public static void destroy() {
+        byteBuddyAgent.reset(ByteBuddyAgent.getInstrumentation(), AgentBuilder.RedefinitionStrategy.RETRANSFORMATION);
+    }
+}
diff --git a/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/loader/PluginLoaderTest.java b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/loader/PluginLoaderTest.java
new file mode 100644
index 0000000..0d42a31
--- /dev/null
+++ b/shardingsphere-agent/shardingsphere-agent-core/src/test/java/org/apache/shardingsphere/agent/core/plugin/loader/PluginLoaderTest.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shardingsphere.agent.core.plugin.loader;
+
+import com.google.common.collect.Maps;
+import lombok.SneakyThrows;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.matcher.ElementMatchers;
+import net.bytebuddy.pool.TypePool;
+import org.apache.shardingsphere.agent.api.point.PluginInterceptorPoint;
+import org.apache.shardingsphere.agent.core.mock.advice.MockConstructor;
+import org.apache.shardingsphere.agent.core.mock.advice.MockMethodAroundAdvice;
+import org.apache.shardingsphere.agent.core.mock.advice.MockStaticMethodAroundAdvice;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.internal.util.reflection.FieldReader;
+import org.mockito.internal.util.reflection.FieldSetter;
+
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+
+@Category(PluginLoaderTest.class)
+public final class PluginLoaderTest {
+    
+    private static final PluginLoader PLUGIN_LOADER = PluginLoader.getInstance();
+    
+    private static final TypePool POOL = TypePool.Default.ofSystemLoader();
+    
+    private static final TypeDescription FAKE = POOL.describe("java.lang.String").resolve();
+    
+    private static final TypeDescription MATERIAL = POOL.describe("org.apache.shardingsphere.agent.core.mock.Material").resolve();
+    
+    @BeforeClass
+    @SneakyThrows
+    public static void setup() {
+        FieldReader objectPoolReader = new FieldReader(PLUGIN_LOADER, PLUGIN_LOADER.getClass().getDeclaredField("objectPool"));
+        Map<String, Object> objectPool = (Map<String, Object>) objectPoolReader.read();
+        objectPool.put(MockConstructor.class.getTypeName(), new MockConstructor());
+        objectPool.put(MockMethodAroundAdvice.class.getTypeName(), new MockMethodAroundAdvice());
+        objectPool.put(MockStaticMethodAroundAdvice.class.getTypeName(), new MockStaticMethodAroundAdvice());
+        Map<String, PluginInterceptorPoint> interceptorPointMap = Maps.newHashMap();
+        PluginInterceptorPoint interceptorPoint = PluginInterceptorPoint.intercept("org.apache.shardingsphere.agent.core.mock.Material")
+                .aroundInstanceMethod(ElementMatchers.named("mock"))
+                .implement(MockMethodAroundAdvice.class.getTypeName())
+                .build()
+                .aroundClassStaticMethod(ElementMatchers.named("staticMock"))
+                .implement(MockStaticMethodAroundAdvice.class.getTypeName())
+                .build()
+                .onConstructor(ElementMatchers.takesArguments(1))
+                .implement(MockConstructor.class.getTypeName())
+                .build()
+                .install();
+        interceptorPointMap.put(interceptorPoint.getClassNameOfTarget(), interceptorPoint);
+        FieldSetter.setField(PLUGIN_LOADER, PLUGIN_LOADER.getClass().getDeclaredField("interceptorPointMap"), interceptorPointMap);
+    }
+    
+    @Test
+    public void assertTypeMatcher() {
+        assertThat(PLUGIN_LOADER.typeMatcher().matches(MATERIAL), is(true));
+        assertThat(PLUGIN_LOADER.typeMatcher().matches(FAKE), is(false));
+    }
+    
+    @Test
+    public void assertContainsType() {
+        assertThat(PLUGIN_LOADER.containsType(MATERIAL), is(true));
+        assertThat(PLUGIN_LOADER.containsType(FAKE), is(false));
+    }
+    
+    @Test
+    public void assertLoadPluginInterceptorPoint() {
+        assertNotNull(PLUGIN_LOADER.loadPluginInterceptorPoint(MATERIAL));
+    }
+    
+}