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));
+ }
+
+}