diff --git a/.github/workflows/integration_test.yml b/.github/workflows/integration_test.yml index 8305dde365..9b75891fa2 100644 --- a/.github/workflows/integration_test.yml +++ b/.github/workflows/integration_test.yml @@ -13,8 +13,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - dubbo-version: [ '2-6','2-7' ] - dubbo-versions: [ '0','1','3','5','6','7','8','9','10','11','12' ] + dubbo-version: ['2-6','2-7'] + dubbo-versions: ['0','1','3','5','6','7','8','9','10','11','12'] include: - dubbo-version: '2-6' dubbo-versions: '2' @@ -50,7 +50,7 @@ jobs: tar -zxf apache-zookeeper-3.8.0-bin.tar.gz bash apache-zookeeper-3.8.0-bin/bin/zkServer.sh start apache-zookeeper-3.8.0-bin/conf/zoo_sample.cfg - name: package agent - run: mvn package -DskipTests -Pagent --file pom.xml + run: sed -i '/sermant-backend/d' pom.xml & mvn package -DskipTests -Pagent --file pom.xml - name: package dubbo 2.6.0 tests if: matrix.dubbo-version == '2-6' && matrix.dubbo-versions == '0' run: mvn package -Dalibaba.dubbo.version=2.6.${{ matrix.dubbo-versions }} -DskipTests -P260 --file sermant-integration-tests/dubbo-test/pom.xml @@ -65,44 +65,77 @@ jobs: servicecomb.service.enableDubboRegister: true servicecomb.service.enableSpringRegister: true servicecomb.service.openMigration: false - service.meta.environment: testing - server.port: 38020 - dubbo.protocol.port: 38820 - run: nohup java -javaagent:sermant-agent-1.0.0/agent/sermant-agent.jar=appName=dubbo-integration-provider -jar sermant-integration-tests/dubbo-test/dubbo-${{ matrix.dubbo-version }}-integration-provider/target/dubbo-integration-provider.jar & + SERVICE_META_ENVIRONMENT: testing + SERVER_PORT: 38020 + DUBBO_PROTOCOL_PORT: 38820 + run: | + nohup java -javaagent:sermant-agent-1.0.0/agent/sermant-agent.jar=appName=dubbo-integration-provider -jar \ + sermant-integration-tests/dubbo-test/dubbo-${{ matrix.dubbo-version }}-integration-provider/target/dubbo-integration-provider.jar > spring-and-dubbo-provider.log 2>&1 & - name: start second spring and dubbo provider service env: servicecomb.service.enableDubboRegister: true servicecomb.service.enableSpringRegister: true servicecomb.service.openMigration: false - service.meta.environment: testing - server.port: 38021 - dubbo.protocol.port: 38821 - run: nohup java -javaagent:sermant-agent-1.0.0/agent/sermant-agent.jar=appName=dubbo-integration-provider -jar sermant-integration-tests/dubbo-test/dubbo-${{ matrix.dubbo-version }}-integration-provider/target/dubbo-integration-provider.jar & - - name: start spring and dubbo consumer service - env: - servicecomb.service.enableDubboRegister: true - servicecomb.service.enableSpringRegister: true - servicecomb.service.openMigration: false - service.meta.environment: testing - server.port: 38022 - dubbo.protocol.port: 38822 - run: nohup java -javaagent:sermant-agent-1.0.0/agent/sermant-agent.jar=appName=dubbo-integration-consumer -jar sermant-integration-tests/dubbo-test/dubbo-${{ matrix.dubbo-version }}-integration-consumer/target/dubbo-integration-consumer.jar & + SERVICE_META_ENVIRONMENT: testing + SERVER_PORT: 38021 + DUBBO_PROTOCOL_PORT: 38821 + run: | + nohup java -javaagent:sermant-agent-1.0.0/agent/sermant-agent.jar=appName=dubbo-integration-provider -jar \ + sermant-integration-tests/dubbo-test/dubbo-${{ matrix.dubbo-version }}-integration-provider/target/dubbo-integration-provider.jar > spring-and-dubbo-provider2.log 2>&1 & - name: start provider service env: servicecomb.service.enableDubboRegister: true servicecomb.service.openMigration: false - run: nohup java -javaagent:sermant-agent-1.0.0/agent/sermant-agent.jar=appName=dubbo-integration-provider -jar sermant-integration-tests/dubbo-test/dubbo-${{ matrix.dubbo-version }}-integration-provider/target/dubbo-integration-provider.jar & + run: | + nohup java -javaagent:sermant-agent-1.0.0/agent/sermant-agent.jar=appName=dubbo-integration-provider -jar \ + sermant-integration-tests/dubbo-test/dubbo-${{ matrix.dubbo-version }}-integration-provider/target/dubbo-integration-provider.jar > dubbo-provider.log 2>&1 & - name: start zookeeper provider service env: - server.port: 48021 - dubbo.protocol.port: 48821 - run: nohup java -jar sermant-integration-tests/dubbo-test/dubbo-${{ matrix.dubbo-version }}-integration-provider/target/dubbo-integration-provider.jar & + SERVER_PORT: 48021 + DUBBO_PROTOCOL_PORT: 48821 + run: | + nohup java -jar sermant-integration-tests/dubbo-test/dubbo-${{ matrix.dubbo-version }}-integration-provider/target/dubbo-integration-provider.jar > dubbo-zk-provider.log 2>&1 & + - name: waiting for providers start + run: | + ps -ef | grep java + bash ./sermant-integration-tests/scripts/checkService.sh http://127.0.0.1:48021/ping 120 + bash ./sermant-integration-tests/scripts/checkService.sh http://127.0.0.1:28021/ping 120 + bash ./sermant-integration-tests/scripts/checkService.sh http://127.0.0.1:38021/ping 120 + bash ./sermant-integration-tests/scripts/checkService.sh http://127.0.0.1:38020/ping 120 + ps -ef | grep java + - name: start spring and dubbo consumer service + env: + servicecomb.service.enableDubboRegister: true + servicecomb.service.enableSpringRegister: true + servicecomb.service.openMigration: false + SERVICE_META_ENVIRONMENT: testing + SERVER_PORT: 38022 + DUBBO_PROTOCOL_PORT: 38822 + run: | + nohup java -javaagent:sermant-agent-1.0.0/agent/sermant-agent.jar=appName=dubbo-integration-consumer -jar \ + sermant-integration-tests/dubbo-test/dubbo-${{ matrix.dubbo-version }}-integration-consumer/target/dubbo-integration-consumer.jar > spring-and-dubbo-consumer.log 2>&1 & - name: start consumer service env: servicecomb.service.enableDubboRegister: true servicecomb.service.openMigration: true - run: nohup java -javaagent:sermant-agent-1.0.0/agent/sermant-agent.jar=appName=dubbo-integration-consumer -jar sermant-integration-tests/dubbo-test/dubbo-${{ matrix.dubbo-version }}-integration-consumer/target/dubbo-integration-consumer.jar & - - name: waiting for services start - run: sleep 60s + run: | + nohup java -javaagent:sermant-agent-1.0.0/agent/sermant-agent.jar=appName=dubbo-integration-consumer -jar \ + sermant-integration-tests/dubbo-test/dubbo-${{ matrix.dubbo-version }}-integration-consumer/target/dubbo-integration-consumer.jar > dubbo-consumer.log 2>&1 & + - name: waiting for consumers start + run: | + ps -ef | grep java + bash ./sermant-integration-tests/scripts/checkService.sh http://127.0.0.1:38022/ping 120 + bash ./sermant-integration-tests/scripts/checkService.sh http://127.0.0.1:28820/ping 120 + ps -ef | grep java - name: integration test - run: mvn -Dcontroller.port=38022 test --file sermant-integration-tests/dubbo-test/pom.xml \ No newline at end of file + run: mvn -Dcontroller.port=38022 test --file sermant-integration-tests/dubbo-test/pom.xml + - name: if failure then upload error log + uses: actions/upload-artifact@v3 + if: failure() + with: + name: (test-for-dubbo)-(${{ matrix.dubbo-version }}-${{ matrix.dubbo-versions }})-logs + path: | + ./*.log + ./logs/**/*.log + if-no-files-found: warn + retention-days: 5 \ No newline at end of file diff --git a/sermant-integration-tests/dubbo-test/dubbo-2-6-integration-provider/src/main/resources/application.yaml b/sermant-integration-tests/dubbo-test/dubbo-2-6-integration-provider/src/main/resources/application.yaml index 6db95199c4..fea20ba55e 100644 --- a/sermant-integration-tests/dubbo-test/dubbo-2-6-integration-provider/src/main/resources/application.yaml +++ b/sermant-integration-tests/dubbo-test/dubbo-2-6-integration-provider/src/main/resources/application.yaml @@ -2,7 +2,7 @@ server: port: 28021 dubbo: protocol: - port: 28821 + port: ${DUBBO_PROTOCOL_PORT:28821} spring: application: diff --git a/sermant-integration-tests/dubbo-test/dubbo-2-7-integration-provider/src/main/resources/application.yaml b/sermant-integration-tests/dubbo-test/dubbo-2-7-integration-provider/src/main/resources/application.yaml index 2176ae9747..ca13fbb055 100644 --- a/sermant-integration-tests/dubbo-test/dubbo-2-7-integration-provider/src/main/resources/application.yaml +++ b/sermant-integration-tests/dubbo-test/dubbo-2-7-integration-provider/src/main/resources/application.yaml @@ -4,7 +4,7 @@ dubbo: application: name: dubbo-integration-provider protocol: - port: 28821 + port: ${DUBBO_PROTOCOL_PORT:28821} name: dubbo registry: # 模拟存量dubbo应用注册到zookeeper的情况,新开发的应用建议配置为 sc://127.0.0.1:30100 diff --git a/sermant-integration-tests/dubbo-test/dubbo-integration-api/src/main/java/com/huaweicloud/integration/controller/PingController.java b/sermant-integration-tests/dubbo-test/dubbo-integration-api/src/main/java/com/huaweicloud/integration/controller/PingController.java new file mode 100644 index 0000000000..4274837fb0 --- /dev/null +++ b/sermant-integration-tests/dubbo-test/dubbo-integration-api/src/main/java/com/huaweicloud/integration/controller/PingController.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.integration.controller; + +import org.springframework.context.annotation.Lazy; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * PingController + * + * @author provenceee + * @since 2022-09-13 + */ +@RestController +@Lazy +public class PingController { + /** + * 测试方法 + * + * @return msg + */ + @GetMapping("ping") + public String ping() { + return "ok"; + } +} diff --git a/sermant-integration-tests/dubbo-test/dubbo-integration-test/src/test/java/com/huaweicloud/integration/ConsumerTest.java b/sermant-integration-tests/dubbo-test/dubbo-integration-test/src/test/java/com/huaweicloud/integration/ConsumerTest.java index b7990fdda3..cb23a13b9c 100644 --- a/sermant-integration-tests/dubbo-test/dubbo-integration-test/src/test/java/com/huaweicloud/integration/ConsumerTest.java +++ b/sermant-integration-tests/dubbo-test/dubbo-integration-test/src/test/java/com/huaweicloud/integration/ConsumerTest.java @@ -23,6 +23,7 @@ import java.util.HashSet; import java.util.Set; +import java.util.concurrent.TimeUnit; /** * 测试dubbo接口 @@ -87,7 +88,7 @@ public void testTag() { * 测试多注册中心 */ @Test - public void testMultipleRegistry() { + public void testMultipleRegistry() throws InterruptedException { // 因为多注册中心是随机选择一个注册中心的节点进行访问,所以这里访问100次,这个用例失败并不一定真的失败,需要详细分析 Set set = new HashSet<>(); for (int i = 0; i <= 100; i++) { @@ -95,6 +96,7 @@ public void testMultipleRegistry() { if (set.size() >= 2) { break; } + TimeUnit.SECONDS.sleep(1); } Assertions.assertTrue(set.size() >= 2); } diff --git a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/declarer/AbstractDirectoryDeclarer.java b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/declarer/AbstractDirectoryDeclarer.java index d5d8901848..d0bb85a327 100644 --- a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/declarer/AbstractDirectoryDeclarer.java +++ b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/declarer/AbstractDirectoryDeclarer.java @@ -19,7 +19,7 @@ import com.huaweicloud.sermant.core.plugin.agent.matcher.ClassMatcher; /** - * 增强AbstractDirectory的子类的doList方法,筛选灰度应用的地址 + * 增强AbstractDirectory的子类的doList方法,筛选标签应用的地址 * * @author provenceee * @since 2021-06-28 diff --git a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/interceptor/AbstractDirectoryInterceptor.java b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/interceptor/AbstractDirectoryInterceptor.java index 162b3f8a17..ce8e7b0d66 100644 --- a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/interceptor/AbstractDirectoryInterceptor.java +++ b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/interceptor/AbstractDirectoryInterceptor.java @@ -22,7 +22,7 @@ import com.huaweicloud.sermant.router.dubbo.service.AbstractDirectoryService; /** - * 增强AbstractDirectory的子类的doList方法,筛选灰度应用的地址 + * 增强AbstractDirectory的子类的doList方法,筛选标签应用的地址 * * @author provenceee * @since 2021-06-28 diff --git a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryService.java b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryService.java index cad443eb87..655dd2cb96 100644 --- a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryService.java +++ b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryService.java @@ -26,7 +26,7 @@ */ public interface AbstractDirectoryService extends PluginService { /** - * 筛选灰度invoker + * 筛选标签invoker * * @param obj RegistryDirectory * @param arguments 参数 diff --git a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ApplicationConfigService.java b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ApplicationConfigService.java index bc9cc64f9b..e470634288 100644 --- a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ApplicationConfigService.java +++ b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ApplicationConfigService.java @@ -26,7 +26,7 @@ */ public interface ApplicationConfigService extends PluginService { /** - * 获取dubbo服务名,并设置灰度参数 + * 获取dubbo服务名,并设置标签 * * @param obj 增强的类 * @see com.alibaba.dubbo.config.ApplicationConfig diff --git a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ClusterService.java b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ClusterService.java index 1bb87637bd..ff6f086f65 100644 --- a/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ClusterService.java +++ b/sermant-plugins/sermant-router/dubbo-router-plugin/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ClusterService.java @@ -26,7 +26,7 @@ */ public interface ClusterService extends PluginService { /** - * 从url中缓存接口与下游服务名的映射关系,从map中删除灰度发布相关的参数 + * 从url中缓存接口与下游服务名的映射关系,从map中删除标签相关的参数 * * @param arguments 请求参数 */ diff --git a/sermant-plugins/sermant-router/dubbo-router-plugin/src/test/java/com/huaweicloud/sermant/router/dubbo/DubboReflectUtilsTest.java b/sermant-plugins/sermant-router/dubbo-router-plugin/src/test/java/com/huaweicloud/sermant/router/dubbo/DubboReflectUtilsTest.java index 01c4f25cac..efff043b82 100644 --- a/sermant-plugins/sermant-router/dubbo-router-plugin/src/test/java/com/huaweicloud/sermant/router/dubbo/DubboReflectUtilsTest.java +++ b/sermant-plugins/sermant-router/dubbo-router-plugin/src/test/java/com/huaweicloud/sermant/router/dubbo/DubboReflectUtilsTest.java @@ -18,6 +18,7 @@ import com.huaweicloud.sermant.core.common.CommonConstant; import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.core.utils.StringUtils; import com.huaweicloud.sermant.router.common.utils.ReflectUtils; import com.huaweicloud.sermant.router.dubbo.utils.DubboReflectUtils; @@ -26,8 +27,10 @@ import com.alibaba.dubbo.rpc.Invocation; import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.Result; +import com.alibaba.dubbo.rpc.RpcContext; import com.alibaba.dubbo.rpc.RpcException; +import org.apache.dubbo.common.utils.MapUtils; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -44,10 +47,11 @@ * @since 2022-03-18 */ public class DubboReflectUtilsTest { - private static final URL ALIBABA_URL = URL.valueOf("dubbo://localhost:8080/com.huawei.foo.BarTest?bar=foo"); + private static final URL ALIBABA_URL = URL + .valueOf("dubbo://localhost:8080/com.huaweicloud.foo.BarTest?bar=foo&version=0.0.1"); private static final org.apache.dubbo.common.URL APACHE_URL = org.apache.dubbo.common.URL - .valueOf("dubbo://localhost:8081/com.huawei.foo.FooTest?foo=bar"); + .valueOf("dubbo://localhost:8081/com.huaweicloud.foo.FooTest?foo=bar&version=0.0.1"); private static final String BAR = "bar"; @@ -172,8 +176,8 @@ public void testGetUrl() { */ @Test public void testGetServiceInterface() { - Assert.assertEquals("com.huawei.foo.BarTest", DubboReflectUtils.getServiceInterface(ALIBABA_URL)); - Assert.assertEquals("com.huawei.foo.FooTest", DubboReflectUtils.getServiceInterface(APACHE_URL)); + Assert.assertEquals("com.huaweicloud.foo.BarTest", DubboReflectUtils.getServiceInterface(ALIBABA_URL)); + Assert.assertEquals("com.huaweicloud.foo.FooTest", DubboReflectUtils.getServiceInterface(APACHE_URL)); } /** @@ -220,6 +224,34 @@ public void testSetParameters() { Assert.assertEquals(BAR, apacheConfig.getParameters().get(FOO)); } + /** + * 从Invocation获取attachments + * + * @see com.alibaba.dubbo.rpc.Invocation + * @see org.apache.dubbo.rpc.Invocation + */ + @Test + public void testGetAttachmentsWithInvocation() { + AlibabaInvocation alibabaInvocation = new AlibabaInvocation(); + alibabaInvocation.getAttachments().put(BAR, FOO); + Assert.assertEquals(FOO, DubboReflectUtils.getAttachments(alibabaInvocation).get(BAR)); + + ApacheInvocation apacheInvocation = new ApacheInvocation(); + apacheInvocation.getObjectAttachments().put(FOO, BAR); + Assert.assertEquals(BAR, DubboReflectUtils.getAttachments(apacheInvocation).get(FOO)); + } + + /** + * 从RpcContext获取attachments + * + * @see com.alibaba.dubbo.rpc.RpcContext + */ + @Test + public void testGetAttachmentsWithRpcContext() { + RpcContext.getContext().getAttachments().put(BAR, FOO); + Assert.assertEquals(FOO, DubboReflectUtils.getAttachments(new AlibabaInvocation()).get(BAR)); + } + /** * 获取权限检查类 */ @@ -319,6 +351,8 @@ public void destroy() { * @since 2022-03-18 */ public static class AlibabaInvocation implements Invocation { + private final Map attachments = new HashMap<>(); + @Override public String getMethodName() { return "BarTest"; @@ -326,7 +360,7 @@ public String getMethodName() { @Override public Class[] getParameterTypes() { - return new Class[0]; + return new Class[]{String.class, String.class}; } @Override @@ -336,17 +370,17 @@ public Object[] getArguments() { @Override public Map getAttachments() { - return Collections.emptyMap(); + return attachments; } @Override - public String getAttachment(String str) { - return ""; + public String getAttachment(String key) { + return attachments.get(key); } @Override - public String getAttachment(String str, String str1) { - return ""; + public String getAttachment(String key, String defaultValue) { + return attachments.getOrDefault(key, defaultValue); } @Override @@ -376,6 +410,8 @@ public Map getAttributes() { * @since 2022-03-18 */ public static class ApacheInvocation implements org.apache.dubbo.rpc.Invocation { + private final Map attachments = new HashMap<>(); + @Override public String getTargetServiceUniqueName() { return ""; @@ -398,7 +434,7 @@ public String getServiceName() { @Override public Class[] getParameterTypes() { - return new Class[0]; + return new Class[]{String.class, String.class}; } @Override @@ -408,56 +444,68 @@ public Object[] getArguments() { @Override public Map getAttachments() { - return Collections.emptyMap(); + return MapUtils.objectToStringMap(attachments); } @Override public Map getObjectAttachments() { - return Collections.emptyMap(); + return attachments; } @Override public void setAttachment(String key, String value) { + attachments.put(key, value); } @Override public void setAttachment(String key, Object value) { + attachments.put(key, value); } @Override public void setObjectAttachment(String key, Object value) { + attachments.put(key, value); } @Override public void setAttachmentIfAbsent(String key, String value) { + attachments.putIfAbsent(key, value); } @Override public void setAttachmentIfAbsent(String key, Object value) { + attachments.putIfAbsent(key, value); } @Override public void setObjectAttachmentIfAbsent(String key, Object value) { + attachments.putIfAbsent(key, value); } @Override public String getAttachment(String key) { - return ""; + Object value = attachments.get(key); + return value instanceof String ? (String) value : null; } @Override public String getAttachment(String key, String defaultValue) { - return ""; + Object value = attachments.get(key); + if (value instanceof String) { + String strValue = (String) value; + return StringUtils.isBlank(strValue) ? defaultValue : strValue; + } + return defaultValue; } @Override public Object getObjectAttachment(String key) { - return new Object(); + return attachments.get(key); } @Override public Object getObjectAttachment(String key, Object defaultValue) { - return ""; + return attachments.getOrDefault(key, defaultValue); } @Override diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceImpl.java b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceImpl.java index 8f34dd8ba1..020c73a0fd 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceImpl.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceImpl.java @@ -49,7 +49,7 @@ public class AbstractDirectoryServiceImpl implements AbstractDirectoryService { private static final String CONSUMER_VALUE = "consumer"; /** - * 筛选灰度invoker + * 筛选标签invoker * * @param obj RegistryDirectory * @param arguments 参数 diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ApplicationConfigServiceImpl.java b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ApplicationConfigServiceImpl.java index e4d7e3a605..29dbb30e8c 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ApplicationConfigServiceImpl.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ApplicationConfigServiceImpl.java @@ -44,7 +44,7 @@ public ApplicationConfigServiceImpl() { } /** - * 获取dubbo服务名,并设置灰度参数 + * 获取dubbo服务名,并设置标签 * * @param obj 增强的类 * @see com.alibaba.dubbo.config.ApplicationConfig diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ClusterServiceImpl.java b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ClusterServiceImpl.java index a1e4b9d2ad..538a34ac0f 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ClusterServiceImpl.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/service/ClusterServiceImpl.java @@ -35,7 +35,7 @@ public class ClusterServiceImpl implements ClusterService { private static final int EXPECT_LENGTH = 2; /** - * 从url中缓存接口与下游服务名的映射关系,从map中删除灰度发布相关的参数 + * 从url中缓存接口与下游服务名的映射关系,从map中删除标签相关的参数 * * @param arguments 请求参数 * @see com.alibaba.dubbo.common.URL @@ -51,7 +51,7 @@ public void doBefore(Object[] arguments) { DubboCache.INSTANCE.putApplication(DubboReflectUtils.getServiceInterface(arguments[0]), DubboReflectUtils.getParameter(arguments[0], APPLICATION_KEY)); if (arguments[1] instanceof Map) { - // 本地参数的map,需要把这个map中的灰度参数删除,才能让下游invoker的灰度参数不被本地参数覆盖,即保留下游invoker的灰度参数 + // 本地参数的map,需要把这个map中的标签删除,才能让下游invoker的标签不被本地参数覆盖,即保留下游invoker的标签 Map localMap = new HashMap<>((Map) arguments[1]); localMap.entrySet().removeIf(entry -> entry.getKey().startsWith(RouterConstant.PARAMETERS_KEY_PREFIX) || RouterConstant.VERSION_KEY.equals(entry.getKey())); diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandler.java b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandler.java index 271076573c..242ef07493 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandler.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/main/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandler.java @@ -42,11 +42,11 @@ public enum RuleStrategyHandler { } /** - * 选取灰度应用的invokers + * 选取标签应用的invokers * * @param routes 路由规则 * @param invokers dubbo invokers - * @return 灰度应用的invokers + * @return 标签应用的invokers */ public List getTargetInvoker(List routes, List invokers) { return ruleStrategy.getTargetInstances(routes, invokers); diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/AlibabaInvoker.java b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/AlibabaInvoker.java new file mode 100644 index 0000000000..81c5c8a6bc --- /dev/null +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/AlibabaInvoker.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.dubbo; + +import com.huaweicloud.sermant.router.common.constants.RouterConstant; + +import com.alibaba.dubbo.common.URL; +import com.alibaba.dubbo.rpc.Invocation; +import com.alibaba.dubbo.rpc.Invoker; +import com.alibaba.dubbo.rpc.Result; +import com.alibaba.dubbo.rpc.RpcException; + +/** + * 测试类 + * + * @since 2022-03-18 + */ +public class AlibabaInvoker implements Invoker { + private static final URL ALIBABA_URL = URL.valueOf("dubbo://localhost:8080/com.huaweicloud.foo.BarTest?bar=foo"); + + private final URL url; + + /** + * 构造方法 + * + * @param version 版本 + */ + public AlibabaInvoker(String version) { + this.url = ALIBABA_URL.addParameter(RouterConstant.VERSION_KEY, version).setPort(8080); + } + + @Override + public Class getInterface() { + return null; + } + + @Override + public Result invoke(Invocation invocation) throws RpcException { + return null; + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public boolean isAvailable() { + return false; + } + + @Override + public void destroy() { + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/ApacheInvoker.java b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/ApacheInvoker.java new file mode 100644 index 0000000000..95659fd984 --- /dev/null +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/ApacheInvoker.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.dubbo; + +import com.huaweicloud.sermant.router.common.constants.RouterConstant; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.RpcException; + +/** + * 测试类 + * + * @since 2022-03-18 + */ +public class ApacheInvoker implements Invoker { + private static final URL APACHE_URL = URL + .valueOf("dubbo://localhost:8080/com.huaweicloud.foo.FooTest?foo=bar&version=0.0.1"); + + private final URL url; + + /** + * 构造方法 + * + * @param version 版本 + */ + public ApacheInvoker(String version) { + this.url = APACHE_URL.addParameter(RouterConstant.VERSION_KEY, version).setPort(8080); + } + + @Override + public Class getInterface() { + return null; + } + + @Override + public Result invoke(Invocation invocation) throws RpcException { + return null; + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public boolean isAvailable() { + return false; + } + + @Override + public void destroy() { + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceTest.java b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceTest.java new file mode 100644 index 0000000000..b1953cff0a --- /dev/null +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/service/AbstractDirectoryServiceTest.java @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.dubbo.service; + +import com.huaweicloud.sermant.core.utils.StringUtils; +import com.huaweicloud.sermant.router.common.constants.RouterConstant; +import com.huaweicloud.sermant.router.config.label.LabelCache; +import com.huaweicloud.sermant.router.config.label.entity.Match; +import com.huaweicloud.sermant.router.config.label.entity.MatchRule; +import com.huaweicloud.sermant.router.config.label.entity.MatchStrategy; +import com.huaweicloud.sermant.router.config.label.entity.Route; +import com.huaweicloud.sermant.router.config.label.entity.RouterConfiguration; +import com.huaweicloud.sermant.router.config.label.entity.Rule; +import com.huaweicloud.sermant.router.config.label.entity.ValueMatch; +import com.huaweicloud.sermant.router.dubbo.ApacheInvoker; +import com.huaweicloud.sermant.router.dubbo.cache.DubboCache; + +import org.apache.dubbo.common.utils.MapUtils; +import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.Invoker; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 测试AbstractDirectoryService + * + * @author provenceee + * @since 2022-09-14 + */ +public class AbstractDirectoryServiceTest { + private final AbstractDirectoryService service; + + public AbstractDirectoryServiceTest() { + service = new AbstractDirectoryServiceImpl(); + } + + @Before + public void clear() { + DubboCache.INSTANCE.putApplication("com.huaweicloud.foo.FooTest", ""); + LabelCache.getLabel(RouterConstant.DUBBO_CACHE_NAME).resetRouteRule(Collections.emptyMap()); + } + + /** + * 测试无效时 + */ + @Test + public void testSelectInvokersWhenInvalid() { + List invokers = new ArrayList<>(); + ApacheInvoker invoker1 = new ApacheInvoker<>("1.0.0"); + invokers.add(invoker1); + ApacheInvoker invoker2 = new ApacheInvoker<>("1.0.1"); + invokers.add(invoker2); + TestObject testObject = new TestObject(); + Invocation invocation = new ApacheInvocation(); + + // 测试arguments为null + List targetInvokers = (List) service.selectInvokers(testObject, null, invokers); + Assert.assertEquals(invokers, targetInvokers); + Assert.assertEquals(2, targetInvokers.size()); + + // 测试arguments为空 + targetInvokers = (List) service.selectInvokers(testObject, new Object[0], invokers); + Assert.assertEquals(invokers, targetInvokers); + Assert.assertEquals(2, targetInvokers.size()); + + // 设置arguments + Object[] arguments = {invocation}; + + // 测试路由规则无效 + targetInvokers = (List) service.selectInvokers(testObject, arguments, invokers); + Assert.assertEquals(invokers, targetInvokers); + Assert.assertEquals(2, targetInvokers.size()); + + // 初始化路由规则 + init(); + + // 测试queryMap为空 + targetInvokers = (List) service.selectInvokers(testObject, arguments, invokers); + Assert.assertEquals(invokers, targetInvokers); + Assert.assertEquals(2, targetInvokers.size()); + + // side不为consumer + testObject.getQueryMap().put("side", ""); + targetInvokers = (List) service.selectInvokers(testObject, arguments, invokers); + Assert.assertEquals(invokers, targetInvokers); + Assert.assertEquals(2, targetInvokers.size()); + + // targetService为空 + testObject.getQueryMap().put("side", "consumer"); + testObject.getQueryMap().put("interface", "com.huaweicloud.foo.FooTest"); + targetInvokers = (List) service.selectInvokers(testObject, arguments, invokers); + Assert.assertEquals(invokers, targetInvokers); + Assert.assertEquals(2, targetInvokers.size()); + } + + @Test + public void testGetTargetInvoker() { + // 初始化路由规则 + init(); + + List invokers = new ArrayList<>(); + ApacheInvoker invoker1 = new ApacheInvoker<>("1.0.0"); + invokers.add(invoker1); + ApacheInvoker invoker2 = new ApacheInvoker<>("1.0.1"); + invokers.add(invoker2); + TestObject testObject = new TestObject(); + Invocation invocation = new ApacheInvocation(); + invocation.setAttachment("bar", "bar1"); + Object[] arguments = new Object[]{invocation}; + Map queryMap = testObject.getQueryMap(); + queryMap.put("side", "consumer"); + queryMap.put("group", "fooGroup"); + queryMap.put("version", "0.0.1"); + queryMap.put("interface", "com.huaweicloud.foo.FooTest"); + DubboCache.INSTANCE.putApplication("com.huaweicloud.foo.FooTest", "foo"); + List targetInvokers = (List) service.selectInvokers(testObject, arguments, invokers); + Assert.assertEquals(1, targetInvokers.size()); + Assert.assertEquals(invoker2, targetInvokers.get(0)); + } + + @Test + public void testGetMissMatchInstances() { + // 初始化路由规则 + init(); + + List invokers = new ArrayList<>(); + ApacheInvoker invoker1 = new ApacheInvoker<>("1.0.0"); + invokers.add(invoker1); + ApacheInvoker invoker2 = new ApacheInvoker<>("1.0.1"); + invokers.add(invoker2); + TestObject testObject = new TestObject(); + Invocation invocation = new ApacheInvocation(); + invocation.setAttachment("bar", "bar2"); + Object[] arguments = new Object[]{invocation}; + Map queryMap = testObject.getQueryMap(); + queryMap.put("side", "consumer"); + queryMap.put("group", "fooGroup"); + queryMap.put("version", "0.0.1"); + queryMap.put("interface", "com.huaweicloud.foo.FooTest"); + DubboCache.INSTANCE.putApplication("com.huaweicloud.foo.FooTest", "foo"); + List targetInvokers = (List) service.selectInvokers(testObject, arguments, invokers); + Assert.assertEquals(1, targetInvokers.size()); + Assert.assertEquals(invoker1, targetInvokers.get(0)); + } + + private void init() { + ValueMatch valueMatch = new ValueMatch(); + valueMatch.setMatchStrategy(MatchStrategy.EXACT); + valueMatch.setValues(Collections.singletonList("bar1")); + MatchRule matchRule = new MatchRule(); + matchRule.setValueMatch(valueMatch); + List matchRuleList = new ArrayList<>(); + matchRuleList.add(matchRule); + Map> attachments = new HashMap<>(); + attachments.put("bar", matchRuleList); + Match match = new Match(); + match.setAttachments(attachments); + Rule rule = new Rule(); + rule.setPrecedence(2); + rule.setMatch(match); + Route route = new Route(); + route.setWeight(100); + Map tags = new HashMap<>(); + tags.put("version", "1.0.1"); + route.setTags(tags); + List routeList = new ArrayList<>(); + routeList.add(route); + rule.setRoute(routeList); + List ruleList = new ArrayList<>(); + ruleList.add(rule); + Map> map = new HashMap<>(); + map.put("foo", ruleList); + RouterConfiguration configuration = LabelCache.getLabel(RouterConstant.DUBBO_CACHE_NAME); + configuration.resetRouteRule(map); + } + + public static class TestObject { + private final Map queryMap; + + public TestObject() { + queryMap = new HashMap<>(); + } + + public Map getQueryMap() { + return queryMap; + } + } + + /** + * 测试类 + * + * @since 2022-09-14 + */ + public static class ApacheInvocation implements Invocation { + private final Map attachments = new HashMap<>(); + + @Override + public String getTargetServiceUniqueName() { + return ""; + } + + @Override + public String getProtocolServiceKey() { + return ""; + } + + @Override + public String getMethodName() { + return "FooTest"; + } + + @Override + public String getServiceName() { + return ""; + } + + @Override + public Class[] getParameterTypes() { + return new Class[]{String.class, String.class}; + } + + @Override + public Object[] getArguments() { + return new Object[]{"foo", "bar"}; + } + + @Override + public Map getAttachments() { + return MapUtils.objectToStringMap(attachments); + } + + @Override + public Map getObjectAttachments() { + return attachments; + } + + @Override + public void setAttachment(String key, String value) { + attachments.put(key, value); + } + + @Override + public void setAttachment(String key, Object value) { + attachments.put(key, value); + } + + @Override + public void setObjectAttachment(String key, Object value) { + attachments.put(key, value); + } + + @Override + public void setAttachmentIfAbsent(String key, String value) { + attachments.putIfAbsent(key, value); + } + + @Override + public void setAttachmentIfAbsent(String key, Object value) { + attachments.putIfAbsent(key, value); + } + + @Override + public void setObjectAttachmentIfAbsent(String key, Object value) { + attachments.putIfAbsent(key, value); + } + + @Override + public String getAttachment(String key) { + Object value = attachments.get(key); + return value instanceof String ? (String) value : null; + } + + @Override + public String getAttachment(String key, String defaultValue) { + Object value = attachments.get(key); + if (value instanceof String) { + String strValue = (String) value; + return StringUtils.isBlank(strValue) ? defaultValue : strValue; + } + return defaultValue; + } + + @Override + public Object getObjectAttachment(String key) { + return attachments.get(key); + } + + @Override + public Object getObjectAttachment(String key, Object defaultValue) { + return attachments.getOrDefault(key, defaultValue); + } + + @Override + public Invoker getInvoker() { + return null; + } + + @Override + public Object put(Object key, Object value) { + return new Object(); + } + + @Override + public Object get(Object key) { + return new Object(); + } + + @Override + public Map getAttributes() { + return Collections.emptyMap(); + } + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/service/ApplicationConfigServiceTest.java b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/service/ApplicationConfigServiceTest.java index 6a34c67b19..51db6d9f34 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/service/ApplicationConfigServiceTest.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/service/ApplicationConfigServiceTest.java @@ -57,6 +57,9 @@ public ApplicationConfigServiceTest() throws IllegalAccessException, NoSuchField apacheConfig = new org.apache.dubbo.config.ApplicationConfig(); service = new ApplicationConfigServiceImpl(); config = new RouterConfig(); + Map parameters = new HashMap<>(); + parameters.put(FOO, "foo1"); + config.setParameters(parameters); Field field = service.getClass().getDeclaredField("routerConfig"); field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); @@ -86,7 +89,7 @@ public void testAlibaba() { Assert.assertEquals(BAR, DubboCache.INSTANCE.getAppName()); Map parameters = alibabaConfig.getParameters(); testParameters(parameters); - Assert.assertEquals(1, parameters.size()); + Assert.assertEquals(2, parameters.size()); // 应用名不为null,parameters不为null Map map = new HashMap<>(); @@ -97,7 +100,7 @@ public void testAlibaba() { parameters = alibabaConfig.getParameters(); testParameters(parameters); Assert.assertEquals(FOO, parameters.get(BAR)); - Assert.assertEquals(2, parameters.size()); + Assert.assertEquals(3, parameters.size()); Assert.assertEquals(map, parameters); } @@ -122,7 +125,7 @@ public void testApache() { Assert.assertEquals(FOO, DubboCache.INSTANCE.getAppName()); Map parameters = apacheConfig.getParameters(); testParameters(parameters); - Assert.assertEquals(1, parameters.size()); + Assert.assertEquals(2, parameters.size()); // 应用名不为null,parameters不为null Map map = new HashMap<>(); @@ -133,12 +136,14 @@ public void testApache() { parameters = apacheConfig.getParameters(); testParameters(parameters); Assert.assertEquals(BAR, parameters.get(FOO)); - Assert.assertEquals(2, parameters.size()); + Assert.assertEquals(3, parameters.size()); Assert.assertEquals(map, parameters); } private void testParameters(Map parameters) { Assert.assertNotNull(parameters); Assert.assertEquals(config.getRouterVersion(), parameters.get(RouterConstant.VERSION_KEY)); + Assert.assertEquals(config.getParameters().get(FOO), + parameters.get(RouterConstant.PARAMETERS_KEY_PREFIX + FOO)); } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandlerTest.java b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandlerTest.java index 203394f97c..010b2337db 100644 --- a/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandlerTest.java +++ b/sermant-plugins/sermant-router/dubbo-router-service/src/test/java/com/huaweicloud/sermant/router/dubbo/strategy/RuleStrategyHandlerTest.java @@ -16,15 +16,10 @@ package com.huaweicloud.sermant.router.dubbo.strategy; -import com.huaweicloud.sermant.router.common.addr.AddrCache; import com.huaweicloud.sermant.router.common.constants.RouterConstant; import com.huaweicloud.sermant.router.config.label.entity.Route; - -import com.alibaba.dubbo.common.URL; -import com.alibaba.dubbo.rpc.Invocation; -import com.alibaba.dubbo.rpc.Invoker; -import com.alibaba.dubbo.rpc.Result; -import com.alibaba.dubbo.rpc.RpcException; +import com.huaweicloud.sermant.router.dubbo.AlibabaInvoker; +import com.huaweicloud.sermant.router.dubbo.ApacheInvoker; import org.junit.Assert; import org.junit.Test; @@ -35,17 +30,12 @@ import java.util.Map; /** - * 流量灰度策略测试 + * 标签路由策略测试 * * @author provenceee * @since 2022-03-22 */ public class RuleStrategyHandlerTest { - private static final URL ALIBABA_URL = URL.valueOf("dubbo://localhost:8080/com.huawei.foo.BarTest?bar=foo"); - - private static final org.apache.dubbo.common.URL APACHE_URL = org.apache.dubbo.common.URL - .valueOf("dubbo://localhost:8080/com.huawei.foo.FooTest?foo=bar"); - private final List routes; /** @@ -54,19 +44,17 @@ public class RuleStrategyHandlerTest { public RuleStrategyHandlerTest() { routes = new ArrayList<>(); Map tags1 = new HashMap<>(); - tags1.put("version", "0.0.1"); + tags1.put(RouterConstant.DUBBO_VERSION_KEY, "0.0.1"); Route route1 = new Route(); route1.setTags(tags1); route1.setWeight(100); routes.add(route1); Map tags2 = new HashMap<>(); - tags2.put("version", "0.0.2"); + tags2.put(RouterConstant.DUBBO_VERSION_KEY, "0.0.2"); Route route2 = new Route(); route2.setTags(tags2); route2.setWeight(100); routes.add(route2); - AddrCache.setRegisterVersionCache("localhost:8081", "0.0.1"); - AddrCache.setRegisterVersionCache("localhost:8082", "0.0.2"); } /** @@ -75,9 +63,9 @@ public RuleStrategyHandlerTest() { @Test public void testAlibabaV1() { List invokers = new ArrayList<>(); - AlibabaInvoker invoker1 = new AlibabaInvoker<>(8081, "0.0.1"); + AlibabaInvoker invoker1 = new AlibabaInvoker<>("0.0.1"); invokers.add(invoker1); - AlibabaInvoker invoker2 = new AlibabaInvoker<>(8082, "0.0.2"); + AlibabaInvoker invoker2 = new AlibabaInvoker<>("0.0.2"); invokers.add(invoker2); List targetInvoker = RuleStrategyHandler.INSTANCE.getTargetInvoker(routes, invokers); Assert.assertEquals(100, routes.get(0).getWeight().intValue()); @@ -91,14 +79,23 @@ public void testAlibabaV1() { @Test public void testAlibabaMismatch() { List invokers = new ArrayList<>(); - AlibabaInvoker invoker1 = new AlibabaInvoker<>(8081, "0.0.1"); + AlibabaInvoker invoker1 = new AlibabaInvoker<>("0.0.1"); invokers.add(invoker1); - AlibabaInvoker invoker2 = new AlibabaInvoker<>(8082, "0.0.2"); + AlibabaInvoker invoker2 = new AlibabaInvoker<>("0.0.2"); invokers.add(invoker2); routes.get(0).setWeight(0); + + // 测试匹配上路由,没有随机到实例的情况 List targetInvoker = RuleStrategyHandler.INSTANCE.getTargetInvoker(routes, invokers); Assert.assertEquals(1, targetInvoker.size()); Assert.assertEquals(invoker2, targetInvoker.get(0)); + + // 测试没有匹配上路由,选取不匹配标签的实例的情况 + List> tags = new ArrayList<>(); + tags.add(routes.get(0).getTags()); + List missMatchInvoker = RuleStrategyHandler.INSTANCE.getMissMatchInstances(tags, invokers); + Assert.assertEquals(1, missMatchInvoker.size()); + Assert.assertEquals(invoker2, missMatchInvoker.get(0)); } /** @@ -107,9 +104,9 @@ public void testAlibabaMismatch() { @Test public void testApacheV1() { List invokers = new ArrayList<>(); - ApacheInvoker invoker1 = new ApacheInvoker<>(8081, "0.0.1"); + ApacheInvoker invoker1 = new ApacheInvoker<>("0.0.1"); invokers.add(invoker1); - ApacheInvoker invoker2 = new ApacheInvoker<>(8082, "0.0.2"); + ApacheInvoker invoker2 = new ApacheInvoker<>("0.0.2"); invokers.add(invoker2); List targetInvoker = RuleStrategyHandler.INSTANCE.getTargetInvoker(routes, invokers); Assert.assertEquals(100, routes.get(0).getWeight().intValue()); @@ -123,100 +120,22 @@ public void testApacheV1() { @Test public void testApacheMismatch() { List invokers = new ArrayList<>(); - ApacheInvoker invoker1 = new ApacheInvoker<>(8081, "0.0.1"); + ApacheInvoker invoker1 = new ApacheInvoker<>("0.0.1"); invokers.add(invoker1); - ApacheInvoker invoker2 = new ApacheInvoker<>(8082, "0.0.2"); + ApacheInvoker invoker2 = new ApacheInvoker<>("0.0.2"); invokers.add(invoker2); routes.get(0).setWeight(0); + + // 测试匹配上路由,没有随机到实例的情况 List targetInvoker = RuleStrategyHandler.INSTANCE.getTargetInvoker(routes, invokers); Assert.assertEquals(1, targetInvoker.size()); Assert.assertEquals(invoker2, targetInvoker.get(0)); - } - - /** - * 测试类 - * - * @since 2022-03-18 - */ - public static class AlibabaInvoker implements Invoker { - private final URL url; - - /** - * 构造方法 - * - * @param port 端口 - * @param version 版本 - */ - public AlibabaInvoker(int port, String version) { - this.url = ALIBABA_URL.addParameter(RouterConstant.VERSION_KEY, version).setPort(port); - } - - @Override - public Class getInterface() { - return null; - } - - @Override - public Result invoke(Invocation invocation) throws RpcException { - return null; - } - - @Override - public URL getUrl() { - return url; - } - - @Override - public boolean isAvailable() { - return false; - } - - @Override - public void destroy() { - } - } - - /** - * 测试类 - * - * @since 2022-03-18 - */ - public static class ApacheInvoker implements org.apache.dubbo.rpc.Invoker { - private final org.apache.dubbo.common.URL url; - - /** - * 构造方法 - * - * @param port 端口 - * @param version 版本 - */ - public ApacheInvoker(int port, String version) { - this.url = APACHE_URL.addParameter(RouterConstant.VERSION_KEY, version).setPort(port); - } - - @Override - public Class getInterface() { - return null; - } - - @Override - public org.apache.dubbo.rpc.Result invoke(org.apache.dubbo.rpc.Invocation invocation) - throws org.apache.dubbo.rpc.RpcException { - return null; - } - - @Override - public org.apache.dubbo.common.URL getUrl() { - return url; - } - - @Override - public boolean isAvailable() { - return false; - } - @Override - public void destroy() { - } + // 测试没有匹配上路由,选取不匹配标签的实例的情况 + List> tags = new ArrayList<>(); + tags.add(routes.get(0).getTags()); + List missMatchInvoker = RuleStrategyHandler.INSTANCE.getMissMatchInstances(tags, invokers); + Assert.assertEquals(1, missMatchInvoker.size()); + Assert.assertEquals(invoker2, missMatchInvoker.get(0)); } } \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/addr/AddrCache.java b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/addr/AddrCache.java deleted file mode 100644 index d127e89818..0000000000 --- a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/addr/AddrCache.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2021-2022 Huawei Technologies Co., Ltd. All rights reserved. - * - * Licensed 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 com.huaweicloud.sermant.router.common.addr; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 地址缓存 - * - * @author provenceee - * @since 2021-10-15 - */ -public class AddrCache { - // 注册版本缓存 - private static final Map REGISTER_VERSION_CACHE = new ConcurrentHashMap<>(); - - private AddrCache() { - } - - /** - * 设置注册版本缓存 - * - * @param addr 地址 - * @param version 注册版本 - */ - public static void setRegisterVersionCache(String addr, String version) { - REGISTER_VERSION_CACHE.put(addr, version); - } - - /** - * 获取注册版本缓存 - * - * @param addr 地址 - * @return 注册版本 - */ - public static String getRegisterVersionCache(String addr) { - return REGISTER_VERSION_CACHE.get(addr); - } -} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/constants/RouterConstant.java b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/constants/RouterConstant.java index accb77803b..be279f3ab5 100644 --- a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/constants/RouterConstant.java +++ b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/constants/RouterConstant.java @@ -29,7 +29,7 @@ public class RouterConstant { public static final String DUBBO_SOURCE_TYPE_PREFIX = "args"; /** - * 灰度发布默认版本 + * 标签路由默认版本 */ public static final String ROUTER_DEFAULT_VERSION = "0.0.0"; @@ -39,32 +39,27 @@ public class RouterConstant { public static final String ENABLED_METHOD_NAME = ".isEnabled()"; /** - * 注册时灰度版本的key - */ - public static final String TAG_VERSION_KEY = "tag.version"; - - /** - * 灰度配置servicecomb的key + * 标签路由servicecomb的key */ public static final String ROUTER_CONFIG_SERVICECOMB_KEY = "servicecomb"; /** - * 灰度配置routeRule的key + * 标签路由routeRule的key */ public static final String ROUTER_CONFIG_ROUTE_RULE_KEY = "routeRule"; /** - * 灰度配置key前缀 + * 标签路由key前缀 */ public static final String ROUTER_KEY_PREFIX = "servicecomb.routeRule"; /** - * dubbo应用灰度标签缓存名 + * dubbo路由规则缓存名 */ public static final String DUBBO_CACHE_NAME = "DUBBO_ROUTE"; /** - * spring应用灰度标签缓存名 + * spring路由规则缓存名 */ public static final String SPRING_CACHE_NAME = "SPRING_ROUTE"; diff --git a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/utils/ReflectUtils.java b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/utils/ReflectUtils.java index 1d73b539b3..90203061b3 100644 --- a/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/utils/ReflectUtils.java +++ b/sermant-plugins/sermant-router/router-common/src/main/java/com/huaweicloud/sermant/router/common/utils/ReflectUtils.java @@ -89,8 +89,8 @@ public static String invokeWithNoneParameterAndReturnString(Object obj, String n /** * 反射调用无参方法并且返回map * - * @param obj - * @param name + * @param obj 对象 + * @param name 方法名 * @return 值 */ public static Map invokeWithNoneParameterAndReturnMap(Object obj, String name) { diff --git a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/label/entity/RouterConfiguration.java b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/label/entity/RouterConfiguration.java index ee39c715ab..5e443f0f65 100644 --- a/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/label/entity/RouterConfiguration.java +++ b/sermant-plugins/sermant-router/router-config-common/src/main/java/com/huaweicloud/sermant/router/config/label/entity/RouterConfiguration.java @@ -49,9 +49,9 @@ public void resetRouteRule(Map> map) { } /** - * 灰度标签是否无效 + * 路由规则是否无效 * - * @param configuration 灰度标签 + * @param configuration 路由规则 * @return 是否无效 */ public static boolean isInValid(RouterConfiguration configuration) { diff --git a/sermant-plugins/sermant-router/spring-router-plugin/pom.xml b/sermant-plugins/sermant-router/spring-router-plugin/pom.xml index be25894a03..abd3a4a25f 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/pom.xml +++ b/sermant-plugins/sermant-router/spring-router-plugin/pom.xml @@ -20,6 +20,8 @@ 1.10.7 1.4.3 1.3.1 + 5.2.0.RELEASE + 9.0.43 @@ -81,12 +83,45 @@ zuul-core ${zuul.version} provided + + + org.mockito + mockito-all + + com.huaweicloud.sermant router-common ${project.version} + + org.mockito + mockito-core + test + + + org.mockito + mockito-inline + test + + + junit + junit + test + + + org.apache.tomcat.embed + tomcat-embed-core + ${tomcat.version} + test + + + org.springframework + spring-test + ${spring.test.version} + test + diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptor.java b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptor.java index ed78120cb5..c993aa7375 100644 --- a/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptor.java +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/main/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptor.java @@ -16,6 +16,7 @@ package com.huaweicloud.sermant.router.spring.interceptor; +import com.huaweicloud.sermant.core.common.LoggerFactory; import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; import com.huaweicloud.sermant.core.plugin.agent.interceptor.AbstractInterceptor; import com.huaweicloud.sermant.core.plugin.config.PluginConfigManager; @@ -31,6 +32,8 @@ import org.springframework.cloud.client.serviceregistry.Registration; import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; +import java.util.logging.Logger; /** * AbstractAutoServiceRegistration增强类,spring cloud注册方法 @@ -39,6 +42,8 @@ * @since 2022-07-12 */ public class ServiceRegistryInterceptor extends AbstractInterceptor { + private static final Logger LOGGER = LoggerFactory.getLogger(); + private final SpringConfigService configService; private final RouterConfig routerConfig; @@ -52,15 +57,18 @@ public ServiceRegistryInterceptor() { } @Override - public ExecuteContext before(ExecuteContext context) - throws InvocationTargetException, IllegalAccessException, NoSuchMethodException { + public ExecuteContext before(ExecuteContext context) { Object object = context.getObject(); if (object instanceof AbstractAutoServiceRegistration) { AbstractAutoServiceRegistration serviceRegistration = (AbstractAutoServiceRegistration) object; - Registration registration = (Registration) ReflectUtils.getAccessibleObject(serviceRegistration.getClass() - .getDeclaredMethod("getRegistration")).invoke(serviceRegistration); - AppCache.INSTANCE.setAppName(registration.getServiceId()); - SpringRouterUtils.putMetaData(registration.getMetadata(), routerConfig); + try { + Registration registration = (Registration) ReflectUtils.getAccessibleObject( + serviceRegistration.getClass().getDeclaredMethod("getRegistration")).invoke(serviceRegistration); + AppCache.INSTANCE.setAppName(registration.getServiceId()); + SpringRouterUtils.putMetaData(registration.getMetadata(), routerConfig); + } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException ex) { + LOGGER.log(Level.WARNING, "Can not get the registration.", ex); + } } return context; } diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/BaseLoadBalancerInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/BaseLoadBalancerInterceptorTest.java new file mode 100644 index 0000000000..b0d9eeb738 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/BaseLoadBalancerInterceptorTest.java @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.core.common.CommonConstant; +import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.service.ServiceManager; +import com.huaweicloud.sermant.router.spring.cache.RequestData; +import com.huaweicloud.sermant.router.spring.service.LoadBalancerService; +import com.huaweicloud.sermant.router.spring.service.SpringConfigService; +import com.huaweicloud.sermant.router.spring.utils.ThreadLocalUtils; + +import com.netflix.loadbalancer.BaseLoadBalancer; +import com.netflix.loadbalancer.Server; +import com.netflix.zuul.context.RequestContext; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.mock.web.MockHttpServletRequest; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 测试BaseLoadBalancerInterceptor + * + * @author provenceee + * @since 2022-09-08 + */ +public class BaseLoadBalancerInterceptorTest { + private final BaseLoadBalancerInterceptor interceptor; + + private final ExecuteContext context; + + private final BaseLoadBalancer loadBalancer; + + private static TestSpringConfigService configService; + + private static MockedStatic mockServiceManager; + + /** + * UT执行前进行mock + */ + @BeforeClass + public static void before() { + Map map = new HashMap<>(); + map.put(CommonConstant.LOG_SETTING_FILE_KEY, + ServiceRegistryInterceptorTest.class.getResource("/logback-test.xml").getPath()); + LoggerFactory.init(map); + configService = new TestSpringConfigService(); + mockServiceManager = Mockito.mockStatic(ServiceManager.class); + mockServiceManager.when(() -> ServiceManager.getService(SpringConfigService.class)).thenReturn(configService); + mockServiceManager.when(() -> ServiceManager.getService(LoadBalancerService.class)) + .thenReturn(new TestLoadBalancerService()); + } + + /** + * UT执行后释放mock对象 + */ + @AfterClass + public static void after() { + mockServiceManager.close(); + } + + public BaseLoadBalancerInterceptorTest() throws NoSuchMethodException { + interceptor = new BaseLoadBalancerInterceptor(); + loadBalancer = new BaseLoadBalancer(); + context = ExecuteContext.forMemberMethod(loadBalancer, String.class.getMethod("trim"), null, null, + null); + } + + @Before + public void reset() { + ThreadLocalUtils.removeRequestHeader(); + ThreadLocalUtils.removeRequestData(); + configService.setInvalid(false); + List servers = new ArrayList<>(); + servers.add(new Server("bar", 8080)); + servers.add(new Server("foo", 8081)); + loadBalancer.setServersList(servers); + } + + /** + * 测试路由规则无效时 + */ + @Test + public void testBeforeWhenInvalid() { + configService.setInvalid(true); + interceptor.before(context); + BaseLoadBalancer loadBalancer = (BaseLoadBalancer) context.getObject(); + List servers = loadBalancer.getAllServers(); + Assert.assertNotNull(servers); + Assert.assertEquals(2, servers.size()); + } + + /** + * 测试实例列表为空时 + */ + @Test + public void testBeforeWithEmptyServers() { + loadBalancer.setServersList(Collections.emptyList()); + ThreadLocalUtils.setRequestData(new RequestData(Collections.emptyMap(), "", "")); + interceptor.before(context); + BaseLoadBalancer loadBalancer = (BaseLoadBalancer) context.getObject(); + List servers = loadBalancer.getAllServers(); + Assert.assertNotNull(servers); + Assert.assertEquals(0, servers.size()); + } + + /** + * 测试从ThreadLocal获取请求数据 + */ + @Test + public void testBeforeWithThreadLocal() { + ThreadLocalUtils.setRequestData(new RequestData(Collections.emptyMap(), "", "")); + interceptor.before(context); + BaseLoadBalancer loadBalancer = (BaseLoadBalancer) context.getObject(); + List servers = loadBalancer.getAllServers(); + Assert.assertNotNull(servers); + Assert.assertEquals(1, servers.size()); + Assert.assertEquals("foo", servers.get(0).getHost()); + Assert.assertEquals(8081, servers.get(0).getPort()); + } + + /** + * 测试从RequestContext获取请求数据 + */ + @Test + public void testBeforeWithRequestContext() { + RequestContext requestContext = RequestContext.getCurrentContext(); + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("bar", "bar1"); + request.addHeader("foo", "foo1"); + request.addHeader("foo2", "foo2"); + requestContext.setRequest(request); + interceptor.before(context); + BaseLoadBalancer loadBalancer = (BaseLoadBalancer) context.getObject(); + List servers = loadBalancer.getAllServers(); + Assert.assertNotNull(servers); + Assert.assertEquals(1, servers.size()); + Assert.assertEquals("foo", servers.get(0).getHost()); + Assert.assertEquals(8081, servers.get(0).getPort()); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ClientHttpRequestInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ClientHttpRequestInterceptorTest.java new file mode 100644 index 0000000000..1fa0d5526a --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ClientHttpRequestInterceptorTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.router.spring.cache.RequestData; +import com.huaweicloud.sermant.router.spring.cache.RequestHeader; +import com.huaweicloud.sermant.router.spring.utils.ThreadLocalUtils; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpMethod; +import org.springframework.mock.http.client.MockClientHttpRequest; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 测试ClientHttpRequestInterceptor + * + * @author provenceee + * @since 2022-09-08 + */ +public class ClientHttpRequestInterceptorTest { + private final ClientHttpRequestInterceptor interceptor; + + private final ExecuteContext context; + + public ClientHttpRequestInterceptorTest() { + interceptor = new ClientHttpRequestInterceptor(); + Object[] arguments = new Object[1]; + MockClientHttpRequest request = new MockClientHttpRequest(); + request.getHeaders().add("bar", "bar2"); + request.getHeaders().add("bar3", "bar3"); + arguments[0] = request; + context = ExecuteContext.forMemberMethod(new Object(), null, arguments, null, null); + } + + @Before + public void clear() { + ThreadLocalUtils.removeRequestHeader(); + ThreadLocalUtils.removeRequestData(); + } + + @Test + public void testBefore() { + Map> header = new HashMap<>(); + header.put("bar", Collections.singletonList("bar1")); + header.put("foo", Collections.singletonList("foo1")); + RequestHeader requestHeader = new RequestHeader(header); + ThreadLocalUtils.setRequestHeader(requestHeader); + interceptor.before(context); + RequestData requestData = ThreadLocalUtils.getRequestData(); + Assert.assertNotNull(requestData); + Assert.assertEquals(HttpMethod.GET.name(), requestData.getHttpMethod()); + Assert.assertEquals("/", requestData.getPath()); + Map> headerData = requestData.getHeader(); + Assert.assertEquals(3, headerData.size()); + Assert.assertEquals("bar2", headerData.get("bar").get(0)); + Assert.assertEquals("foo1", headerData.get("foo").get(0)); + Assert.assertEquals("bar3", headerData.get("bar3").get(0)); + + } + + @Test + public void testAfter() { + ThreadLocalUtils.setRequestData(new RequestData(Collections.emptyMap(), "", "")); + interceptor.after(context); + Assert.assertNull(ThreadLocalUtils.getRequestData()); + } + + @Test + public void testOnThrow() { + ThreadLocalUtils.setRequestData(new RequestData(Collections.emptyMap(), "", "")); + interceptor.onThrow(context); + Assert.assertNull(ThreadLocalUtils.getRequestData()); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/EurekaHttpClientInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/EurekaHttpClientInterceptorTest.java new file mode 100644 index 0000000000..c5d07bc165 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/EurekaHttpClientInterceptorTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.router.common.config.RouterConfig; +import com.huaweicloud.sermant.router.spring.cache.AppCache; + +import com.netflix.appinfo.InstanceInfo; +import com.netflix.appinfo.InstanceInfo.Builder; + +import org.junit.Assert; +import org.junit.Test; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.HashMap; +import java.util.Map; + +/** + * 测试EurekaHttpClientInterceptor + * + * @author provenceee + * @since 2022-09-06 + */ +public class EurekaHttpClientInterceptorTest { + private final EurekaHttpClientInterceptor interceptor; + + private final RouterConfig routerConfig; + + private final ExecuteContext context; + + public EurekaHttpClientInterceptorTest() throws IllegalAccessException, NoSuchFieldException { + interceptor = new EurekaHttpClientInterceptor(); + routerConfig = new RouterConfig(); + Map parameters = new HashMap<>(); + parameters.put("foo", "foo1"); + parameters.put("bar", "bar1"); + routerConfig.setParameters(parameters); + Field field = interceptor.getClass().getDeclaredField("routerConfig"); + field.setAccessible(true); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(interceptor, routerConfig); + Object[] arguments = new Object[1]; + Builder builder = Builder.newBuilder(); + builder.setAppName("foo"); + Map metadata = new HashMap<>(); + metadata.put("foo", "foo2"); + builder.setMetadata(metadata); + arguments[0] = builder.build(); + context = ExecuteContext.forMemberMethod(new Object(), null, arguments, null, null); + } + + @Test + public void testBefore() { + interceptor.before(context); + + // ek会把服务名转为大写,所以这里期望值也是大写 + Assert.assertEquals("FOO", AppCache.INSTANCE.getAppName()); + InstanceInfo instanceInfo = (InstanceInfo) context.getArguments()[0]; + Map metadata = instanceInfo.getMetadata(); + Assert.assertEquals(routerConfig.getRouterVersion(), metadata.get("version")); + Assert.assertEquals("bar1", metadata.get("bar")); + Assert.assertEquals("foo2", metadata.get("foo")); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptorTest.java new file mode 100644 index 0000000000..8881353b10 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/FeignClientInterceptorTest.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.router.spring.cache.RequestData; +import com.huaweicloud.sermant.router.spring.cache.RequestHeader; +import com.huaweicloud.sermant.router.spring.utils.ThreadLocalUtils; + +import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext; +import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableDefault; + +import feign.Request; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpMethod; + +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 测试FeignClientInterceptor + * + * @author provenceee + * @since 2022-09-08 + */ +public class FeignClientInterceptorTest { + private final FeignClientInterceptor interceptor; + + private final ExecuteContext context; + + public FeignClientInterceptorTest() { + interceptor = new FeignClientInterceptor(); + Object[] arguments = new Object[1]; + Map> headers = new HashMap<>(); + headers.put("bar", Collections.singletonList("bar1")); + headers.put("foo", Collections.singletonList("foo1")); + arguments[0] = Request.create("GET", "/", headers, new byte[]{}, StandardCharsets.UTF_8); + context = ExecuteContext.forMemberMethod(new Object(), null, arguments, null, null); + } + + @Before + public void clear() { + ThreadLocalUtils.removeRequestHeader(); + ThreadLocalUtils.removeRequestData(); + } + + @Test + public void testBeforeWithThreadLocal() { + Map> header = new HashMap<>(); + header.put("bar", Collections.singletonList("bar2")); + header.put("foo3", Collections.singletonList("foo3")); + RequestHeader requestHeader = new RequestHeader(header); + ThreadLocalUtils.setRequestHeader(requestHeader); + interceptor.before(context); + RequestData requestData = ThreadLocalUtils.getRequestData(); + Assert.assertNotNull(requestData); + Assert.assertEquals(HttpMethod.GET.name(), requestData.getHttpMethod()); + Assert.assertEquals("/", requestData.getPath()); + Map> headerData = requestData.getHeader(); + Assert.assertEquals(3, headerData.size()); + Assert.assertEquals("bar1", headerData.get("bar").get(0)); + Assert.assertEquals("foo1", headerData.get("foo").get(0)); + Assert.assertEquals("foo3", headerData.get("foo3").get(0)); + } + + @Test + public void testBeforeWithHystrix() { + Map> header = new HashMap<>(); + header.put("bar", Collections.singletonList("bar2")); + header.put("foo3", Collections.singletonList("foo3")); + RequestHeader requestHeader = new RequestHeader(header); + HystrixRequestContext.initializeContext(); + HystrixRequestVariableDefault hystrixRequest = new HystrixRequestVariableDefault<>(); + hystrixRequest.set(requestHeader); + interceptor.before(context); + RequestData requestData = ThreadLocalUtils.getRequestData(); + Assert.assertNotNull(requestData); + Assert.assertEquals(HttpMethod.GET.name(), requestData.getHttpMethod()); + Assert.assertEquals("/", requestData.getPath()); + Map> headerData = requestData.getHeader(); + Assert.assertEquals(3, headerData.size()); + Assert.assertEquals("bar1", headerData.get("bar").get(0)); + Assert.assertEquals("foo1", headerData.get("foo").get(0)); + Assert.assertEquals("foo3", headerData.get("foo3").get(0)); + } + + @Test + public void testBeforeWithoutHystrix() { + interceptor.before(context); + RequestData requestData = ThreadLocalUtils.getRequestData(); + Assert.assertNotNull(requestData); + Assert.assertEquals(HttpMethod.GET.name(), requestData.getHttpMethod()); + Assert.assertEquals("/", requestData.getPath()); + Map> headerData = requestData.getHeader(); + Assert.assertEquals(2, headerData.size()); + Assert.assertEquals("bar1", headerData.get("bar").get(0)); + Assert.assertEquals("foo1", headerData.get("foo").get(0)); + } + + @Test + public void testBeforeWithoutRequestHeader() { + HystrixRequestContext.initializeContext(); + HystrixRequestVariableDefault hystrixRequest = new HystrixRequestVariableDefault<>(); + hystrixRequest.set("bar"); + interceptor.before(context); + RequestData requestData = ThreadLocalUtils.getRequestData(); + Assert.assertNotNull(requestData); + Assert.assertEquals(HttpMethod.GET.name(), requestData.getHttpMethod()); + Assert.assertEquals("/", requestData.getPath()); + Map> headerData = requestData.getHeader(); + Assert.assertEquals(2, headerData.size()); + Assert.assertEquals("bar1", headerData.get("bar").get(0)); + Assert.assertEquals("foo1", headerData.get("foo").get(0)); + } + + @Test + public void testAfter() { + ThreadLocalUtils.setRequestData(new RequestData(Collections.emptyMap(), "", "")); + interceptor.after(context); + Assert.assertNull(ThreadLocalUtils.getRequestData()); + } + + @Test + public void testOnThrow() { + ThreadLocalUtils.setRequestData(new RequestData(Collections.emptyMap(), "", "")); + interceptor.onThrow(context); + Assert.assertNull(ThreadLocalUtils.getRequestData()); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/HandlerExecutionChainInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/HandlerExecutionChainInterceptorTest.java new file mode 100644 index 0000000000..86b2764aa6 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/HandlerExecutionChainInterceptorTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.service.ServiceManager; +import com.huaweicloud.sermant.router.spring.service.RouteHandlerService; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.web.servlet.HandlerExecutionChain; + +import java.util.Collections; + +/** + * 测试HandlerExecutionChainInterceptor + * + * @author provenceee + * @since 2022-09-07 + */ +public class HandlerExecutionChainInterceptorTest { + private final HandlerExecutionChainInterceptor interceptor; + + private final ExecuteContext context; + + private static MockedStatic mockServiceManager; + + /** + * UT执行前进行mock + */ + @BeforeClass + public static void before() { + mockServiceManager = Mockito.mockStatic(ServiceManager.class); + mockServiceManager.when(() -> ServiceManager.getService(RouteHandlerService.class)).thenReturn( + (RouteHandlerService) Collections::emptySet); + } + + /** + * UT执行后释放mock对象 + */ + @AfterClass + public static void after() { + mockServiceManager.close(); + } + + public HandlerExecutionChainInterceptorTest() { + interceptor = new HandlerExecutionChainInterceptor(); + context = ExecuteContext.forMemberMethod(new HandlerExecutionChain(new Object()), null, null, null, null); + } + + @Test + public void testBefore() { + interceptor.before(context); + HandlerExecutionChain chain = (HandlerExecutionChain) context.getObject(); + Assert.assertNotNull(chain.getInterceptors()); + Assert.assertEquals(1, chain.getInterceptors().length); + Assert.assertEquals(RouteHandlerInterceptor.class, chain.getInterceptors()[0].getClass()); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/HystrixActionInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/HystrixActionInterceptorTest.java new file mode 100644 index 0000000000..20ebc735b2 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/HystrixActionInterceptorTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.router.common.utils.ReflectUtils; +import com.huaweicloud.sermant.router.spring.cache.RequestHeader; +import com.huaweicloud.sermant.router.spring.utils.ThreadLocalUtils; + +import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategyDefault; +import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext; +import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableDefault; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * 测试HystrixActionInterceptor + * + * @author provenceee + * @since 2022-09-08 + */ +public class HystrixActionInterceptorTest { + private final HystrixActionInterceptor interceptor; + + private final ExecuteContext context; + + public HystrixActionInterceptorTest() { + interceptor = new HystrixActionInterceptor(); + Object[] arguments = new Object[1]; + arguments[0] = HystrixConcurrencyStrategyDefault.getInstance(); + context = ExecuteContext.forMemberMethod(new Object(), null, arguments, null, null); + } + + @Test + public void testBefore() { + Map> header = new HashMap<>(); + header.put("bar", Collections.singletonList("bar1")); + header.put("foo", Collections.singletonList("foo1")); + RequestHeader requestHeader = new RequestHeader(header); + ThreadLocalUtils.setRequestHeader(requestHeader); + interceptor.before(context); + HystrixRequestContext context = HystrixRequestContext.getContextForCurrentThread(); + Assert.assertNotNull(context); + Map, ?> state = ReflectUtils.getFieldValue(context, "state") + .map(value -> (Map, ?>) value).orElse(Collections.emptyMap()); + for (Entry, ?> entry : state.entrySet()) { + Object lazyInitializer = entry.getValue(); + Object obj = ReflectUtils.getFieldValue(lazyInitializer, "value").orElse(null); + if (obj instanceof RequestHeader) { + entry.getKey().remove(); + Assert.assertEquals(requestHeader, obj); + } + } + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerClientFilterInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerClientFilterInterceptorTest.java new file mode 100644 index 0000000000..e56ac9cd74 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/LoadBalancerClientFilterInterceptorTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.router.spring.cache.RequestData; +import com.huaweicloud.sermant.router.spring.utils.ThreadLocalUtils; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.springframework.http.HttpMethod; +import org.springframework.mock.http.server.reactive.MockServerHttpRequest; +import org.springframework.mock.web.server.MockServerWebExchange; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * 测试LoadBalancerClientFilterInterceptor + * + * @author provenceee + * @since 2022-09-08 + */ +public class LoadBalancerClientFilterInterceptorTest { + private final LoadBalancerClientFilterInterceptor interceptor; + + private final ExecuteContext context; + + public LoadBalancerClientFilterInterceptorTest() { + interceptor = new LoadBalancerClientFilterInterceptor(); + Object[] arguments = new Object[1]; + MockServerHttpRequest request = MockServerHttpRequest.get("") + .header("bar", "bar1").header("foo", "foo1").build(); + MockServerWebExchange exchange = MockServerWebExchange.from(request); + arguments[0] = exchange; + context = ExecuteContext.forMemberMethod(new Object(), null, arguments, null, null); + } + + @Before + public void clear() { + ThreadLocalUtils.removeRequestHeader(); + ThreadLocalUtils.removeRequestData(); + } + + @Test + public void testBefore() { + interceptor.before(context); + RequestData requestData = ThreadLocalUtils.getRequestData(); + Assert.assertEquals(HttpMethod.GET.name(), requestData.getHttpMethod()); + Assert.assertEquals("", requestData.getPath()); + Assert.assertNotNull(requestData); + Map> headerData = requestData.getHeader(); + Assert.assertEquals(2, headerData.size()); + Assert.assertEquals("bar1", headerData.get("bar").get(0)); + Assert.assertEquals("foo1", headerData.get("foo").get(0)); + } + + @Test + public void testAfter() { + ThreadLocalUtils.setRequestData(new RequestData(Collections.emptyMap(), "", "")); + interceptor.after(context); + Assert.assertNull(ThreadLocalUtils.getRequestData()); + } + + @Test + public void testOnThrow() { + ThreadLocalUtils.setRequestData(new RequestData(Collections.emptyMap(), "", "")); + interceptor.onThrow(context); + Assert.assertNull(ThreadLocalUtils.getRequestData()); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/RouteHandlerInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/RouteHandlerInterceptorTest.java new file mode 100644 index 0000000000..7bda3f63b0 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/RouteHandlerInterceptorTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.core.service.ServiceManager; +import com.huaweicloud.sermant.router.spring.cache.RequestData; +import com.huaweicloud.sermant.router.spring.cache.RequestHeader; +import com.huaweicloud.sermant.router.spring.service.RouteHandlerService; +import com.huaweicloud.sermant.router.spring.utils.ThreadLocalUtils; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; + +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 测试RouteHandlerInterceptor + * + * @author provenceee + * @since 2022-09-07 + */ +public class RouteHandlerInterceptorTest { + private final RouteHandlerInterceptor interceptor; + + private static MockedStatic mockServiceManager; + + /** + * UT执行前进行mock + */ + @BeforeClass + public static void before() { + mockServiceManager = Mockito.mockStatic(ServiceManager.class); + mockServiceManager.when(() -> ServiceManager.getService(RouteHandlerService.class)) + .thenReturn((RouteHandlerService) () -> { + Set keys = new HashSet<>(); + keys.add("bar"); + keys.add("foo"); + return keys; + }); + + } + + /** + * UT执行后释放mock对象 + */ + @AfterClass + public static void after() { + mockServiceManager.close(); + } + + public RouteHandlerInterceptorTest() { + interceptor = new RouteHandlerInterceptor(); + } + + @Before + public void clear() { + ThreadLocalUtils.removeRequestHeader(); + ThreadLocalUtils.removeRequestData(); + } + + /** + * 测试preHandle方法 + */ + @Test + public void testPreHandle() { + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("bar", "bar1"); + request.addHeader("foo", "foo1"); + request.addHeader("foo2", "foo2"); + MockHttpServletResponse response = new MockHttpServletResponse(); + Object obj = new Object(); + + // 测试preHandle方法 + interceptor.preHandle(request, response, obj); + RequestHeader requestHeader = ThreadLocalUtils.getRequestHeader(); + Map> header = requestHeader.getHeader(); + Assert.assertNotNull(header); + Assert.assertEquals(2, header.size()); + Assert.assertEquals("bar1", header.get("bar").get(0)); + Assert.assertEquals("foo1", header.get("foo").get(0)); + } + + /** + * 测试afterCompletion,验证是否释放线程变量 + */ + @Test + public void testAfterCompletion() { + ThreadLocalUtils.setRequestData(new RequestData(Collections.emptyMap(), "", "")); + + // 测试afterCompletion,验证是否释放线程变量 + interceptor.afterCompletion(new MockHttpServletRequest(), new MockHttpServletResponse(), new Object(), null); + Assert.assertNull(ThreadLocalUtils.getRequestHeader()); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceInstanceListSupplierInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceInstanceListSupplierInterceptorTest.java new file mode 100644 index 0000000000..7cac0d6a53 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceInstanceListSupplierInterceptorTest.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.core.common.CommonConstant; +import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.service.ServiceManager; +import com.huaweicloud.sermant.router.spring.cache.RequestData; +import com.huaweicloud.sermant.router.spring.service.LoadBalancerService; +import com.huaweicloud.sermant.router.spring.service.SpringConfigService; +import com.huaweicloud.sermant.router.spring.utils.ThreadLocalUtils; + +import reactor.core.publisher.Flux; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.ServiceInstance; +import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 测试ServiceInstanceListSupplierInterceptor + * + * @author provenceee + * @since 2022-09-08 + */ +public class ServiceInstanceListSupplierInterceptorTest { + private final ServiceInstanceListSupplierInterceptor interceptor; + + private final ExecuteContext context; + + private final TestServiceInstanceListSupplier supplier; + + private static TestSpringConfigService configService; + + private static MockedStatic mockServiceManager; + + /** + * UT执行前进行mock + */ + @BeforeClass + public static void before() { + Map map = new HashMap<>(); + map.put(CommonConstant.LOG_SETTING_FILE_KEY, + ServiceRegistryInterceptorTest.class.getResource("/logback-test.xml").getPath()); + LoggerFactory.init(map); + configService = new TestSpringConfigService(); + mockServiceManager = Mockito.mockStatic(ServiceManager.class); + mockServiceManager.when(() -> ServiceManager.getService(SpringConfigService.class)).thenReturn(configService); + mockServiceManager.when(() -> ServiceManager.getService(LoadBalancerService.class)) + .thenReturn(new TestLoadBalancerService()); + } + + /** + * UT执行后释放mock对象 + */ + @AfterClass + public static void after() { + mockServiceManager.close(); + } + + public ServiceInstanceListSupplierInterceptorTest() throws NoSuchMethodException { + interceptor = new ServiceInstanceListSupplierInterceptor(); + supplier = new TestServiceInstanceListSupplier(); + context = ExecuteContext.forMemberMethod(supplier, String.class.getMethod("trim"), null, null, null); + } + + @Before + public void reset() { + ThreadLocalUtils.removeRequestHeader(); + ThreadLocalUtils.removeRequestData(); + configService.setInvalid(false); + List list = new ArrayList<>(); + list.add(new DefaultServiceInstance("foo1", "foo", "foo", 8080, false)); + list.add(new DefaultServiceInstance("bar2", "foo", "bar", 8081, false)); + supplier.setServiceInstances(list); + } + + /** + * 测试路由规则无效时 + */ + @Test + public void testBeforeWhenInvalid() { + configService.setInvalid(true); + interceptor.before(context); + ServiceInstanceListSupplier supplier = (ServiceInstanceListSupplier) context.getObject(); + List instances = supplier.get().blockFirst(); + Assert.assertNotNull(instances); + Assert.assertEquals(2, instances.size()); + } + + /** + * 测试ThreadLocal没有请求数据时 + */ + @Test + public void testBeforeWithoutThreadLocal() { + interceptor.before(context); + ServiceInstanceListSupplier supplier = (ServiceInstanceListSupplier) context.getObject(); + List instances = supplier.get().blockFirst(); + Assert.assertNotNull(instances); + Assert.assertEquals(2, instances.size()); + } + + /** + * 测试obj无效 + */ + @Test + public void testBeforeWithInvalidObject() { + ThreadLocalUtils.setRequestData(new RequestData(Collections.emptyMap(), "", "")); + ExecuteContext context = ExecuteContext.forMemberMethod(new Object(), null, null, null, null); + interceptor.before(context); + Assert.assertNotNull(context.getObject()); + } + + /** + * 测试实例列表为空时 + */ + @Test + public void testBeforeWithEmptyInstances() { + supplier.setServiceInstances(Collections.emptyList()); + ThreadLocalUtils.setRequestData(new RequestData(Collections.emptyMap(), "", "")); + interceptor.before(context); + ServiceInstanceListSupplier supplier = (ServiceInstanceListSupplier) context.getObject(); + List instances = supplier.get().blockFirst(); + Assert.assertNotNull(instances); + Assert.assertEquals(0, instances.size()); + } + + /** + * 测试正常情况 + */ + @Test + public void testBefore() { + ThreadLocalUtils.setRequestData(new RequestData(Collections.emptyMap(), "", "")); + interceptor.before(context); + ServiceInstanceListSupplier supplier = (ServiceInstanceListSupplier) context.getObject(); + List instances = supplier.get().blockFirst(); + Assert.assertNotNull(instances); + Assert.assertEquals(1, instances.size()); + } + + public static class TestServiceInstanceListSupplier implements ServiceInstanceListSupplier { + private Flux> serviceInstances; + + private final String serviceId; + + public TestServiceInstanceListSupplier() { + this.serviceId = "foo"; + } + + public void setServiceInstances(List serviceInstances) { + this.serviceInstances = Flux.just(serviceInstances); + } + + @Override + public String getServiceId() { + return serviceId; + } + + @Override + public Flux> get() { + return serviceInstances; + } + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptorTest.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptorTest.java new file mode 100644 index 0000000000..46996fdbd4 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/ServiceRegistryInterceptorTest.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.core.common.CommonConstant; +import com.huaweicloud.sermant.core.common.LoggerFactory; +import com.huaweicloud.sermant.core.plugin.agent.entity.ExecuteContext; +import com.huaweicloud.sermant.core.service.ServiceManager; +import com.huaweicloud.sermant.router.common.config.RouterConfig; +import com.huaweicloud.sermant.router.common.constants.RouterConstant; +import com.huaweicloud.sermant.router.spring.cache.AppCache; +import com.huaweicloud.sermant.router.spring.service.SpringConfigService; + +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration; +import org.springframework.cloud.client.serviceregistry.Registration; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +/** + * 测试ServiceRegistryInterceptor + * + * @author provenceee + * @since 2022-09-06 + */ +public class ServiceRegistryInterceptorTest { + private final ServiceRegistryInterceptor interceptor; + + private final RouterConfig routerConfig; + + private final ExecuteContext context; + + private static TestSpringConfigService configService; + + private static MockedStatic mockServiceManager; + + /** + * UT执行前进行mock + */ + @BeforeClass + public static void before() { + Map map = new HashMap<>(); + map.put(CommonConstant.LOG_SETTING_FILE_KEY, + ServiceRegistryInterceptorTest.class.getResource("/logback-test.xml").getPath()); + LoggerFactory.init(map); + configService = new TestSpringConfigService(); + mockServiceManager = Mockito.mockStatic(ServiceManager.class); + mockServiceManager.when(() -> ServiceManager.getService(SpringConfigService.class)).thenReturn(configService); + } + + /** + * UT执行后释放mock对象 + */ + @AfterClass + public static void after() { + mockServiceManager.close(); + } + + public ServiceRegistryInterceptorTest() throws IllegalAccessException, NoSuchFieldException { + interceptor = new ServiceRegistryInterceptor(); + routerConfig = new RouterConfig(); + Map parameters = new HashMap<>(); + parameters.put("foo", "foo1"); + parameters.put("bar", "bar1"); + routerConfig.setParameters(parameters); + Field field = interceptor.getClass().getDeclaredField("routerConfig"); + field.setAccessible(true); + Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); + field.set(interceptor, routerConfig); + TestRegistration registration = new TestRegistration(); + registration.getMetadata().put("foo", "foo2"); + TestServiceRegistration serviceRegistration = new TestServiceRegistration(registration); + context = ExecuteContext.forMemberMethod(serviceRegistration, null, null, null, null); + } + + @Test + public void testBefore() { + interceptor.before(context); + Assert.assertEquals("foo", AppCache.INSTANCE.getAppName()); + TestServiceRegistration registration = (TestServiceRegistration) context.getObject(); + Map metadata = registration.getRegistration().getMetadata(); + Assert.assertEquals(routerConfig.getRouterVersion(), metadata.get("version")); + Assert.assertEquals("bar1", metadata.get("bar")); + Assert.assertEquals("foo2", metadata.get("foo")); + } + + @Test + public void testAfter() { + AppCache.INSTANCE.setAppName("foo"); + interceptor.after(context); + Assert.assertEquals(RouterConstant.SPRING_CACHE_NAME, configService.getCacheName()); + Assert.assertEquals("foo", configService.getServiceName()); + } + + public static class TestServiceRegistration extends AbstractAutoServiceRegistration { + private final TestRegistration registration; + + protected TestServiceRegistration(TestRegistration registration) { + super(null, null); + this.registration = registration; + } + + @Override + protected Object getConfiguration() { + return null; + } + + @Override + protected boolean isEnabled() { + return false; + } + + @Override + protected TestRegistration getRegistration() { + return registration; + } + + @Override + protected TestRegistration getManagementRegistration() { + return null; + } + } + + public static class TestRegistration implements Registration { + private final Map metadata = new HashMap<>(); + + @Override + public String getServiceId() { + return "foo"; + } + + @Override + public String getHost() { + return null; + } + + @Override + public int getPort() { + return 0; + } + + @Override + public boolean isSecure() { + return false; + } + + @Override + public URI getUri() { + return null; + } + + @Override + public Map getMetadata() { + return metadata; + } + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/TestLoadBalancerService.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/TestLoadBalancerService.java new file mode 100644 index 0000000000..5d319c3f01 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/TestLoadBalancerService.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.router.spring.service.LoadBalancerService; + +import java.util.List; +import java.util.Map; + +/** + * 测试负载均衡服务 + * + * @author provenceee + * @since 2022-09-08 + */ +public class TestLoadBalancerService implements LoadBalancerService { + @Override + public List getTargetInstances(String targetName, List serverList, String path, + Map> header) { + serverList.remove(0); + return serverList; + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/TestSpringConfigService.java b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/TestSpringConfigService.java new file mode 100644 index 0000000000..72edba2a01 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/java/com/huaweicloud/sermant/router/spring/interceptor/TestSpringConfigService.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.interceptor; + +import com.huaweicloud.sermant.router.spring.service.SpringConfigService; + +/** + * 测试配置服务 + * + * @author provenceee + * @since 2022-09-08 + */ +public class TestSpringConfigService implements SpringConfigService { + private String cacheName; + + private String serviceName; + + private boolean invalid; + + @Override + public void init(String cacheName, String serviceName) { + this.cacheName = cacheName; + this.serviceName = serviceName; + } + + public void setInvalid(boolean invalid) { + this.invalid = invalid; + } + + @Override + public boolean isInValid(String cacheName) { + return invalid; + } + + public String getCacheName() { + return cacheName; + } + + public String getServiceName() { + return serviceName; + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-plugin/src/test/resources/logback-test.xml b/sermant-plugins/sermant-router/spring-router-plugin/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..524cde0e9b --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-plugin/src/test/resources/logback-test.xml @@ -0,0 +1,19 @@ + + + + + + + + + %d{yyyy-MM-dd HH:mm:ss.SSS} [%-5level] [%thread] %logger - %msg%n + + + + + + + + + + \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-service/pom.xml b/sermant-plugins/sermant-router/spring-router-service/pom.xml index c7d668c83d..8f4768303d 100644 --- a/sermant-plugins/sermant-router/spring-router-service/pom.xml +++ b/sermant-plugins/sermant-router/spring-router-service/pom.xml @@ -18,6 +18,7 @@ false 2.7.15 2.6.12 + 2.2.5.RELEASE @@ -43,6 +44,17 @@ router-config-common ${project.version} + + junit + junit + test + + + org.springframework.cloud + spring-cloud-commons + ${spring.cloud.version} + test + diff --git a/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/TestDefaultServiceInstance.java b/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/TestDefaultServiceInstance.java new file mode 100644 index 0000000000..aec11003d8 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/TestDefaultServiceInstance.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring; + +import org.springframework.cloud.client.DefaultServiceInstance; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * 测试ServiceInstance + * + * @author provenceee + * @since 2022-09-13 + */ +public class TestDefaultServiceInstance extends DefaultServiceInstance { + public TestDefaultServiceInstance(Map metadata) { + super("foo", "bar", "bar", 8080, false, Collections.unmodifiableMap(metadata)); + } + + public static TestDefaultServiceInstance getTestDefaultServiceInstance(String version) { + Map metadata = new HashMap<>(); + metadata.put("version", version); + return new TestDefaultServiceInstance(metadata); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/service/LoadBalancerServiceTest.java b/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/service/LoadBalancerServiceTest.java new file mode 100644 index 0000000000..5636c38112 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/service/LoadBalancerServiceTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.service; + +import com.huaweicloud.sermant.router.common.constants.RouterConstant; +import com.huaweicloud.sermant.router.config.label.LabelCache; +import com.huaweicloud.sermant.router.config.label.entity.Match; +import com.huaweicloud.sermant.router.config.label.entity.MatchRule; +import com.huaweicloud.sermant.router.config.label.entity.MatchStrategy; +import com.huaweicloud.sermant.router.config.label.entity.Route; +import com.huaweicloud.sermant.router.config.label.entity.RouterConfiguration; +import com.huaweicloud.sermant.router.config.label.entity.Rule; +import com.huaweicloud.sermant.router.config.label.entity.ValueMatch; +import com.huaweicloud.sermant.router.spring.TestDefaultServiceInstance; +import com.huaweicloud.sermant.router.spring.cache.AppCache; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.cloud.client.ServiceInstance; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 测试LoadBalancerServiceImpl + * + * @author provenceee + * @since 2022-09-13 + */ +public class LoadBalancerServiceTest { + private final LoadBalancerService loadBalancerService; + + public LoadBalancerServiceTest() { + loadBalancerService = new LoadBalancerServiceImpl(); + init(); + } + + @Test + public void testGetTargetInstances() { + List instances = new ArrayList<>(); + ServiceInstance instance1 = TestDefaultServiceInstance.getTestDefaultServiceInstance("1.0.0"); + instances.add(instance1); + ServiceInstance instance2 = TestDefaultServiceInstance.getTestDefaultServiceInstance("1.0.1"); + instances.add(instance2); + Map> header = new HashMap<>(); + header.put("bar", Collections.singletonList("bar1")); + List targetInstances = loadBalancerService.getTargetInstances("foo", instances, null, header); + Assert.assertEquals(1, targetInstances.size()); + Assert.assertEquals(instance2, targetInstances.get(0)); + } + + @Test + public void testGetMismatchInstances() { + List instances = new ArrayList<>(); + ServiceInstance instance1 = TestDefaultServiceInstance.getTestDefaultServiceInstance("1.0.0"); + instances.add(instance1); + ServiceInstance instance2 = TestDefaultServiceInstance.getTestDefaultServiceInstance("1.0.1"); + instances.add(instance2); + instances.add(instance2); + + Map> header = new HashMap<>(); + header.put("bar", Collections.singletonList("bar2")); + List targetInstances = loadBalancerService.getTargetInstances("foo", instances, null, header); + Assert.assertEquals(1, targetInstances.size()); + Assert.assertEquals(instance1, targetInstances.get(0)); + } + + private void init() { + ValueMatch valueMatch = new ValueMatch(); + valueMatch.setMatchStrategy(MatchStrategy.EXACT); + valueMatch.setValues(Collections.singletonList("bar1")); + MatchRule matchRule = new MatchRule(); + matchRule.setValueMatch(valueMatch); + List matchRuleList = new ArrayList<>(); + matchRuleList.add(matchRule); + Map> headers = new HashMap<>(); + headers.put("bar", matchRuleList); + Match match = new Match(); + match.setHeaders(headers); + Rule rule = new Rule(); + rule.setPrecedence(2); + rule.setMatch(match); + Route route = new Route(); + route.setWeight(100); + Map tags = new HashMap<>(); + tags.put("version", "1.0.1"); + route.setTags(tags); + List routeList = new ArrayList<>(); + routeList.add(route); + rule.setRoute(routeList); + List ruleList = new ArrayList<>(); + ruleList.add(rule); + Map> map = new HashMap<>(); + map.put("foo", ruleList); + RouterConfiguration configuration = LabelCache.getLabel(RouterConstant.SPRING_CACHE_NAME); + configuration.resetRouteRule(map); + AppCache.INSTANCE.setAppName("foo"); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/service/RouteHandlerServiceTest.java b/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/service/RouteHandlerServiceTest.java new file mode 100644 index 0000000000..e1f5b4563d --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/service/RouteHandlerServiceTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.service; + +import com.huaweicloud.sermant.router.config.label.entity.Match; +import com.huaweicloud.sermant.router.config.label.entity.MatchRule; +import com.huaweicloud.sermant.router.config.label.entity.Rule; +import com.huaweicloud.sermant.router.config.utils.RuleUtils; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Collections; +import java.util.Set; + +/** + * 测试RouteHandlerService + * + * @author provenceee + * @since 2022-09-13 + */ +public class RouteHandlerServiceTest { + private final RouteHandlerService routeHandlerService; + + public RouteHandlerServiceTest() { + routeHandlerService = new RouteHandlerServiceImpl(); + } + + @Test + public void testGetHeaderKeys() { + Match match = new Match(); + match.setHeaders(Collections.singletonMap("bar", Collections.singletonList(new MatchRule()))); + Rule rule = new Rule(); + rule.setMatch(match); + RuleUtils.updateHeaderKeys("bar", Collections.singletonList(rule)); + Set headerKeys = routeHandlerService.getHeaderKeys(); + Assert.assertEquals(1, headerKeys.size()); + } +} \ No newline at end of file diff --git a/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandlerTest.java b/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandlerTest.java new file mode 100644 index 0000000000..59aae30123 --- /dev/null +++ b/sermant-plugins/sermant-router/spring-router-service/src/test/java/com/huaweicloud/sermant/router/spring/strategy/RuleStrategyHandlerTest.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2022-2022 Huawei Technologies Co., Ltd. All rights reserved. + * + * Licensed 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 com.huaweicloud.sermant.router.spring.strategy; + +import com.huaweicloud.sermant.router.config.label.entity.Route; +import com.huaweicloud.sermant.router.spring.TestDefaultServiceInstance; + +import org.junit.Assert; +import org.junit.Test; +import org.springframework.cloud.client.ServiceInstance; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 测试RuleStrategyHandler + * + * @author provenceee + * @since 2022-09-09 + */ +public class RuleStrategyHandlerTest { + private final List routes; + + /** + * 构造方法 + */ + public RuleStrategyHandlerTest() { + routes = new ArrayList<>(); + Map tags1 = new HashMap<>(); + tags1.put("version", "0.0.1"); + Route route1 = new Route(); + route1.setTags(tags1); + route1.setWeight(100); + routes.add(route1); + Map tags2 = new HashMap<>(); + tags2.put("version", "0.0.2"); + Route route2 = new Route(); + route2.setTags(tags2); + route2.setWeight(100); + routes.add(route2); + } + + /** + * 测试命中0.0.1版本实例的情况 + */ + @Test + public void testDefaultV1() { + List instances = new ArrayList<>(); + ServiceInstance instance1 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.1"); + instances.add(instance1); + ServiceInstance instance2 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.2"); + instances.add(instance2); + List targetInvoker = RuleStrategyHandler.INSTANCE.getTargetInstances(routes, instances); + Assert.assertEquals(100, routes.get(0).getWeight().intValue()); + Assert.assertEquals(1, targetInvoker.size()); + Assert.assertEquals(instance1, targetInvoker.get(0)); + } + + /** + * 测试未命中0.0.1版本实例的情况 + */ + @Test + public void testDefaultMismatch() { + List instances = new ArrayList<>(); + ServiceInstance instance1 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.1"); + instances.add(instance1); + ServiceInstance instance2 = TestDefaultServiceInstance.getTestDefaultServiceInstance("0.0.2"); + instances.add(instance2); + routes.get(0).setWeight(0); + + // 测试匹配上路由,没有随机到实例的情况 + List targetInvoker = RuleStrategyHandler.INSTANCE.getTargetInstances(routes, instances); + Assert.assertEquals(1, targetInvoker.size()); + Assert.assertEquals(instance2, targetInvoker.get(0)); + + // 测试没有匹配上路由,选取不匹配标签的实例的情况 + List> tags = new ArrayList<>(); + tags.add(routes.get(0).getTags()); + List mismatchInvoker = RuleStrategyHandler.INSTANCE.getMismatchInstances(tags, instances); + Assert.assertEquals(1, mismatchInvoker.size()); + Assert.assertEquals(instance2, mismatchInvoker.get(0)); + } +} \ No newline at end of file