This is an automated email from the ASF dual-hosted git repository. jimin pushed a commit to branch 2.x in repository https://gitbox.apache.org/repos/asf/incubator-seata.git
The following commit(s) were added to refs/heads/2.x by this push: new b7e4856bfc test: add test for apm-seata-skywalking-plugin module(#7321) b7e4856bfc is described below commit b7e4856bfcf03fed8d34aedbfa3e7f2e2dbf325d Author: chenxi <16267732+chenxi-n...@users.noreply.github.com> AuthorDate: Mon Apr 28 11:18:33 2025 +0800 test: add test for apm-seata-skywalking-plugin module(#7321) --- .gitignore | 4 + ext/apm-seata-skywalking-plugin/pom.xml | 26 ++++++ .../apm/skywalking/plugin/common/SWSeataUtils.java | 8 +- .../DefaultCoreDoGlobalCommitInterceptorTest.java | 89 ++++++++++++++++++ ...NettyRemotingClientSendSyncInterceptorTest.java | 100 +++++++++++++++++++++ .../RemotingProcessorProcessInterceptorTest.java | 94 +++++++++++++++++++ .../AbstractNettyRemotingInstrumentationTest.java | 36 ++++++++ .../define/DefaultCoreInstrumentationTest.java | 35 ++++++++ .../RemotingProcessorInstrumentationTest.java | 35 ++++++++ 9 files changed, 423 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 6400c2c9dd..2eb9470ffe 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,10 @@ dependency-reduced-pom.xml .settings/ .project .classpath +.factorypath + +# vscode ignore +.vscode # idea ignore .idea/ diff --git a/ext/apm-seata-skywalking-plugin/pom.xml b/ext/apm-seata-skywalking-plugin/pom.xml index 014b36b571..3aacdb60e9 100644 --- a/ext/apm-seata-skywalking-plugin/pom.xml +++ b/ext/apm-seata-skywalking-plugin/pom.xml @@ -67,6 +67,32 @@ </exclusions> <scope>provided</scope> </dependency> + + <!-- Testing dependencies --> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + <version>5.8.2</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>4.0.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <version>4.0.0</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>1.7.36</version> + <scope>test</scope> + </dependency> </dependencies> <build> diff --git a/ext/apm-seata-skywalking-plugin/src/main/java/org/apache/seata/apm/skywalking/plugin/common/SWSeataUtils.java b/ext/apm-seata-skywalking-plugin/src/main/java/org/apache/seata/apm/skywalking/plugin/common/SWSeataUtils.java index 633493eaca..5079fdad7f 100644 --- a/ext/apm-seata-skywalking-plugin/src/main/java/org/apache/seata/apm/skywalking/plugin/common/SWSeataUtils.java +++ b/ext/apm-seata-skywalking-plugin/src/main/java/org/apache/seata/apm/skywalking/plugin/common/SWSeataUtils.java @@ -53,10 +53,10 @@ public class SWSeataUtils { String xid = null; try { - xid = SWSeataConstants.TRANSACTION_TRANSMISSION_CLASS_NAME_MAPPING.get(requestSimpleName) != null - ? (String) SWSeataConstants.TRANSACTION_TRANSMISSION_CLASS_NAME_MAPPING.get(requestSimpleName) - .getDeclaredMethod("getXid").invoke(subMessage) - : xid; + Class<?> clz = SWSeataConstants.TRANSACTION_TRANSMISSION_CLASS_NAME_MAPPING.get(requestSimpleName); + if (clz != null) { + xid = (String) clz.getDeclaredMethod("getXid").invoke(subMessage); + } } catch (Throwable e) { LOGGER.error("convert seata xid failure", e); } diff --git a/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/DefaultCoreDoGlobalCommitInterceptorTest.java b/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/DefaultCoreDoGlobalCommitInterceptorTest.java new file mode 100644 index 0000000000..c9f6b935b2 --- /dev/null +++ b/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/DefaultCoreDoGlobalCommitInterceptorTest.java @@ -0,0 +1,89 @@ +/* + * 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.seata.apm.skywalking.plugin; + +import org.apache.seata.core.protocol.RpcMessage; +import org.apache.seata.core.protocol.transaction.GlobalCommitRequest; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.StringTag; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.lang.reflect.Method; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class DefaultCoreDoGlobalCommitInterceptorTest { + + private DefaultCoreDoGlobalCommitInterceptor interceptor; + private EnhancedInstance enhancedInstance; + private Method method; + private MethodInterceptResult result; + + @BeforeEach + public void setUp() throws Exception { + interceptor = new DefaultCoreDoGlobalCommitInterceptor(); + enhancedInstance = mock(EnhancedInstance.class); + method = Object.class.getDeclaredMethod("toString"); + result = mock(MethodInterceptResult.class); + } + + @Test + public void testBeforeAndAfterMethod() throws Throwable { + // Given + RpcMessage rpcMessage = new RpcMessage(); + GlobalCommitRequest request = new GlobalCommitRequest(); + request.setXid("test-xid"); + rpcMessage.setBody(request); + + Object[] allArguments = new Object[] { rpcMessage }; + Class<?>[] argumentTypes = new Class[] { RpcMessage.class }; + + try (MockedStatic<ContextManager> contextManagerMockedStatic = Mockito.mockStatic(ContextManager.class)) { + AbstractSpan span = mock(AbstractSpan.class); + contextManagerMockedStatic.when(() -> ContextManager.createLocalSpan(anyString())).thenReturn(span); + + // When + interceptor.beforeMethod(enhancedInstance, method, allArguments, argumentTypes, result); + + // Then + verify(span, atLeastOnce()).setComponent(any()); + verify(span, atLeastOnce()).tag(any(StringTag.class), any(String.class)); + } + + // afterMethod should call ContextManager.stopSpan if body is AbstractMessage + try (MockedStatic<ContextManager> contextManagerMockedStatic = Mockito.mockStatic(ContextManager.class)) { + contextManagerMockedStatic.when(ContextManager::stopSpan).then(invocation -> null); + + // When + interceptor.afterMethod(enhancedInstance, method, allArguments, argumentTypes, null); + + // Then + contextManagerMockedStatic.verify(ContextManager::stopSpan, times(1)); + } + } +} diff --git a/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/NettyRemotingClientSendSyncInterceptorTest.java b/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/NettyRemotingClientSendSyncInterceptorTest.java new file mode 100644 index 0000000000..6e97fe1a2c --- /dev/null +++ b/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/NettyRemotingClientSendSyncInterceptorTest.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.seata.apm.skywalking.plugin; + +import io.netty.channel.Channel; +import org.apache.seata.core.protocol.RpcMessage; +import org.apache.seata.core.protocol.transaction.GlobalCommitRequest; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.StringTag; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.lang.reflect.Method; +import java.util.HashMap; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class NettyRemotingClientSendSyncInterceptorTest { + + private NettyRemotingClientSendSyncInterceptor interceptor; + private EnhancedInstance enhancedInstance; + private Method method; + private MethodInterceptResult result; + + @BeforeEach + public void setUp() throws Exception { + interceptor = new NettyRemotingClientSendSyncInterceptor(); + enhancedInstance = mock(EnhancedInstance.class); + method = Object.class.getDeclaredMethod("toString"); + result = mock(MethodInterceptResult.class); + } + + @Test + public void testBeforeAndAfterMethod() throws Throwable { + // Given + Channel channel = mock(Channel.class); + when(channel.remoteAddress()).thenReturn(new java.net.InetSocketAddress("127.0.0.1", 8091)); + RpcMessage rpcMessage = new RpcMessage(); + GlobalCommitRequest request = new GlobalCommitRequest(); + request.setXid("test-xid"); + rpcMessage.setBody(request); + rpcMessage.setHeadMap(new HashMap<>()); + + Object[] allArguments = new Object[] { channel, rpcMessage }; + Class<?>[] argumentTypes = new Class[] { Channel.class, RpcMessage.class }; + + try (MockedStatic<ContextManager> contextManagerMockedStatic = Mockito.mockStatic(ContextManager.class)) { + AbstractSpan span = mock(AbstractSpan.class); + contextManagerMockedStatic + .when(() -> ContextManager.createExitSpan(anyString(), any(ContextCarrier.class), anyString())) + .thenReturn(span); + + // When + interceptor.beforeMethod(enhancedInstance, method, allArguments, argumentTypes, result); + + // Then + verify(span, atLeastOnce()).setComponent(any()); + verify(span, atLeastOnce()).setPeer(anyString()); + verify(span, atLeastOnce()).tag(any(StringTag.class), any(String.class)); + } + + // afterMethod should call ContextManager.stopSpan if body is AbstractMessage + Object[] afterArgs = new Object[] { rpcMessage }; + try (MockedStatic<ContextManager> contextManagerMockedStatic = Mockito.mockStatic(ContextManager.class)) { + contextManagerMockedStatic.when(ContextManager::stopSpan).then(invocation -> null); + + // When + interceptor.afterMethod(enhancedInstance, method, afterArgs, argumentTypes, null); + + // Then + contextManagerMockedStatic.verify(ContextManager::stopSpan, times(1)); + } + } +} diff --git a/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/RemotingProcessorProcessInterceptorTest.java b/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/RemotingProcessorProcessInterceptorTest.java new file mode 100644 index 0000000000..796ebd9a54 --- /dev/null +++ b/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/RemotingProcessorProcessInterceptorTest.java @@ -0,0 +1,94 @@ +/* + * 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.seata.apm.skywalking.plugin; + +import org.apache.seata.core.protocol.RpcMessage; +import org.apache.seata.core.protocol.transaction.GlobalCommitRequest; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.StringTag; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; + +import java.lang.reflect.Method; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +public class RemotingProcessorProcessInterceptorTest { + + private RemotingProcessorProcessInterceptor interceptor; + private EnhancedInstance enhancedInstance; + private Method method; + private MethodInterceptResult result; + + @BeforeEach + public void setUp() throws Exception { + interceptor = new RemotingProcessorProcessInterceptor(); + enhancedInstance = mock(EnhancedInstance.class); + method = Object.class.getDeclaredMethod("toString"); + result = mock(MethodInterceptResult.class); + } + + @Test + public void testBeforeAndAfterMethod() throws Throwable { + // Given + RpcMessage rpcMessage = new RpcMessage(); + GlobalCommitRequest request = new GlobalCommitRequest(); + request.setXid("test-xid"); + rpcMessage.setBody(request); + rpcMessage.setHeadMap(new java.util.HashMap<>()); + + Object[] allArguments = new Object[] { null, rpcMessage }; + Class<?>[] argumentTypes = new Class[] { Object.class, RpcMessage.class }; + + try (MockedStatic<ContextManager> contextManagerMockedStatic = Mockito.mockStatic(ContextManager.class)) { + AbstractSpan span = mock(AbstractSpan.class); + contextManagerMockedStatic + .when(() -> ContextManager.createEntrySpan(anyString(), any(ContextCarrier.class))) + .thenReturn(span); + + // When + interceptor.beforeMethod(enhancedInstance, method, allArguments, argumentTypes, result); + + // THen + verify(span, atLeastOnce()).setComponent(any()); + verify(span, atLeastOnce()).tag(any(StringTag.class), any(String.class)); + } + + // afterMethod should call ContextManager.stopSpan if body is AbstractMessage + Object[] afterArgs = new Object[] { rpcMessage }; + try (MockedStatic<ContextManager> contextManagerMockedStatic = Mockito.mockStatic(ContextManager.class)) { + contextManagerMockedStatic.when(ContextManager::stopSpan).then(invocation -> null); + + // When + interceptor.afterMethod(enhancedInstance, method, afterArgs, argumentTypes, null); + + // Then + contextManagerMockedStatic.verify(ContextManager::stopSpan, times(1)); + } + } +} diff --git a/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/define/AbstractNettyRemotingInstrumentationTest.java b/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/define/AbstractNettyRemotingInstrumentationTest.java new file mode 100644 index 0000000000..d6023ea821 --- /dev/null +++ b/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/define/AbstractNettyRemotingInstrumentationTest.java @@ -0,0 +1,36 @@ +/* + * 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.seata.apm.skywalking.plugin.define; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class AbstractNettyRemotingInstrumentationTest { + + @Test + void testInterceptPointsNotEmpty() { + AbstractNettyRemotingInstrumentation target = new AbstractNettyRemotingInstrumentation(); + + // Expect: + assertNotNull(target.getConstructorsInterceptPoints()); + // and: + assertNotNull(target.getInstanceMethodsInterceptPoints()); + assertTrue(target.getInstanceMethodsInterceptPoints().length > 0); + } +} diff --git a/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/define/DefaultCoreInstrumentationTest.java b/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/define/DefaultCoreInstrumentationTest.java new file mode 100644 index 0000000000..716a74283c --- /dev/null +++ b/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/define/DefaultCoreInstrumentationTest.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.seata.apm.skywalking.plugin.define; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class DefaultCoreInstrumentationTest { + + @Test + void testInterceptPointsNotEmpty() { + DefaultCoreInstrumentation target = new DefaultCoreInstrumentation(); + + assertNotNull(target.getConstructorsInterceptPoints()); + + assertNotNull(target.getInstanceMethodsInterceptPoints()); + assertTrue(target.getInstanceMethodsInterceptPoints().length > 0); + } +} diff --git a/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/define/RemotingProcessorInstrumentationTest.java b/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/define/RemotingProcessorInstrumentationTest.java new file mode 100644 index 0000000000..b06bf0b469 --- /dev/null +++ b/ext/apm-seata-skywalking-plugin/src/test/java/org/apache/seata/apm/skywalking/plugin/define/RemotingProcessorInstrumentationTest.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.seata.apm.skywalking.plugin.define; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class RemotingProcessorInstrumentationTest { + + @Test + void testInterceptPointsNotEmpty() { + RemotingProcessorInstrumentation target = new RemotingProcessorInstrumentation(); + + assertNotNull(target.getConstructorsInterceptPoints()); + + assertNotNull(target.getInstanceMethodsInterceptPoints()); + assertTrue(target.getInstanceMethodsInterceptPoints().length > 0); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@seata.apache.org For additional commands, e-mail: notifications-h...@seata.apache.org