This is an automated email from the ASF dual-hosted git repository.
zhangliang 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 04c6b5f285e Add more test cases on shardingsphere-agent (#37632)
04c6b5f285e is described below
commit 04c6b5f285e58584dcf4b10d55c28fe616a699b2
Author: Liang Zhang <[email protected]>
AuthorDate: Sun Jan 4 13:59:13 2026 +0800
Add more test cases on shardingsphere-agent (#37632)
* Add more test cases on shardingsphere-agent
* Add more test cases on shardingsphere-agent
* Add more test cases on shardingsphere-agent
* Add more test cases on shardingsphere-agent
---
.../executor/AdviceExecutorFactoryTest.java | 113 ++++++++++
.../type/ConstructorAdviceExecutorTest.java | 134 ++++++++++++
.../type/InstanceMethodAdviceExecutorTest.java | 233 +++++++++++++++++++++
.../type/StaticMethodAdviceExecutorTest.java | 212 +++++++++++++++++++
.../core/builder/AgentBuilderFactoryTest.java | 59 +++++-
.../impl/MethodAdvisorBuilderInterceptorTest.java | 100 +++++++++
6 files changed, 843 insertions(+), 8 deletions(-)
diff --git
a/agent/core/src/test/java/org/apache/shardingsphere/agent/core/advisor/executor/AdviceExecutorFactoryTest.java
b/agent/core/src/test/java/org/apache/shardingsphere/agent/core/advisor/executor/AdviceExecutorFactoryTest.java
new file mode 100644
index 00000000000..7e1cf688582
--- /dev/null
+++
b/agent/core/src/test/java/org/apache/shardingsphere/agent/core/advisor/executor/AdviceExecutorFactoryTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.advisor.executor;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.matcher.ElementMatchers;
+import
org.apache.shardingsphere.agent.core.advisor.config.AdvisorConfiguration;
+import
org.apache.shardingsphere.agent.core.advisor.config.MethodAdvisorConfiguration;
+import
org.apache.shardingsphere.agent.core.advisor.executor.type.ConstructorAdviceExecutor;
+import
org.apache.shardingsphere.agent.core.advisor.executor.type.InstanceMethodAdviceExecutor;
+import
org.apache.shardingsphere.agent.core.advisor.executor.type.StaticMethodAdviceExecutor;
+import
org.apache.shardingsphere.agent.core.plugin.classloader.ClassLoaderContext;
+import org.apache.shardingsphere.fixture.advice.BarAdvice;
+import org.apache.shardingsphere.fixture.advice.FooAdvice;
+import org.apache.shardingsphere.fixture.targeted.TargetObjectFixture;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.internal.configuration.plugins.Plugins;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.isA;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class AdviceExecutorFactoryTest {
+
+ @AfterEach
+ void resetCache() throws ReflectiveOperationException {
+ ((Map<?, ?>)
Plugins.getMemberAccessor().get(AdviceFactory.class.getDeclaredField("CACHED_ADVICES"),
null)).clear();
+ ((Map<?, ?>)
Plugins.getMemberAccessor().get(ClassLoaderContext.class.getDeclaredField("AGENT_CLASS_LOADERS"),
null)).clear();
+ }
+
+ @Test
+ void assertFindMatchedAdviceExecutorWithEmptyAdvisors() throws
NoSuchMethodException {
+ AdvisorConfiguration advisorConfig = new
AdvisorConfiguration(TargetObjectFixture.class.getName());
+ AdviceExecutorFactory factory = new AdviceExecutorFactory(new
ClassLoaderContext(new URLClassLoader(new URL[0], getClass().getClassLoader()),
Collections.emptyList()), advisorConfig);
+ assertFalse(factory.findMatchedAdviceExecutor(new
MethodDescription.ForLoadedMethod(TargetObjectFixture.class.getMethod("call",
List.class))).isPresent());
+ }
+
+ @Test
+ void assertFindMatchedAdviceExecutorWithUnmatchedPointcut() throws
NoSuchMethodException {
+ AdvisorConfiguration advisorConfig = new
AdvisorConfiguration(TargetObjectFixture.class.getName());
+ MethodDescription.InDefinedShape instanceMethod = new
MethodDescription.ForLoadedMethod(TargetObjectFixture.class.getMethod("call",
List.class));
+ advisorConfig.getAdvisors().add(new
MethodAdvisorConfiguration(ElementMatchers.none(), FooAdvice.class.getName(),
"foo"));
+ AdviceExecutorFactory factory = new AdviceExecutorFactory(new
ClassLoaderContext(new URLClassLoader(new URL[0], getClass().getClassLoader()),
Collections.emptyList()), advisorConfig);
+
assertFalse(factory.findMatchedAdviceExecutor(instanceMethod).isPresent());
+ }
+
+ @Test
+ void assertFindMatchedAdviceExecutorWithConstructor() throws
NoSuchMethodException {
+ MethodDescription.InDefinedShape constructor = new
MethodDescription.ForLoadedConstructor(TargetObjectFixture.class.getDeclaredConstructor(List.class));
+ AdvisorConfiguration advisorConfig = new
AdvisorConfiguration(TargetObjectFixture.class.getName());
+ advisorConfig.getAdvisors().add(new
MethodAdvisorConfiguration(ElementMatchers.is(constructor),
FooAdvice.class.getName(), "foo"));
+ advisorConfig.getAdvisors().add(new
MethodAdvisorConfiguration(ElementMatchers.is(constructor),
BarAdvice.class.getName(), "bar"));
+ AdviceExecutorFactory factory = new AdviceExecutorFactory(new
ClassLoaderContext(new URLClassLoader(new URL[0], getClass().getClassLoader()),
Collections.emptyList()), advisorConfig);
+ Optional<AdviceExecutor> actual =
factory.findMatchedAdviceExecutor(constructor);
+ assertTrue(actual.isPresent());
+ assertThat(actual.get(), isA(ConstructorAdviceExecutor.class));
+ }
+
+ @Test
+ void assertFindMatchedAdviceExecutorWithStaticMethod() throws
NoSuchMethodException {
+ MethodDescription.InDefinedShape staticMethod = new
MethodDescription.ForLoadedMethod(TargetObjectFixture.class.getMethod("staticCall",
List.class));
+ AdvisorConfiguration advisorConfig = new
AdvisorConfiguration(TargetObjectFixture.class.getName());
+ advisorConfig.getAdvisors().add(new
MethodAdvisorConfiguration(ElementMatchers.is(staticMethod),
FooAdvice.class.getName(), "foo"));
+ AdviceExecutorFactory factory = new AdviceExecutorFactory(new
ClassLoaderContext(new URLClassLoader(new URL[0], getClass().getClassLoader()),
Collections.emptyList()), advisorConfig);
+ Optional<AdviceExecutor> actual =
factory.findMatchedAdviceExecutor(staticMethod);
+ assertTrue(actual.isPresent());
+ assertThat(actual.get(), isA(StaticMethodAdviceExecutor.class));
+ }
+
+ @Test
+ void assertFindMatchedAdviceExecutorWithInstanceMethod() throws
NoSuchMethodException {
+ MethodDescription.InDefinedShape instanceMethod = new
MethodDescription.ForLoadedMethod(TargetObjectFixture.class.getMethod("call",
List.class));
+ AdvisorConfiguration advisorConfig = new
AdvisorConfiguration(TargetObjectFixture.class.getName());
+ advisorConfig.getAdvisors().add(new
MethodAdvisorConfiguration(ElementMatchers.is(instanceMethod),
FooAdvice.class.getName(), "foo"));
+ AdviceExecutorFactory factory = new AdviceExecutorFactory(new
ClassLoaderContext(new URLClassLoader(new URL[0], getClass().getClassLoader()),
Collections.emptyList()), advisorConfig);
+ Optional<AdviceExecutor> actual =
factory.findMatchedAdviceExecutor(instanceMethod);
+ assertTrue(actual.isPresent());
+ assertThat(actual.get(), isA(InstanceMethodAdviceExecutor.class));
+ }
+
+ @Test
+ void assertFindMatchedAdviceExecutorWithAbstractMethod() throws
NoSuchMethodException {
+ MethodDescription.InDefinedShape abstractMethod = new
MethodDescription.ForLoadedMethod(Runnable.class.getMethod("run"));
+ AdvisorConfiguration advisorConfig = new
AdvisorConfiguration(Runnable.class.getName());
+ advisorConfig.getAdvisors().add(new MethodAdvisorConfiguration(target
-> true, FooAdvice.class.getName(), "foo"));
+ AdviceExecutorFactory factory = new AdviceExecutorFactory(new
ClassLoaderContext(new URLClassLoader(new URL[0], getClass().getClassLoader()),
Collections.emptyList()), advisorConfig);
+
assertFalse(factory.findMatchedAdviceExecutor(abstractMethod).isPresent());
+ }
+}
diff --git
a/agent/core/src/test/java/org/apache/shardingsphere/agent/core/advisor/executor/type/ConstructorAdviceExecutorTest.java
b/agent/core/src/test/java/org/apache/shardingsphere/agent/core/advisor/executor/type/ConstructorAdviceExecutorTest.java
new file mode 100644
index 00000000000..95d1f765f04
--- /dev/null
+++
b/agent/core/src/test/java/org/apache/shardingsphere/agent/core/advisor/executor/type/ConstructorAdviceExecutorTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.advisor.executor.type;
+
+import net.bytebuddy.dynamic.DynamicType.Builder;
+import
net.bytebuddy.dynamic.DynamicType.Builder.MethodDefinition.ImplementationDefinition;
+import
net.bytebuddy.dynamic.DynamicType.Builder.MethodDefinition.ReceiverTypeDefinition;
+import org.apache.shardingsphere.agent.api.advice.TargetAdviceObject;
+import org.apache.shardingsphere.agent.api.advice.type.ConstructorAdvice;
+import org.apache.shardingsphere.agent.api.plugin.AgentPluginEnable;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class ConstructorAdviceExecutorTest {
+
+ @Test
+ void assertAdviceInvokeEnabledAdvice() {
+ List<String> queue = new LinkedList<>();
+ Map<String, Collection<ConstructorAdvice>> advices =
Collections.singletonMap("foo", Arrays.asList(new
RecordingConstructorAdvice(queue, true), new
PluginDisabledConstructorAdvice(queue)));
+ new ConstructorAdviceExecutor(advices).advice(new
SimpleTargetAdviceObject(), new Object[]{queue});
+ assertThat(queue, is(Collections.singletonList("foo constructor")));
+ }
+
+ @Test
+ void assertAdviceCatchException() {
+ Map<String, Collection<ConstructorAdvice>> advices =
Collections.singletonMap("foo", Collections.singletonList(new
ThrowingConstructorAdvice()));
+ ConstructorAdviceExecutor executor = new
ConstructorAdviceExecutor(advices);
+ assertDoesNotThrow(() -> executor.advice(new
SimpleTargetAdviceObject(), new Object[]{new LinkedList<>()}));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void assertIntercept() {
+ Builder<?> builder = mock(Builder.class);
+ ImplementationDefinition<?> implementationDefinition =
mock(ImplementationDefinition.class);
+ ReceiverTypeDefinition<?> intercepted =
mock(ReceiverTypeDefinition.class);
+ when(builder.constructor(any())).thenReturn((ImplementationDefinition)
implementationDefinition);
+
when(implementationDefinition.intercept(any())).thenReturn((ReceiverTypeDefinition)
intercepted);
+ ConstructorAdviceExecutor executor = new
ConstructorAdviceExecutor(Collections.emptyMap());
+ assertThat(executor.intercept(builder, mock()), is(intercepted));
+ }
+
+ private static final class RecordingConstructorAdvice implements
ConstructorAdvice, AgentPluginEnable {
+
+ private final List<String> queue;
+
+ private final boolean pluginEnabled;
+
+ RecordingConstructorAdvice(final List<String> queue, final boolean
pluginEnabled) {
+ this.queue = queue;
+ this.pluginEnabled = pluginEnabled;
+ }
+
+ @Override
+ public boolean isPluginEnabled() {
+ return pluginEnabled;
+ }
+
+ @Override
+ public void onConstructor(final TargetAdviceObject target, final
Object[] args, final String pluginType) {
+ queue.add(pluginType + " constructor");
+ }
+ }
+
+ private static final class PluginDisabledConstructorAdvice implements
ConstructorAdvice, AgentPluginEnable {
+
+ private final List<String> queue;
+
+ PluginDisabledConstructorAdvice(final List<String> queue) {
+ this.queue = queue;
+ }
+
+ @Override
+ public boolean isPluginEnabled() {
+ return false;
+ }
+
+ @Override
+ public void onConstructor(final TargetAdviceObject target, final
Object[] args, final String pluginType) {
+ queue.add("disabled");
+ }
+ }
+
+ private static final class ThrowingConstructorAdvice implements
ConstructorAdvice {
+
+ @Override
+ public void onConstructor(final TargetAdviceObject target, final
Object[] args, final String pluginType) {
+ throw new IllegalStateException("error");
+ }
+ }
+
+ private static final class SimpleTargetAdviceObject implements
TargetAdviceObject {
+
+ private Object attachment;
+
+ @Override
+ public Object getAttachment() {
+ return attachment;
+ }
+
+ @Override
+ public void setAttachment(final Object attachment) {
+ this.attachment = attachment;
+ }
+ }
+}
diff --git
a/agent/core/src/test/java/org/apache/shardingsphere/agent/core/advisor/executor/type/InstanceMethodAdviceExecutorTest.java
b/agent/core/src/test/java/org/apache/shardingsphere/agent/core/advisor/executor/type/InstanceMethodAdviceExecutorTest.java
new file mode 100644
index 00000000000..cc23ee6adde
--- /dev/null
+++
b/agent/core/src/test/java/org/apache/shardingsphere/agent/core/advisor/executor/type/InstanceMethodAdviceExecutorTest.java
@@ -0,0 +1,233 @@
+/*
+ * 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.advisor.executor.type;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.Setter;
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.dynamic.DynamicType.Builder;
+import
net.bytebuddy.dynamic.DynamicType.Builder.MethodDefinition.ImplementationDefinition;
+import
net.bytebuddy.dynamic.DynamicType.Builder.MethodDefinition.ReceiverTypeDefinition;
+import org.apache.shardingsphere.agent.api.advice.TargetAdviceMethod;
+import org.apache.shardingsphere.agent.api.advice.TargetAdviceObject;
+import org.apache.shardingsphere.agent.api.advice.type.InstanceMethodAdvice;
+import org.apache.shardingsphere.agent.api.plugin.AgentPluginEnable;
+import org.apache.shardingsphere.agent.core.advisor.executor.AdviceExecutor;
+import org.apache.shardingsphere.fixture.targeted.TargetObjectFixture;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class InstanceMethodAdviceExecutorTest {
+
+ @Test
+ void assertAdviceWhenCallableSucceeded() throws
ReflectiveOperationException {
+ List<String> queue = new LinkedList<>();
+ Map<String, Collection<InstanceMethodAdvice>> advices = new
LinkedHashMap<>(2, 1F);
+ advices.put("foo", Collections.singletonList(new
RecordingInstanceMethodAdvice(queue, "plain")));
+ advices.put("bar", Collections.singletonList(new
ConfigurableInstanceMethodAdvice(queue, "config", false, false, false, false)));
+ InstanceMethodAdviceExecutor executor = new
InstanceMethodAdviceExecutor(advices);
+ Method method = TargetObjectFixture.class.getMethod("call",
List.class);
+ Callable<Object> callable = () -> {
+ queue.add("origin call");
+ return "result";
+ };
+ assertThat(executor.advice(new SimpleTargetAdviceObject(), method, new
Object[]{queue}, callable), is("result"));
+ assertThat(queue, is(Arrays.asList("plain before foo", "origin call",
"plain after foo")));
+ }
+
+ @Test
+ void assertAdviceWhenCallableThrows() throws ReflectiveOperationException {
+ List<String> queue = new LinkedList<>();
+ Map<String, Collection<InstanceMethodAdvice>> advices = new
LinkedHashMap<>(2, 1F);
+ advices.put("foo", Collections.singletonList(new
RecordingInstanceMethodAdvice(queue, "plain")));
+ advices.put("bar", Collections.singletonList(new
ConfigurableInstanceMethodAdvice(queue, "config", true, false, false, true)));
+ InstanceMethodAdviceExecutor executor = new
InstanceMethodAdviceExecutor(advices);
+ Method method =
TargetObjectFixture.class.getMethod("callWhenExceptionThrown", List.class);
+ Callable<Object> callable = () -> {
+ throw new IllegalStateException("callable error");
+ };
+ assertThrows(IllegalStateException.class, () -> executor.advice(new
SimpleTargetAdviceObject(), method, new Object[]{queue}, callable));
+ assertThat(queue, is(Arrays.asList("plain before foo", "config before
bar", "plain throw foo", "plain after foo", "config after bar")));
+ }
+
+ @Test
+ void assertAdviceWhenCallableThrowsWithoutOnThrowingException() throws
ReflectiveOperationException {
+ List<String> queue = new LinkedList<>();
+ Map<String, Collection<InstanceMethodAdvice>> advices = new
LinkedHashMap<>(1, 1F);
+ advices.put("foo", Collections.singletonList(new
RecordingInstanceMethodAdvice(queue, "plain")));
+ InstanceMethodAdviceExecutor executor = new
InstanceMethodAdviceExecutor(advices);
+ Method method =
TargetObjectFixture.class.getMethod("callWhenExceptionThrown", List.class);
+ Callable<Object> callable = () -> {
+ throw new IllegalStateException("callable error");
+ };
+ assertThrows(IllegalStateException.class, () -> executor.advice(new
SimpleTargetAdviceObject(), method, new Object[]{queue}, callable));
+ assertThat(queue, is(Arrays.asList("plain before foo", "plain throw
foo", "plain after foo")));
+ }
+
+ @Test
+ void assertAdviceWhenCallableThrowsWithPluginDisabled() throws
ReflectiveOperationException {
+ List<String> queue = new LinkedList<>();
+ Map<String, Collection<InstanceMethodAdvice>> advices = new
LinkedHashMap<>(1, 1F);
+ advices.put("foo", Collections.singletonList(new
ConfigurableInstanceMethodAdvice(queue, "disabled", false, false, false,
false)));
+ InstanceMethodAdviceExecutor executor = new
InstanceMethodAdviceExecutor(advices);
+ Method method =
TargetObjectFixture.class.getMethod("callWhenExceptionThrown", List.class);
+ Callable<Object> callable = () -> {
+ throw new IllegalStateException("callable error");
+ };
+ assertThrows(IllegalStateException.class, () -> executor.advice(new
SimpleTargetAdviceObject(), method, new Object[]{queue}, callable));
+ assertThat(queue, is(Collections.emptyList()));
+ }
+
+ @Test
+ void assertAdviceWhenBeforeThrows() throws ReflectiveOperationException {
+ List<String> queue = new LinkedList<>();
+ Map<String, Collection<InstanceMethodAdvice>> advices = new
LinkedHashMap<>(2, 1F);
+ advices.put("foo", Collections.singletonList(new
ConfigurableInstanceMethodAdvice(queue, "first", true, true, false, false)));
+ advices.put("bar", Collections.singletonList(new
RecordingInstanceMethodAdvice(queue, "second")));
+ InstanceMethodAdviceExecutor executor = new
InstanceMethodAdviceExecutor(advices);
+ Method method = TargetObjectFixture.class.getMethod("call",
List.class);
+ Callable<Object> callable = () -> {
+ queue.add("origin call");
+ return "result";
+ };
+ assertThat(executor.advice(new SimpleTargetAdviceObject(), method, new
Object[]{queue}, callable), is("result"));
+ assertThat(queue, is(Arrays.asList("origin call", "first after foo",
"second after bar")));
+ }
+
+ @Test
+ void assertAdviceWhenAfterThrows() throws ReflectiveOperationException {
+ List<String> queue = new LinkedList<>();
+ Map<String, Collection<InstanceMethodAdvice>> advices = new
LinkedHashMap<>(2, 1F);
+ advices.put("foo", Collections.singletonList(new
ConfigurableInstanceMethodAdvice(queue, "first", true, false, true, false)));
+ advices.put("bar", Collections.singletonList(new
RecordingInstanceMethodAdvice(queue, "second")));
+ InstanceMethodAdviceExecutor executor = new
InstanceMethodAdviceExecutor(advices);
+ Method method = TargetObjectFixture.class.getMethod("call",
List.class);
+ Callable<Object> callable = () -> {
+ queue.add("origin call");
+ return "result";
+ };
+ assertThat(executor.advice(new SimpleTargetAdviceObject(), method, new
Object[]{queue}, callable), is("result"));
+ assertThat(queue, is(Arrays.asList("first before foo", "second before
bar", "origin call")));
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ void assertIntercept() {
+ Builder<?> builder = mock(Builder.class);
+ ImplementationDefinition<?> implementationDefinition =
mock(ImplementationDefinition.class);
+ ReceiverTypeDefinition<?> intercepted =
mock(ReceiverTypeDefinition.class);
+ MethodDescription methodDescription = mock(MethodDescription.class);
+ when(builder.method(any())).thenReturn((ImplementationDefinition)
implementationDefinition);
+
when(implementationDefinition.intercept(any())).thenReturn((ReceiverTypeDefinition)
intercepted);
+ AdviceExecutor executor = new
InstanceMethodAdviceExecutor(Collections.emptyMap());
+ Builder<?> actual = executor.intercept(builder, methodDescription);
+ assertThat(actual, is(intercepted));
+ }
+
+ @RequiredArgsConstructor
+ private static final class RecordingInstanceMethodAdvice implements
InstanceMethodAdvice {
+
+ private final List<String> queue;
+
+ private final String label;
+
+ @Override
+ public void beforeMethod(final TargetAdviceObject target, final
TargetAdviceMethod method, final Object[] args, final String pluginType) {
+ queue.add(label + " before " + pluginType);
+ }
+
+ @Override
+ public void afterMethod(final TargetAdviceObject target, final
TargetAdviceMethod method, final Object[] args, final Object result, final
String pluginType) {
+ queue.add(label + " after " + pluginType);
+ }
+
+ @Override
+ public void onThrowing(final TargetAdviceObject target, final
TargetAdviceMethod method, final Object[] args, final Throwable throwable,
final String pluginType) {
+ queue.add(label + " throw " + pluginType);
+ }
+ }
+
+ @RequiredArgsConstructor
+ private static final class ConfigurableInstanceMethodAdvice implements
InstanceMethodAdvice, AgentPluginEnable {
+
+ private final List<String> queue;
+
+ private final String label;
+
+ private final boolean pluginEnabled;
+
+ private final boolean throwBefore;
+
+ private final boolean throwAfter;
+
+ private final boolean throwOnThrow;
+
+ @Override
+ public boolean isPluginEnabled() {
+ return pluginEnabled;
+ }
+
+ @Override
+ public void beforeMethod(final TargetAdviceObject target, final
TargetAdviceMethod method, final Object[] args, final String pluginType) {
+ if (throwBefore) {
+ throw new IllegalStateException("before");
+ }
+ queue.add(label + " before " + pluginType);
+ }
+
+ @Override
+ public void afterMethod(final TargetAdviceObject target, final
TargetAdviceMethod method, final Object[] args, final Object result, final
String pluginType) {
+ if (throwAfter) {
+ throw new IllegalStateException("after");
+ }
+ queue.add(label + " after " + pluginType);
+ }
+
+ @Override
+ public void onThrowing(final TargetAdviceObject target, final
TargetAdviceMethod method, final Object[] args, final Throwable throwable,
final String pluginType) {
+ if (throwOnThrow) {
+ throw new IllegalStateException("throw");
+ }
+ queue.add(label + " throw " + pluginType);
+ }
+ }
+
+ @Getter
+ @Setter
+ private static final class SimpleTargetAdviceObject implements
TargetAdviceObject {
+
+ private Object attachment;
+ }
+}
diff --git
a/agent/core/src/test/java/org/apache/shardingsphere/agent/core/advisor/executor/type/StaticMethodAdviceExecutorTest.java
b/agent/core/src/test/java/org/apache/shardingsphere/agent/core/advisor/executor/type/StaticMethodAdviceExecutorTest.java
new file mode 100644
index 00000000000..299a5ac2723
--- /dev/null
+++
b/agent/core/src/test/java/org/apache/shardingsphere/agent/core/advisor/executor/type/StaticMethodAdviceExecutorTest.java
@@ -0,0 +1,212 @@
+/*
+ * 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.advisor.executor.type;
+
+import lombok.RequiredArgsConstructor;
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.dynamic.DynamicType.Builder;
+import
net.bytebuddy.dynamic.DynamicType.Builder.MethodDefinition.ImplementationDefinition;
+import
net.bytebuddy.dynamic.DynamicType.Builder.MethodDefinition.ReceiverTypeDefinition;
+import org.apache.shardingsphere.agent.api.advice.TargetAdviceMethod;
+import org.apache.shardingsphere.agent.api.advice.type.StaticMethodAdvice;
+import org.apache.shardingsphere.agent.api.plugin.AgentPluginEnable;
+import org.apache.shardingsphere.agent.core.advisor.executor.AdviceExecutor;
+import org.apache.shardingsphere.fixture.targeted.TargetObjectFixture;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class StaticMethodAdviceExecutorTest {
+
+ @Test
+ void assertAdviceWhenCallableSucceeded() throws
ReflectiveOperationException {
+ List<String> queue = new LinkedList<>();
+ Map<String, Collection<StaticMethodAdvice>> advices = new
LinkedHashMap<>(2, 1F);
+ advices.put("foo", Collections.singletonList(new
RecordingStaticMethodAdvice(queue, "plain")));
+ advices.put("bar", Collections.singletonList(new
ConfigurableStaticMethodAdvice(queue, "config", false, false, false, false)));
+ StaticMethodAdviceExecutor executor = new
StaticMethodAdviceExecutor(advices);
+ Method method = TargetObjectFixture.class.getMethod("staticCall",
List.class);
+ Callable<Object> callable = () -> {
+ queue.add("origin call");
+ return "result";
+ };
+ Object actualResult = executor.advice(TargetObjectFixture.class,
method, new Object[]{queue}, callable);
+ assertThat(actualResult, is("result"));
+ assertThat(queue, is(Arrays.asList("plain before foo", "origin call",
"plain after foo")));
+ }
+
+ @Test
+ void assertAdviceWhenCallableThrows() throws ReflectiveOperationException {
+ List<String> queue = new LinkedList<>();
+ Map<String, Collection<StaticMethodAdvice>> advices = new
LinkedHashMap<>(2, 1F);
+ advices.put("foo", Collections.singletonList(new
RecordingStaticMethodAdvice(queue, "plain")));
+ advices.put("bar", Collections.singletonList(new
ConfigurableStaticMethodAdvice(queue, "config", true, false, false, true)));
+ StaticMethodAdviceExecutor executor = new
StaticMethodAdviceExecutor(advices);
+ Method method =
TargetObjectFixture.class.getMethod("staticCallWhenExceptionThrown",
List.class);
+ Callable<Object> callable = () -> {
+ throw new IllegalStateException("callable error");
+ };
+ assertThrows(IllegalStateException.class, () ->
executor.advice(TargetObjectFixture.class, method, new Object[]{queue},
callable));
+ assertThat(queue, is(Arrays.asList("plain before foo", "config before
bar", "plain throw foo", "plain after foo", "config after bar")));
+ }
+
+ @Test
+ void assertAdviceWhenCallableThrowsWithPluginDisabled() throws
ReflectiveOperationException {
+ List<String> queue = new LinkedList<>();
+ Map<String, Collection<StaticMethodAdvice>> advices =
Collections.singletonMap(
+ "foo", Collections.singletonList(new
ConfigurableStaticMethodAdvice(queue, "disabled", false, false, false, false)));
+ StaticMethodAdviceExecutor executor = new
StaticMethodAdviceExecutor(advices);
+ Method method =
TargetObjectFixture.class.getMethod("staticCallWhenExceptionThrown",
List.class);
+ Callable<Object> callable = () -> {
+ throw new IllegalStateException("callable error");
+ };
+ assertThrows(IllegalStateException.class, () ->
executor.advice(TargetObjectFixture.class, method, new Object[]{queue},
callable));
+ assertTrue(queue.isEmpty());
+ }
+
+ @Test
+ void assertAdviceWhenBeforeThrows() throws ReflectiveOperationException {
+ List<String> queue = new LinkedList<>();
+ Map<String, Collection<StaticMethodAdvice>> advices = new
LinkedHashMap<>(2, 1F);
+ advices.put("foo", Collections.singletonList(new
ConfigurableStaticMethodAdvice(queue, "first", true, true, false, false)));
+ advices.put("bar", Collections.singletonList(new
RecordingStaticMethodAdvice(queue, "second")));
+ StaticMethodAdviceExecutor executor = new
StaticMethodAdviceExecutor(advices);
+ Method method = TargetObjectFixture.class.getMethod("staticCall",
List.class);
+ Callable<Object> callable = () -> {
+ queue.add("origin call");
+ return "result";
+ };
+ Object actualResult = executor.advice(TargetObjectFixture.class,
method, new Object[]{queue}, callable);
+ assertThat(actualResult, is("result"));
+ assertThat(queue, is(Arrays.asList("origin call", "first after foo",
"second after bar")));
+ }
+
+ @Test
+ void assertAdviceWhenAfterThrows() throws ReflectiveOperationException {
+ List<String> queue = new LinkedList<>();
+ Map<String, Collection<StaticMethodAdvice>> advices = new
LinkedHashMap<>(2, 1F);
+ advices.put("foo", Collections.singletonList(new
ConfigurableStaticMethodAdvice(queue, "first", true, false, true, false)));
+ advices.put("bar", Collections.singletonList(new
RecordingStaticMethodAdvice(queue, "second")));
+ StaticMethodAdviceExecutor executor = new
StaticMethodAdviceExecutor(advices);
+ Method method = TargetObjectFixture.class.getMethod("staticCall",
List.class);
+ Callable<Object> callable = () -> {
+ queue.add("origin call");
+ return "result";
+ };
+ Object actualResult = executor.advice(TargetObjectFixture.class,
method, new Object[]{queue}, callable);
+ assertThat(actualResult, is("result"));
+ assertThat(queue, is(Arrays.asList("first before foo", "second before
bar", "origin call")));
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ @Test
+ void assertIntercept() {
+ Builder<?> builder = mock(Builder.class);
+ ImplementationDefinition<?> implementationDefinition =
mock(ImplementationDefinition.class);
+ ReceiverTypeDefinition<?> intercepted =
mock(ReceiverTypeDefinition.class);
+ MethodDescription methodDescription = mock(MethodDescription.class);
+ when(builder.method(any())).thenReturn((ImplementationDefinition)
implementationDefinition);
+
when(implementationDefinition.intercept(any())).thenReturn((ReceiverTypeDefinition)
intercepted);
+ AdviceExecutor executor = new
StaticMethodAdviceExecutor(Collections.emptyMap());
+ assertThat(executor.intercept(builder, methodDescription),
is(intercepted));
+ }
+
+ @RequiredArgsConstructor
+ private static final class RecordingStaticMethodAdvice implements
StaticMethodAdvice {
+
+ private final List<String> queue;
+
+ private final String label;
+
+ @Override
+ public void beforeMethod(final Class<?> clazz, final
TargetAdviceMethod method, final Object[] args, final String pluginType) {
+ queue.add(label + " before " + pluginType);
+ }
+
+ @Override
+ public void afterMethod(final Class<?> clazz, final TargetAdviceMethod
method, final Object[] args, final Object result, final String pluginType) {
+ queue.add(label + " after " + pluginType);
+ }
+
+ @Override
+ public void onThrowing(final Class<?> clazz, final TargetAdviceMethod
method, final Object[] args, final Throwable throwable, final String
pluginType) {
+ queue.add(label + " throw " + pluginType);
+ }
+ }
+
+ @RequiredArgsConstructor
+ private static final class ConfigurableStaticMethodAdvice implements
StaticMethodAdvice, AgentPluginEnable {
+
+ private final List<String> queue;
+
+ private final String label;
+
+ private final boolean pluginEnabled;
+
+ private final boolean throwBefore;
+
+ private final boolean throwAfter;
+
+ private final boolean throwOnThrow;
+
+ @Override
+ public boolean isPluginEnabled() {
+ return pluginEnabled;
+ }
+
+ @Override
+ public void beforeMethod(final Class<?> clazz, final
TargetAdviceMethod method, final Object[] args, final String pluginType) {
+ if (throwBefore) {
+ throw new IllegalStateException("before");
+ }
+ queue.add(label + " before " + pluginType);
+ }
+
+ @Override
+ public void afterMethod(final Class<?> clazz, final TargetAdviceMethod
method, final Object[] args, final Object result, final String pluginType) {
+ if (throwAfter) {
+ throw new IllegalStateException("after");
+ }
+ queue.add(label + " after " + pluginType);
+ }
+
+ @Override
+ public void onThrowing(final Class<?> clazz, final TargetAdviceMethod
method, final Object[] args, final Throwable throwable, final String
pluginType) {
+ if (throwOnThrow) {
+ throw new IllegalStateException("throw");
+ }
+ queue.add(label + " throw " + pluginType);
+ }
+ }
+}
diff --git
a/agent/core/src/test/java/org/apache/shardingsphere/agent/core/builder/AgentBuilderFactoryTest.java
b/agent/core/src/test/java/org/apache/shardingsphere/agent/core/builder/AgentBuilderFactoryTest.java
index e51306b373d..5d47e5360b6 100644
---
a/agent/core/src/test/java/org/apache/shardingsphere/agent/core/builder/AgentBuilderFactoryTest.java
+++
b/agent/core/src/test/java/org/apache/shardingsphere/agent/core/builder/AgentBuilderFactoryTest.java
@@ -20,6 +20,7 @@ package org.apache.shardingsphere.agent.core.builder;
import net.bytebuddy.agent.ByteBuddyAgent;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.agent.builder.ResettableClassFileTransformer;
+import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.matcher.ElementMatchers;
import
org.apache.shardingsphere.agent.core.advisor.config.AdvisorConfiguration;
import
org.apache.shardingsphere.agent.core.advisor.config.MethodAdvisorConfiguration;
@@ -41,19 +42,28 @@ import static org.hamcrest.MatcherAssert.assertThat;
class AgentBuilderFactoryTest {
+ private static final String TARGET_CLASS_NAME =
"org.apache.shardingsphere.fixture.targeted.AgentBuilderFactoryTestTarget";
+
private static ResettableClassFileTransformer agent;
+ private static Class<?> targetClass;
+
@BeforeAll
static void setup() {
ByteBuddyAgent.install();
- AdvisorConfiguration advisorConfig = createAdvisorConfiguration();
+ AdvisorConfiguration advisorConfig =
createAdvisorConfiguration(TARGET_CLASS_NAME);
Map<String, AdvisorConfiguration> advisorConfigs =
Collections.singletonMap(advisorConfig.getTargetClassName(), advisorConfig);
AgentBuilder agentBuilder =
AgentBuilderFactory.create(Collections.emptyMap(), Collections.emptyList(),
advisorConfigs, true);
agent = agentBuilder.installOnByteBuddyAgent();
+ targetClass = new
net.bytebuddy.ByteBuddy().redefine(TargetObjectFixture.class)
+ .name(TARGET_CLASS_NAME)
+ .make()
+ .load(AgentBuilderFactoryTest.class.getClassLoader(),
ClassLoadingStrategy.Default.INJECTION)
+ .getLoaded();
}
- private static AdvisorConfiguration createAdvisorConfiguration() {
- AdvisorConfiguration result = new
AdvisorConfiguration("org.apache.shardingsphere.fixture.targeted.TargetObjectFixture");
+ private static AdvisorConfiguration createAdvisorConfiguration(final
String targetClassName) {
+ AdvisorConfiguration result = new
AdvisorConfiguration(targetClassName);
result.getAdvisors().add(new
MethodAdvisorConfiguration(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(1)),
FooAdvice.class.getName(), "FIXTURE"));
result.getAdvisors().add(new
MethodAdvisorConfiguration(ElementMatchers.isConstructor().and(ElementMatchers.takesArguments(1)),
BarAdvice.class.getName(), "FIXTURE"));
result.getAdvisors().add(new
MethodAdvisorConfiguration(ElementMatchers.named("call"),
FooAdvice.class.getName(), "FIXTURE"));
@@ -75,14 +85,15 @@ class AgentBuilderFactoryTest {
@Test
void assertAdviceConstructor() {
List<String> queue = new LinkedList<>();
- new TargetObjectFixture(queue);
+ invokeConstructor(queue);
assertThat(queue, is(Arrays.asList("on constructor", "foo
constructor", "bar constructor")));
}
@Test
void assertAdviceInstanceMethod() {
List<String> queue = new LinkedList<>();
- new TargetObjectFixture(new LinkedList<>()).call(queue);
+ invokeConstructor(new LinkedList<>());
+ invokeInstance("call", queue);
assertThat(queue, is(Arrays.asList("foo before instance method", "bar
before instance method", "on instance method", "foo after instance method",
"bar after instance method")));
}
@@ -90,7 +101,8 @@ class AgentBuilderFactoryTest {
void assertAdviceInstanceMethodWhenExceptionThrown() {
List<String> queue = new LinkedList<>();
try {
- new TargetObjectFixture(new
LinkedList<>()).callWhenExceptionThrown(queue);
+ invokeConstructor(new LinkedList<>());
+ invokeInstance("callWhenExceptionThrown", queue);
} catch (final UnsupportedOperationException ignored) {
}
assertThat(queue, is(Arrays.asList("foo before instance method", "bar
before instance method",
@@ -100,7 +112,7 @@ class AgentBuilderFactoryTest {
@Test
void assertAdviceStaticMethod() {
List<String> queue = new LinkedList<>();
- TargetObjectFixture.staticCall(queue);
+ invokeStatic("staticCall", queue);
assertThat(queue, is(Arrays.asList("foo before static method", "bar
before static method", "on static method", "foo after static method", "bar
after static method")));
}
@@ -108,10 +120,41 @@ class AgentBuilderFactoryTest {
void assertAdviceStaticMethodWhenExceptionThrown() {
List<String> queue = new LinkedList<>();
try {
- TargetObjectFixture.staticCallWhenExceptionThrown(queue);
+ invokeStatic("staticCallWhenExceptionThrown", queue);
} catch (final UnsupportedOperationException ignored) {
}
assertThat(queue, is(Arrays.asList("foo before static method", "bar
before static method",
"foo throw static method exception", "bar throw static method
exception", "foo after static method", "bar after static method")));
}
+
+ private void invokeConstructor(final List<String> queue) {
+ try {
+ targetClass.getConstructor(List.class).newInstance(queue);
+ } catch (final ReflectiveOperationException ex) {
+ throw new AssertionError("Failed to invoke constructor", ex);
+ }
+ }
+
+ private void invokeInstance(final String methodName, final List<String>
queue) {
+ try {
+ Object instance =
targetClass.getConstructor(List.class).newInstance(new LinkedList<>());
+ targetClass.getMethod(methodName, List.class).invoke(instance,
queue);
+ } catch (final ReflectiveOperationException ex) {
+ if (ex.getCause() instanceof UnsupportedOperationException) {
+ throw (UnsupportedOperationException) ex.getCause();
+ }
+ throw new AssertionError(String.format("Failed to invoke instance
method %s", methodName), ex);
+ }
+ }
+
+ private void invokeStatic(final String methodName, final List<String>
queue) {
+ try {
+ targetClass.getMethod(methodName, List.class).invoke(null, queue);
+ } catch (final ReflectiveOperationException ex) {
+ if (ex.getCause() instanceof UnsupportedOperationException) {
+ throw (UnsupportedOperationException) ex.getCause();
+ }
+ throw new AssertionError(String.format("Failed to invoke static
method %s", methodName), ex);
+ }
+ }
}
diff --git
a/agent/core/src/test/java/org/apache/shardingsphere/agent/core/builder/interceptor/impl/MethodAdvisorBuilderInterceptorTest.java
b/agent/core/src/test/java/org/apache/shardingsphere/agent/core/builder/interceptor/impl/MethodAdvisorBuilderInterceptorTest.java
new file mode 100644
index 00000000000..7041f76b7b2
--- /dev/null
+++
b/agent/core/src/test/java/org/apache/shardingsphere/agent/core/builder/interceptor/impl/MethodAdvisorBuilderInterceptorTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.builder.interceptor.impl;
+
+import net.bytebuddy.description.method.MethodDescription;
+import net.bytebuddy.description.method.MethodList.Explicit;
+import net.bytebuddy.description.type.TypeDescription;
+import net.bytebuddy.dynamic.DynamicType.Builder;
+import
org.apache.shardingsphere.agent.core.advisor.config.AdvisorConfiguration;
+import org.apache.shardingsphere.agent.core.advisor.executor.AdviceExecutor;
+import
org.apache.shardingsphere.agent.core.advisor.executor.AdviceExecutorFactory;
+import org.apache.shardingsphere.agent.core.advisor.executor.AdviceFactory;
+import
org.apache.shardingsphere.agent.core.plugin.classloader.ClassLoaderContext;
+import org.apache.shardingsphere.fixture.targeted.TargetObjectFixture;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.internal.configuration.plugins.Plugins;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+class MethodAdvisorBuilderInterceptorTest {
+
+ @AfterEach
+ void resetCache() throws ReflectiveOperationException {
+ ((Map<?, ?>)
Plugins.getMemberAccessor().get(AdviceFactory.class.getDeclaredField("CACHED_ADVICES"),
null)).clear();
+ ((Map<?, ?>)
Plugins.getMemberAccessor().get(ClassLoaderContext.class.getDeclaredField("AGENT_CLASS_LOADERS"),
null)).clear();
+ }
+
+ @Test
+ void assertInterceptWhenNoMatchedAdvice() throws
ReflectiveOperationException {
+ AdvisorConfiguration advisorConfig = new
AdvisorConfiguration(TargetObjectFixture.class.getName());
+ TypeDescription typeDescription = mock(TypeDescription.class);
+ when(typeDescription.getDeclaredMethods()).thenReturn(new Explicit<>(
+ Collections.singletonList(new
MethodDescription.ForLoadedMethod(TargetObjectFixture.class.getMethod("call",
List.class)))));
+ MethodAdvisorBuilderInterceptor interceptor = new
MethodAdvisorBuilderInterceptor(
+ typeDescription, new ClassLoaderContext(new URLClassLoader(new
URL[0], getClass().getClassLoader()), Collections.emptyList()), advisorConfig);
+ Builder<?> builder = mock(Builder.class);
+ assertThat(interceptor.intercept(builder), is(builder));
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ @Test
+ void assertInterceptWhenAdviceMatched() throws
ReflectiveOperationException {
+ TypeDescription typeDescription = mock(TypeDescription.class);
+ MethodDescription.InDefinedShape methodDescription =
mock(MethodDescription.InDefinedShape.class);
+ when(typeDescription.getDeclaredMethods()).thenReturn(new
Explicit<>(Collections.singletonList(methodDescription)));
+ MethodAdvisorBuilderInterceptor interceptor = new
MethodAdvisorBuilderInterceptor(
+ typeDescription, new ClassLoaderContext(new URLClassLoader(new
URL[0], getClass().getClassLoader()), Collections.emptyList()), new
AdvisorConfiguration("ignored"));
+ AdviceExecutorFactory factory = mock(AdviceExecutorFactory.class);
+ AdviceExecutor adviceExecutor = mock(AdviceExecutor.class);
+ Builder intercepted = mock(Builder.class);
+
when(factory.findMatchedAdviceExecutor(methodDescription)).thenReturn(Optional.of(adviceExecutor));
+ when(adviceExecutor.intercept(any(Builder.class),
any(MethodDescription.class))).thenReturn(intercepted);
+
Plugins.getMemberAccessor().set(MethodAdvisorBuilderInterceptor.class.getDeclaredField("adviceExecutorFactory"),
interceptor, factory);
+ Builder<?> builder = mock(Builder.class);
+ assertThat(interceptor.intercept(builder), is(intercepted));
+ }
+
+ @Test
+ void assertInterceptWhenAdviceInterceptThrows() throws
ReflectiveOperationException {
+ TypeDescription typeDescription = mock(TypeDescription.class);
+ MethodDescription.InDefinedShape methodDescription =
mock(MethodDescription.InDefinedShape.class);
+ when(typeDescription.getDeclaredMethods()).thenReturn(new
Explicit<>(Collections.singletonList(methodDescription)));
+ MethodAdvisorBuilderInterceptor interceptor = new
MethodAdvisorBuilderInterceptor(
+ typeDescription, new ClassLoaderContext(new URLClassLoader(new
URL[0], getClass().getClassLoader()), Collections.emptyList()), new
AdvisorConfiguration("ignored"));
+ AdviceExecutorFactory factory = mock(AdviceExecutorFactory.class);
+ AdviceExecutor adviceExecutor = mock(AdviceExecutor.class);
+
when(factory.findMatchedAdviceExecutor(methodDescription)).thenReturn(Optional.of(adviceExecutor));
+ when(adviceExecutor.intercept(any(Builder.class),
any(MethodDescription.class))).thenThrow(new IllegalStateException("error"));
+
Plugins.getMemberAccessor().set(MethodAdvisorBuilderInterceptor.class.getDeclaredField("adviceExecutorFactory"),
interceptor, factory);
+ Builder<?> builder = mock(Builder.class);
+ assertThat(interceptor.intercept(builder), is(builder));
+ }
+}