add router unit test

pull/204/head
lepdou 2 years ago
parent b39cfe0116
commit dfc7264ade

@ -26,3 +26,7 @@ jobs:
# run: mvn -B package --file pom.xml
- name: Test with Maven
run: mvn -B test --file pom.xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v1
with:
file: ${{ github.workspace }}/target/site/jacoco/jacoco.xml

@ -24,8 +24,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.modules.junit4.PowerMockRunner;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.cloud.client.ServiceInstance;
@ -41,8 +40,7 @@ import static org.mockito.Mockito.when;
*
* @author Haotian Zhang
*/
@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.management.*")
@RunWith(MockitoJUnitRunner.class)
public class PolarisDiscoveryClientTest {
@Mock

@ -25,8 +25,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.modules.junit4.PowerMockRunner;
import org.mockito.junit.MockitoJUnitRunner;
import reactor.core.publisher.Flux;
import reactor.test.StepVerifier;
@ -41,8 +40,7 @@ import static org.mockito.Mockito.when;
*
* @author Haotian Zhang
*/
@RunWith(PowerMockRunner.class)
@PowerMockIgnore("javax.management.*")
@RunWith(MockitoJUnitRunner.class)
public class PolarisReactiveDiscoveryClientTest {
@Mock

@ -91,14 +91,20 @@
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

@ -24,6 +24,7 @@ import java.util.Collections;
import java.util.Map;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.common.util.ExpressionLabelUtils;
import com.tencent.cloud.polaris.ratelimit.RateLimitRuleLabelResolver;
import com.tencent.cloud.polaris.ratelimit.config.PolarisRateLimitProperties;
@ -33,14 +34,14 @@ import com.tencent.polaris.api.plugin.ratelimiter.QuotaResult;
import com.tencent.polaris.ratelimit.api.core.LimitAPI;
import com.tencent.polaris.ratelimit.api.rpc.QuotaRequest;
import com.tencent.polaris.ratelimit.api.rpc.QuotaResponse;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import reactor.core.publisher.Mono;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@ -49,7 +50,6 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilterChain;
@ -58,19 +58,16 @@ import static org.assertj.core.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.anyString;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
/**
* Test for {@link QuotaCheckReactiveFilter}.
*
* @author Haotian Zhang
*/
@RunWith(PowerMockRunner.class)
@PowerMockIgnore({"javax.management.*", "javax.script.*"})
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest(ExpressionLabelUtils.class)
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest(classes = QuotaCheckReactiveFilterTest.TestApplication.class, properties = {
"spring.cloud.polaris.namespace=Test", "spring.cloud.polaris.service=TestApp"
})
@ -80,11 +77,23 @@ public class QuotaCheckReactiveFilterTest {
private QuotaCheckReactiveFilter quotaCheckReactiveFilter;
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
private static MockedStatic<ExpressionLabelUtils> expressionLabelUtilsMockedStatic;
@BeforeClass
public static void beforeClass() {
// mock ExpressionLabelUtils.resolve()
mockStatic(ExpressionLabelUtils.class);
expressionLabelUtilsMockedStatic = mockStatic(ExpressionLabelUtils.class);
when(ExpressionLabelUtils.resolve(any(ServerWebExchange.class), anySet())).thenReturn(Collections.singletonMap("RuleLabelResolver", "RuleLabelResolver"));
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
}
@AfterClass
public static void afterClass() {
mockedApplicationContextAwareUtils.close();
expressionLabelUtilsMockedStatic.close();
}
@Before

@ -29,6 +29,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.common.util.ExpressionLabelUtils;
import com.tencent.cloud.polaris.ratelimit.RateLimitRuleLabelResolver;
import com.tencent.cloud.polaris.ratelimit.config.PolarisRateLimitProperties;
@ -37,20 +38,19 @@ import com.tencent.polaris.api.plugin.ratelimiter.QuotaResult;
import com.tencent.polaris.ratelimit.api.core.LimitAPI;
import com.tencent.polaris.ratelimit.api.rpc.QuotaRequest;
import com.tencent.polaris.ratelimit.api.rpc.QuotaResponse;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.server.ServerWebExchange;
import static org.assertj.core.api.Assertions.assertThat;
@ -58,19 +58,16 @@ import static org.assertj.core.api.Assertions.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anySet;
import static org.mockito.ArgumentMatchers.anyString;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
/**
* Test for {@link QuotaCheckServletFilter}.
*
* @author Haotian Zhang
*/
@RunWith(PowerMockRunner.class)
@PowerMockIgnore({"javax.management.*", "javax.script.*"})
@PowerMockRunnerDelegate(SpringRunner.class)
@PrepareForTest(ExpressionLabelUtils.class)
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest(classes = QuotaCheckServletFilterTest.TestApplication.class, properties = {
"spring.cloud.polaris.namespace=Test", "spring.cloud.polaris.service=TestApp"
})
@ -80,11 +77,23 @@ public class QuotaCheckServletFilterTest {
private QuotaCheckServletFilter quotaCheckServletFilter;
private static MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils;
private static MockedStatic<ExpressionLabelUtils> expressionLabelUtilsMockedStatic;
@BeforeClass
public static void beforeClass() {
// mock ExpressionLabelUtils.resolve()
mockStatic(ExpressionLabelUtils.class);
expressionLabelUtilsMockedStatic = mockStatic(ExpressionLabelUtils.class);
when(ExpressionLabelUtils.resolve(any(ServerWebExchange.class), anySet())).thenReturn(Collections.singletonMap("RuleLabelResolver", "RuleLabelResolver"));
mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class);
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn("unit-test");
}
@AfterClass
public static void afterClass() throws Exception {
mockedApplicationContextAwareUtils.close();
expressionLabelUtilsMockedStatic.close();
}
@Before

@ -25,21 +25,19 @@ import com.tencent.polaris.ratelimit.api.rpc.QuotaResultCode;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.modules.junit4.PowerMockRunner;
import org.mockito.junit.MockitoJUnitRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Test for {@link QuotaCheckUtils}.
*
* @author Haotian Zhang
*/
@RunWith(PowerMockRunner.class)
@PowerMockIgnore({"javax.management.*", "javax.script.*"})
@RunWith(MockitoJUnitRunner.class)
public class QuotaCheckUtilsTest {
private LimitAPI limitAPI;

@ -24,24 +24,20 @@ import com.tencent.cloud.polaris.ratelimit.config.PolarisRateLimitProperties;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.mockito.junit.MockitoJUnitRunner;
import static com.tencent.cloud.polaris.ratelimit.constant.RateLimitConstant.QUOTA_LIMITED_INFO;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
/**
* Test for {@link RateLimitUtils}.
*
* @author Haotian Zhang
*/
@RunWith(PowerMockRunner.class)
@PowerMockIgnore({"javax.management.*", "javax.script.*"})
@PrepareForTest(ResourceFileUtils.class)
@RunWith(MockitoJUnitRunner.class)
public class RateLimitUtilsTest {
@BeforeClass

@ -52,6 +52,30 @@
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

@ -71,14 +71,14 @@ import org.springframework.util.CollectionUtils;
*/
public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule {
private final static String STRATEGY_RANDOM = "random";
private final static String STRATEGY_ROUND_ROBIN = "roundRobin";
private final static String STRATEGY_WEIGHT = "polarisWeighted";
private final static String STRATEGY_RETRY = "retry";
private final static String STRATEGY_RESPONSE_TIME_WEIGHTED = "responseTimeWeighted";
private final static String STRATEGY_BEST_AVAILABLE = "bestAvailable";
private final static String STRATEGY_ZONE_AVOIDANCE = "zoneAvoidance";
private final static String STRATEGY_AVAILABILITY_FILTERING = "availabilityFilteringRule";
final static String STRATEGY_RANDOM = "random";
final static String STRATEGY_ROUND_ROBIN = "roundRobin";
final static String STRATEGY_WEIGHT = "polarisWeighted";
final static String STRATEGY_RETRY = "retry";
final static String STRATEGY_RESPONSE_TIME_WEIGHTED = "responseTimeWeighted";
final static String STRATEGY_BEST_AVAILABLE = "bestAvailable";
final static String STRATEGY_ZONE_AVOIDANCE = "zoneAvoidance";
final static String STRATEGY_AVAILABILITY_FILTERING = "availabilityFilteringRule";
private final PolarisLoadBalancerProperties loadBalancerProperties;
private final PolarisNearByRouterProperties polarisNearByRouterProperties;
@ -129,7 +129,7 @@ public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule {
return delegateRule.choose(key);
}
private List<Server> doRouter(List<Server> allServers, Object key) {
List<Server> doRouter(List<Server> allServers, Object key) {
ServiceInstances serviceInstances = LoadBalancerUtils.transferServersToServiceInstances(allServers);
// filter instance by routers
@ -145,7 +145,7 @@ public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule {
return filteredInstances;
}
private ProcessRoutersRequest buildProcessRoutersRequest(ServiceInstances serviceInstances, Object key) {
ProcessRoutersRequest buildProcessRoutersRequest(ServiceInstances serviceInstances, Object key) {
ProcessRoutersRequest processRoutersRequest = new ProcessRoutersRequest();
processRoutersRequest.setDstInstances(serviceInstances);
@ -195,9 +195,6 @@ public class PolarisLoadBalancerCompositeRule extends AbstractLoadBalancerRule {
public AbstractLoadBalancerRule getRule() {
String loadBalanceStrategy = loadBalancerProperties.getStrategy();
if (org.springframework.util.StringUtils.isEmpty(loadBalanceStrategy)) {
return new RoundRobinRule();
}
switch (loadBalanceStrategy) {
case STRATEGY_RANDOM:

@ -46,7 +46,11 @@ public class PolarisRouterContext {
if (CollectionUtils.isEmpty(labels)) {
return Collections.emptyMap();
}
return Collections.unmodifiableMap(labels.get(labelType));
Map<String, String> subLabels = labels.get(labelType);
if (CollectionUtils.isEmpty(subLabels)) {
return Collections.emptyMap();
}
return Collections.unmodifiableMap(subLabels);
}
public void setLabels(String labelType, Map<String, String> subLabels) {

@ -28,5 +28,5 @@ public class RouterConstants {
/**
* the header of router label.
*/
public static final String ROUTER_LABEL_HEADER = "router-label";
public static final String ROUTER_LABEL_HEADER = "internal-router-label";
}

@ -18,6 +18,7 @@
package com.tencent.cloud.polaris.router;
import java.util.Collections;
import java.util.List;
import com.netflix.loadbalancer.ILoadBalancer;
@ -48,16 +49,25 @@ public class SimpleLoadBalancer implements ILoadBalancer {
@Override
public List<Server> getServerList(boolean availableOnly) {
return servers;
if (servers == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(servers);
}
@Override
public List<Server> getReachableServers() {
return servers;
if (servers == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(servers);
}
@Override
public List<Server> getAllServers() {
return servers;
if (servers == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(servers);
}
}

@ -18,6 +18,7 @@
package com.tencent.cloud.polaris.router.feign;
import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -62,7 +63,8 @@ public class FeignExpressionLabelUtils {
labels.put(labelKey, request.method());
}
else if (StringUtils.equalsIgnoreCase(ExpressionLabelUtils.LABEL_URI, labelKey)) {
labels.put(labelKey, request.request().url());
URI uri = URI.create(request.request().url());
labels.put(labelKey, uri.getPath());
}
}

@ -51,11 +51,18 @@ public class PolarisFeignLoadBalancer extends FeignLoadBalancer {
protected void customizeLoadBalancerCommandBuilder(RibbonRequest request, IClientConfig config,
LoadBalancerCommand.Builder<RibbonResponse> builder) {
Map<String, Collection<String>> headers = request.getRequest().headers();
PolarisRouterContext routerContext = buildRouterContext(headers);
builder.withServerLocator(routerContext);
}
//set method to public for unit test
PolarisRouterContext buildRouterContext(Map<String, Collection<String>> headers) {
Collection<String> labelHeaderValues = headers.get(RouterConstants.ROUTER_LABEL_HEADER);
if (CollectionUtils.isEmpty(labelHeaderValues)) {
builder.withServerLocator(null);
return;
return null;
}
PolarisRouterContext routerContext = new PolarisRouterContext();
@ -76,6 +83,6 @@ public class PolarisFeignLoadBalancer extends FeignLoadBalancer {
}
});
builder.withServerLocator(routerContext);
return routerContext;
}
}

@ -74,12 +74,13 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered
@Override
public void apply(RequestTemplate requestTemplate) {
Map<String, String> labels = new HashMap<>();
// local service labels
Map<String, String> labels = new HashMap<>(metadataLocalProperties.getContent());
// labels from downstream
Map<String, String> transitiveLabels = MetadataContextHolder.get()
.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
labels.putAll(transitiveLabels);
// labels from rule expression
String peerServiceName = requestTemplate.feignTarget().name();
Map<String, String> ruleExpressionLabels = getRuleExpressionLabels(requestTemplate, peerServiceName);
labels.putAll(ruleExpressionLabels);
// labels from request
if (!CollectionUtils.isEmpty(routerLabelResolvers)) {
@ -96,14 +97,10 @@ public class RouterLabelFeignInterceptor implements RequestInterceptor, Ordered
});
}
// labels from rule expression
String peerServiceName = requestTemplate.feignTarget().name();
Map<String, String> ruleExpressionLabels = getRuleExpressionLabels(requestTemplate, peerServiceName);
labels.putAll(ruleExpressionLabels);
//local service labels
labels.putAll(metadataLocalProperties.getContent());
// labels from downstream
Map<String, String> transitiveLabels = MetadataContextHolder.get()
.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
labels.putAll(transitiveLabels);
// Because when the label is placed in RequestTemplate.header,
// RequestTemplate will parse the header according to the regular, which conflicts with the expression.

@ -105,13 +105,15 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor {
this.requestFactory.createRequest(request, body, execution));
}
private PolarisRouterContext genRouterContext(HttpRequest request, byte[] body, String peerServiceName) {
Map<String, String> labels = new HashMap<>();
PolarisRouterContext genRouterContext(HttpRequest request, byte[] body, String peerServiceName) {
// local service labels
Map<String, String> labels = new HashMap<>(metadataLocalProperties.getContent());
// labels from downstream
Map<String, String> transitiveLabels = MetadataContextHolder.get()
.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
labels.putAll(transitiveLabels);
// labels from rule expression
Map<String, String> ruleExpressionLabels = getExpressionLabels(request, peerServiceName);
if (!CollectionUtils.isEmpty(ruleExpressionLabels)) {
labels.putAll(ruleExpressionLabels);
}
// labels from request
if (!CollectionUtils.isEmpty(routerLabelResolvers)) {
@ -128,14 +130,10 @@ public class PolarisLoadBalancerInterceptor extends LoadBalancerInterceptor {
});
}
// labels from rule expression
Map<String, String> ruleExpressionLabels = getExpressionLabels(request, peerServiceName);
if (!CollectionUtils.isEmpty(ruleExpressionLabels)) {
labels.putAll(ruleExpressionLabels);
}
// local service labels
labels.putAll(metadataLocalProperties.getContent());
// labels from downstream
Map<String, String> transitiveLabels = MetadataContextHolder.get()
.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
labels.putAll(transitiveLabels);
PolarisRouterContext routerContext = new PolarisRouterContext();

@ -0,0 +1,362 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.polaris.router;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.AvailabilityFilteringRule;
import com.netflix.loadbalancer.BestAvailableRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RetryRule;
import com.netflix.loadbalancer.RoundRobinRule;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.WeightedResponseTimeRule;
import com.netflix.loadbalancer.ZoneAvoidanceRule;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.pojo.PolarisServer;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.polaris.loadbalancer.PolarisWeightedRule;
import com.tencent.cloud.polaris.loadbalancer.config.PolarisLoadBalancerProperties;
import com.tencent.cloud.polaris.router.config.PolarisMetadataRouterProperties;
import com.tencent.cloud.polaris.router.config.PolarisNearByRouterProperties;
import com.tencent.cloud.polaris.router.config.PolarisRuleBasedRouterProperties;
import com.tencent.polaris.api.pojo.DefaultInstance;
import com.tencent.polaris.api.pojo.DefaultServiceInstances;
import com.tencent.polaris.api.pojo.Instance;
import com.tencent.polaris.api.pojo.ServiceInstances;
import com.tencent.polaris.api.pojo.ServiceKey;
import com.tencent.polaris.plugins.router.metadata.MetadataRouter;
import com.tencent.polaris.plugins.router.nearby.NearbyRouter;
import com.tencent.polaris.plugins.router.rule.RuleBasedRouter;
import com.tencent.polaris.router.api.core.RouterAPI;
import com.tencent.polaris.router.api.rpc.ProcessRoutersRequest;
import com.tencent.polaris.router.api.rpc.ProcessRoutersResponse;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
/**
* test for {@link PolarisLoadBalancerCompositeRule}
*@author lepdou 2022-05-26
*/
@RunWith(MockitoJUnitRunner.class)
public class PolarisLoadBalancerCompositeRuleTest {
@Mock
private PolarisLoadBalancerProperties polarisLoadBalancerProperties;
@Mock
private PolarisNearByRouterProperties polarisNearByRouterProperties;
@Mock
private PolarisMetadataRouterProperties polarisMetadataRouterProperties;
@Mock
private PolarisRuleBasedRouterProperties polarisRuleBasedRouterProperties;
@Mock
private RouterAPI routerAPI;
private IClientConfig config;
private static AtomicBoolean initTransitiveMetadata = new AtomicBoolean(false);
private String testNamespace = "testNamespace";
private String testCallerService = "testCallerService";
private String testCalleeService = "testCalleeService";
@Before
public void before() {
config = new DefaultClientConfigImpl();
config.loadDefaultValues();
}
@Test
public void testGetDefaultLB() {
when(polarisLoadBalancerProperties.getStrategy()).thenReturn("");
PolarisLoadBalancerCompositeRule compositeRule = new PolarisLoadBalancerCompositeRule(routerAPI,
polarisLoadBalancerProperties, polarisNearByRouterProperties,
polarisMetadataRouterProperties, polarisRuleBasedRouterProperties, config);
AbstractLoadBalancerRule defaultRule = compositeRule.getRule();
Assert.assertTrue(defaultRule instanceof ZoneAvoidanceRule);
}
@Test
public void testRandomLB() {
when(polarisLoadBalancerProperties.getStrategy()).thenReturn(PolarisLoadBalancerCompositeRule.STRATEGY_RANDOM);
PolarisLoadBalancerCompositeRule compositeRule = new PolarisLoadBalancerCompositeRule(routerAPI,
polarisLoadBalancerProperties, polarisNearByRouterProperties,
polarisMetadataRouterProperties, polarisRuleBasedRouterProperties, config);
AbstractLoadBalancerRule lbRule = compositeRule.getRule();
Assert.assertTrue(lbRule instanceof RandomRule);
}
@Test
public void testWeightLB() {
when(polarisLoadBalancerProperties.getStrategy()).thenReturn(PolarisLoadBalancerCompositeRule.STRATEGY_WEIGHT);
PolarisLoadBalancerCompositeRule compositeRule = new PolarisLoadBalancerCompositeRule(routerAPI,
polarisLoadBalancerProperties, polarisNearByRouterProperties,
polarisMetadataRouterProperties, polarisRuleBasedRouterProperties, config);
AbstractLoadBalancerRule lbRule = compositeRule.getRule();
Assert.assertTrue(lbRule instanceof PolarisWeightedRule);
}
@Test
public void testRetryLB() {
when(polarisLoadBalancerProperties.getStrategy()).thenReturn(PolarisLoadBalancerCompositeRule.STRATEGY_RETRY);
PolarisLoadBalancerCompositeRule compositeRule = new PolarisLoadBalancerCompositeRule(routerAPI,
polarisLoadBalancerProperties, polarisNearByRouterProperties,
polarisMetadataRouterProperties, polarisRuleBasedRouterProperties, config);
AbstractLoadBalancerRule lbRule = compositeRule.getRule();
Assert.assertTrue(lbRule instanceof RetryRule);
}
@Test
public void testWeightedResponseTimeLB() {
when(polarisLoadBalancerProperties.getStrategy()).thenReturn(PolarisLoadBalancerCompositeRule.STRATEGY_RESPONSE_TIME_WEIGHTED);
PolarisLoadBalancerCompositeRule compositeRule = new PolarisLoadBalancerCompositeRule(routerAPI,
polarisLoadBalancerProperties, polarisNearByRouterProperties,
polarisMetadataRouterProperties, polarisRuleBasedRouterProperties, config);
AbstractLoadBalancerRule lbRule = compositeRule.getRule();
Assert.assertTrue(lbRule instanceof WeightedResponseTimeRule);
}
@Test
public void tesBestAvailableLB() {
when(polarisLoadBalancerProperties.getStrategy()).thenReturn(PolarisLoadBalancerCompositeRule.STRATEGY_BEST_AVAILABLE);
PolarisLoadBalancerCompositeRule compositeRule = new PolarisLoadBalancerCompositeRule(routerAPI,
polarisLoadBalancerProperties, polarisNearByRouterProperties,
polarisMetadataRouterProperties, polarisRuleBasedRouterProperties, config);
AbstractLoadBalancerRule lbRule = compositeRule.getRule();
Assert.assertTrue(lbRule instanceof BestAvailableRule);
}
@Test
public void tesRoundRobinLB() {
when(polarisLoadBalancerProperties.getStrategy()).thenReturn(PolarisLoadBalancerCompositeRule.STRATEGY_ROUND_ROBIN);
PolarisLoadBalancerCompositeRule compositeRule = new PolarisLoadBalancerCompositeRule(routerAPI,
polarisLoadBalancerProperties, polarisNearByRouterProperties,
polarisMetadataRouterProperties, polarisRuleBasedRouterProperties, config);
AbstractLoadBalancerRule lbRule = compositeRule.getRule();
Assert.assertTrue(lbRule instanceof RoundRobinRule);
}
@Test
public void testAvailabilityFilteringLB() {
when(polarisLoadBalancerProperties.getStrategy()).thenReturn(PolarisLoadBalancerCompositeRule.STRATEGY_AVAILABILITY_FILTERING);
PolarisLoadBalancerCompositeRule compositeRule = new PolarisLoadBalancerCompositeRule(routerAPI,
polarisLoadBalancerProperties, polarisNearByRouterProperties,
polarisMetadataRouterProperties, polarisRuleBasedRouterProperties, config);
AbstractLoadBalancerRule lbRule = compositeRule.getRule();
Assert.assertTrue(lbRule instanceof AvailabilityFilteringRule);
}
@Test
public void testBuildMetadataRouteRequest() {
when(polarisMetadataRouterProperties.isEnabled()).thenReturn(true);
when(polarisLoadBalancerProperties.getStrategy()).thenReturn("");
try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) {
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn(testCallerService);
setTransitiveMetadata();
PolarisLoadBalancerCompositeRule compositeRule = new PolarisLoadBalancerCompositeRule(routerAPI,
polarisLoadBalancerProperties, polarisNearByRouterProperties,
polarisMetadataRouterProperties, polarisRuleBasedRouterProperties, config);
ServiceInstances serviceInstances = assembleServiceInstances();
PolarisRouterContext routerContext = assembleRouterContext();
ProcessRoutersRequest request = compositeRule.buildProcessRoutersRequest(serviceInstances, routerContext);
Map<String, String> routerMetadata = request.getRouterMetadata(MetadataRouter.ROUTER_TYPE_METADATA);
Assert.assertEquals(1, routerMetadata.size());
Assert.assertEquals(0, request.getRouterMetadata(NearbyRouter.ROUTER_TYPE_NEAR_BY).size());
Assert.assertEquals(1, request.getRouterMetadata(RuleBasedRouter.ROUTER_TYPE_RULE_BASED).size());
Assert.assertEquals("false", request.getRouterMetadata(RuleBasedRouter.ROUTER_TYPE_RULE_BASED)
.get(RuleBasedRouter.ROUTER_ENABLED));
}
}
@Test
public void testBuildNearbyRouteRequest() {
when(polarisNearByRouterProperties.isEnabled()).thenReturn(true);
when(polarisLoadBalancerProperties.getStrategy()).thenReturn("");
try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) {
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn(testCallerService);
setTransitiveMetadata();
PolarisLoadBalancerCompositeRule compositeRule = new PolarisLoadBalancerCompositeRule(routerAPI,
polarisLoadBalancerProperties, polarisNearByRouterProperties,
polarisMetadataRouterProperties, polarisRuleBasedRouterProperties, config);
ServiceInstances serviceInstances = assembleServiceInstances();
PolarisRouterContext routerContext = assembleRouterContext();
ProcessRoutersRequest request = compositeRule.buildProcessRoutersRequest(serviceInstances, routerContext);
Map<String, String> routerMetadata = request.getRouterMetadata(NearbyRouter.ROUTER_TYPE_NEAR_BY);
Assert.assertEquals(0, request.getRouterMetadata(MetadataRouter.ROUTER_TYPE_METADATA).size());
Assert.assertEquals(1, routerMetadata.size());
Assert.assertEquals("true", routerMetadata.get(NearbyRouter.ROUTER_ENABLED));
Assert.assertEquals(1, request.getRouterMetadata(RuleBasedRouter.ROUTER_TYPE_RULE_BASED).size());
Assert.assertEquals("false", request.getRouterMetadata(RuleBasedRouter.ROUTER_TYPE_RULE_BASED)
.get(RuleBasedRouter.ROUTER_ENABLED));
}
}
@Test
public void testBuildRuleBasedRouteRequest() {
when(polarisRuleBasedRouterProperties.isEnabled()).thenReturn(true);
when(polarisLoadBalancerProperties.getStrategy()).thenReturn("");
try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) {
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())).
thenReturn(testCallerService);
setTransitiveMetadata();
PolarisLoadBalancerCompositeRule compositeRule = new PolarisLoadBalancerCompositeRule(routerAPI,
polarisLoadBalancerProperties, polarisNearByRouterProperties,
polarisMetadataRouterProperties, polarisRuleBasedRouterProperties, config);
ServiceInstances serviceInstances = assembleServiceInstances();
PolarisRouterContext routerContext = assembleRouterContext();
ProcessRoutersRequest request = compositeRule.buildProcessRoutersRequest(serviceInstances, routerContext);
Map<String, String> routerMetadata = request.getRouterMetadata(RuleBasedRouter.ROUTER_TYPE_RULE_BASED);
Assert.assertEquals(1, routerMetadata.size());
Assert.assertEquals(0, request.getRouterMetadata(MetadataRouter.ROUTER_TYPE_METADATA).size());
Assert.assertEquals(0, request.getRouterMetadata(NearbyRouter.ROUTER_TYPE_NEAR_BY).size());
Assert.assertEquals(1, request.getRouterMetadata(RuleBasedRouter.ROUTER_TYPE_RULE_BASED).size());
Assert.assertEquals("true", request.getRouterMetadata(RuleBasedRouter.ROUTER_TYPE_RULE_BASED)
.get(RuleBasedRouter.ROUTER_ENABLED));
}
}
@Test
public void testRouter() {
when(polarisRuleBasedRouterProperties.isEnabled()).thenReturn(true);
when(polarisLoadBalancerProperties.getStrategy()).thenReturn("");
try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) {
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn(testCallerService);
setTransitiveMetadata();
PolarisLoadBalancerCompositeRule compositeRule = new PolarisLoadBalancerCompositeRule(routerAPI,
polarisLoadBalancerProperties, polarisNearByRouterProperties,
polarisMetadataRouterProperties, polarisRuleBasedRouterProperties, config);
ProcessRoutersResponse assembleResponse = assembleProcessRoutersResponse();
when(routerAPI.processRouters(any())).thenReturn(assembleResponse);
List<Server> servers = compositeRule.doRouter(assembleServers(), assembleRouterContext());
Assert.assertEquals(assembleResponse.getServiceInstances().getInstances().size(), servers.size());
}
}
private void setTransitiveMetadata() {
if (initTransitiveMetadata.compareAndSet(false, true)) {
// mock transitive metadata
MetadataContext metadataContext = Mockito.mock(MetadataContext.class);
try (MockedStatic<MetadataContextHolder> mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class)) {
mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext);
}
}
}
private ServiceInstances assembleServiceInstances() {
ServiceKey serviceKey = new ServiceKey(testNamespace, testCalleeService);
List<Instance> instances = new LinkedList<>();
instances.add(new DefaultInstance());
instances.add(new DefaultInstance());
instances.add(new DefaultInstance());
instances.add(new DefaultInstance());
instances.add(new DefaultInstance());
return new DefaultServiceInstances(serviceKey, instances);
}
private PolarisRouterContext assembleRouterContext() {
PolarisRouterContext routerContext = new PolarisRouterContext();
Map<String, String> transitiveLabels = new HashMap<>();
transitiveLabels.put("k1", "v1");
Map<String, String> routerLabels = new HashMap<>();
routerLabels.put("k2", "v2");
routerLabels.put("k3", "v3");
routerContext.setLabels(PolarisRouterContext.TRANSITIVE_LABELS, transitiveLabels);
routerContext.setLabels(PolarisRouterContext.RULE_ROUTER_LABELS, routerLabels);
return routerContext;
}
private ProcessRoutersResponse assembleProcessRoutersResponse() {
return new ProcessRoutersResponse(assembleServiceInstances());
}
private List<Server> assembleServers() {
ServiceInstances serviceInstances = assembleServiceInstances();
List<Server> servers = new LinkedList<>();
servers.add(new PolarisServer(serviceInstances, new DefaultInstance()));
servers.add(new PolarisServer(serviceInstances, new DefaultInstance()));
servers.add(new PolarisServer(serviceInstances, new DefaultInstance()));
servers.add(new PolarisServer(serviceInstances, new DefaultInstance()));
return servers;
}
}

@ -0,0 +1,64 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.polaris.router;
import java.util.HashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
/**
* test for {@link PolarisRouterContext}
*
*@author lepdou 2022-05-26
*/
public class PolarisRouterContextTest {
@Test
public void testNormalGetterSetter() {
Map<String, String> labels = new HashMap<>();
labels.put("k1", "v1");
labels.put("k2", "v2");
PolarisRouterContext routerContext = new PolarisRouterContext();
routerContext.setLabels(PolarisRouterContext.RULE_ROUTER_LABELS, labels);
Assert.assertEquals(0, routerContext.getLabels(PolarisRouterContext.TRANSITIVE_LABELS).size());
Assert.assertEquals(2, routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS).size());
Assert.assertEquals("v1", routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS).get("k1"));
Assert.assertEquals("v2", routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS).get("k2"));
Assert.assertNull(routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS).get("k3"));
}
@Test
public void testSetNull() {
PolarisRouterContext routerContext = new PolarisRouterContext();
routerContext.setLabels(PolarisRouterContext.RULE_ROUTER_LABELS, null);
Assert.assertEquals(0, routerContext.getLabels(PolarisRouterContext.TRANSITIVE_LABELS).size());
Assert.assertEquals(0, routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS).size());
}
@Test
public void testGetEmptyRouterContext() {
PolarisRouterContext routerContext = new PolarisRouterContext();
Assert.assertEquals(0, routerContext.getLabels(PolarisRouterContext.TRANSITIVE_LABELS).size());
Assert.assertEquals(0, routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS).size());
}
}

@ -0,0 +1,93 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.polaris.router;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Lists;
import com.tencent.cloud.polaris.context.ServiceRuleManager;
import com.tencent.polaris.client.pb.ModelProto;
import com.tencent.polaris.client.pb.RoutingProto;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.Mockito.when;
/**
* test for {@link RouterRuleLabelResolver}
*@author lepdou 2022-05-26
*/
@RunWith(MockitoJUnitRunner.class)
public class RouterRuleLabelResolverTest {
@Mock
private ServiceRuleManager serviceRuleManager;
private final String testNamespace = "testNamespace";
private final String testSourceService = "sourceService";
private final String testDstService = "dstService";
@Test
public void test() {
Map<String, ModelProto.MatchString> labels = new HashMap<>();
ModelProto.MatchString matchString = ModelProto.MatchString.getDefaultInstance();
String validKey1 = "${http.header.uid}";
String validKey2 = "${http.query.name}";
String validKey3 = "${http.method}";
String validKey4 = "${http.uri}";
String invalidKey = "${http.expression.wrong}";
labels.put(validKey1, matchString);
labels.put(validKey2, matchString);
labels.put(validKey3, matchString);
labels.put(validKey4, matchString);
labels.put(invalidKey, matchString);
RoutingProto.Source source1 = RoutingProto.Source.newBuilder().putAllMetadata(labels).build();
RoutingProto.Source source2 = RoutingProto.Source.newBuilder().putAllMetadata(labels).build();
RoutingProto.Source source3 = RoutingProto.Source.newBuilder().putAllMetadata(new HashMap<>()).build();
List<RoutingProto.Route> routes = new LinkedList<>();
RoutingProto.Route route = RoutingProto.Route.newBuilder()
.addAllSources(Lists.newArrayList(source1, source2, source3))
.build();
routes.add(route);
when(serviceRuleManager.getServiceRouterRule(testNamespace, testSourceService, testDstService)).thenReturn(routes);
RouterRuleLabelResolver resolver = new RouterRuleLabelResolver(serviceRuleManager);
Set<String> resolvedExpressionLabelKeys = resolver.getExpressionLabelKeys(testNamespace, testSourceService, testDstService);
Assert.assertNotNull(resolvedExpressionLabelKeys);
Assert.assertEquals(4, resolvedExpressionLabelKeys.size());
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey1));
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey2));
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey3));
Assert.assertTrue(resolvedExpressionLabelKeys.contains(validKey4));
Assert.assertFalse(resolvedExpressionLabelKeys.contains(invalidKey));
}
}

@ -0,0 +1,71 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.polaris.router;
import java.util.LinkedList;
import java.util.List;
import com.netflix.loadbalancer.Server;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
/**
* test for {@link SimpleLoadBalancer}
*@author lepdou 2022-05-26
*/
public class SimpleLoadBalancerTest {
@Test
public void testSetterGetter() {
List<Server> servers = new LinkedList<>();
servers.add(Mockito.mock(Server.class));
servers.add(Mockito.mock(Server.class));
servers.add(Mockito.mock(Server.class));
servers.add(Mockito.mock(Server.class));
servers.add(Mockito.mock(Server.class));
SimpleLoadBalancer simpleLoadBalancer = new SimpleLoadBalancer();
simpleLoadBalancer.addServers(servers);
List<Server> allServers = simpleLoadBalancer.getAllServers();
List<Server> reachableServers = simpleLoadBalancer.getReachableServers();
List<Server> availableServers = simpleLoadBalancer.getServerList(true);
Assert.assertEquals(servers.size(), allServers.size());
Assert.assertEquals(servers.size(), reachableServers.size());
Assert.assertEquals(servers.size(), availableServers.size());
}
@Test
public void testSetNull() {
SimpleLoadBalancer simpleLoadBalancer = new SimpleLoadBalancer();
simpleLoadBalancer.addServers(null);
List<Server> allServers = simpleLoadBalancer.getAllServers();
List<Server> reachableServers = simpleLoadBalancer.getReachableServers();
List<Server> availableServers = simpleLoadBalancer.getServerList(true);
Assert.assertEquals(0, allServers.size());
Assert.assertEquals(0, reachableServers.size());
Assert.assertEquals(0, availableServers.size());
}
}

@ -0,0 +1,140 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.polaris.router.feign;
import java.util.HashMap;
import java.util.Map;
import com.google.common.collect.Sets;
import feign.Request;
import feign.RequestTemplate;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.util.StringUtils;
/**
* Test for {@link FeignExpressionLabelUtils}
*@author lepdou 2022-05-26
*/
public class FeignExpressionLabelUtilsTest {
@Test
public void testGetHeaderLabel() {
String headerKey = "uid";
String headerValue = "1000";
String headerKey2 = "teacher.age";
String headerValue2 = "1000";
RequestTemplate requestTemplate = new RequestTemplate();
requestTemplate.header(headerKey, headerValue);
requestTemplate.header(headerKey2, headerValue2);
String labelKey1 = "${http.header.uid}";
String labelKey2 = "${http.header.name}";
String labelKey3 = "${http.headername}";
String labelKey4 = "${http.header.}";
String labelKey5 = "${http.header.teacher.age}";
Map<String, String> result = FeignExpressionLabelUtils.resolve(requestTemplate,
Sets.newHashSet(labelKey1, labelKey2, labelKey3, labelKey4, labelKey5));
Assert.assertFalse(result.isEmpty());
Assert.assertEquals(headerValue, result.get(labelKey1));
Assert.assertEquals(headerValue2, result.get(labelKey5));
Assert.assertTrue(StringUtils.isEmpty(result.get(labelKey2)));
Assert.assertTrue(StringUtils.isEmpty(result.get(labelKey3)));
Assert.assertTrue(StringUtils.isEmpty(result.get(labelKey4)));
}
@Test
public void testGetQueryLabel() {
String headerKey = "uid";
String headerValue = "1000";
String headerKey2 = "teacher.age";
String headerValue2 = "1000";
RequestTemplate requestTemplate = new RequestTemplate();
requestTemplate.query(headerKey, headerValue);
requestTemplate.query(headerKey2, headerValue2);
String labelKey1 = "${http.query.uid}";
String labelKey2 = "${http.query.name}";
String labelKey3 = "${http.queryname}";
String labelKey4 = "${http.query.}";
String labelKey5 = "${http.query.teacher.age}";
Map<String, String> result = FeignExpressionLabelUtils.resolve(requestTemplate,
Sets.newHashSet(labelKey1, labelKey2, labelKey3, labelKey4, labelKey5));
Assert.assertFalse(result.isEmpty());
Assert.assertEquals(headerValue, result.get(labelKey1));
Assert.assertEquals(headerValue2, result.get(labelKey5));
Assert.assertTrue(StringUtils.isEmpty(result.get(labelKey2)));
Assert.assertTrue(StringUtils.isEmpty(result.get(labelKey3)));
Assert.assertTrue(StringUtils.isEmpty(result.get(labelKey4)));
}
@Test
public void testGetMethod() {
RequestTemplate requestTemplate = new RequestTemplate();
requestTemplate.method(Request.HttpMethod.GET);
String labelKey1 = "${http.method}";
Map<String, String> result = FeignExpressionLabelUtils.resolve(requestTemplate,
Sets.newHashSet(labelKey1));
Assert.assertFalse(result.isEmpty());
Assert.assertEquals("GET", result.get(labelKey1));
}
@Test
public void testGetUri() {
String uri = "/user/get";
RequestTemplate requestTemplate = new RequestTemplate();
requestTemplate.uri(uri);
requestTemplate.method(Request.HttpMethod.GET);
requestTemplate.target("http://localhost");
requestTemplate = requestTemplate.resolve(new HashMap<>());
String labelKey1 = "${http.uri}";
Map<String, String> result = FeignExpressionLabelUtils.resolve(requestTemplate,
Sets.newHashSet(labelKey1));
Assert.assertFalse(result.isEmpty());
Assert.assertEquals(uri, result.get(labelKey1));
}
@Test
public void testGetUri2() {
String uri = "/";
RequestTemplate requestTemplate = new RequestTemplate();
requestTemplate.uri(uri);
requestTemplate.method(Request.HttpMethod.GET);
requestTemplate.target("http://localhost");
requestTemplate = requestTemplate.resolve(new HashMap<>());
String labelKey1 = "${http.uri}";
Map<String, String> result = FeignExpressionLabelUtils.resolve(requestTemplate,
Sets.newHashSet(labelKey1));
Assert.assertFalse(result.isEmpty());
Assert.assertEquals(uri, result.get(labelKey1));
}
}

@ -0,0 +1,104 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.polaris.router.feign;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.loadbalancer.ILoadBalancer;
import com.tencent.cloud.polaris.router.SimpleLoadBalancer;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
import org.springframework.cloud.openfeign.ribbon.FeignLoadBalancer;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* Test for {@link PolarisCachingSpringLoadBalanceFactory}
*@author lepdou 2022-05-26
*/
@RunWith(MockitoJUnitRunner.class)
public class PolarisCachingSpringLoadBalanceFactoryTest {
@Mock
private SpringClientFactory factory;
private String service1 = "service1";
private String service2 = "service2";
@Test
public void test() {
PolarisCachingSpringLoadBalanceFactory polarisCachingSpringLoadBalanceFactory =
new PolarisCachingSpringLoadBalanceFactory(factory, null);
DefaultClientConfigImpl config1 = new DefaultClientConfigImpl();
config1.loadDefaultValues();
config1.setClientName(service1);
DefaultClientConfigImpl config2 = new DefaultClientConfigImpl();
config2.loadDefaultValues();
config2.setClientName(service2);
when(factory.getClientConfig(service1)).thenReturn(config1);
when(factory.getClientConfig(service2)).thenReturn(config2);
ILoadBalancer loadBalancer = new SimpleLoadBalancer();
when(factory.getLoadBalancer(service1)).thenReturn(loadBalancer);
when(factory.getLoadBalancer(service2)).thenReturn(loadBalancer);
ServerIntrospector serverIntrospector = new DefaultServerIntrospector();
when(factory.getInstance(service1, ServerIntrospector.class)).thenReturn(serverIntrospector);
when(factory.getInstance(service2, ServerIntrospector.class)).thenReturn(serverIntrospector);
// load balancer for service1
FeignLoadBalancer feignLoadBalancer = polarisCachingSpringLoadBalanceFactory.create(service1);
Assert.assertNotNull(feignLoadBalancer);
verify(factory).getClientConfig(service1);
verify(factory, times(0)).getClientConfig(service2);
verify(factory).getLoadBalancer(service1);
verify(factory, times(0)).getLoadBalancer(service2);
verify(factory).getInstance(service1, ServerIntrospector.class);
verify(factory, times(0)).getInstance(service2, ServerIntrospector.class);
Assert.assertEquals(loadBalancer, feignLoadBalancer.getLoadBalancer());
Assert.assertEquals(service1, feignLoadBalancer.getClientName());
// load balancer for service2
FeignLoadBalancer feignLoadBalancer2 = polarisCachingSpringLoadBalanceFactory.create(service2);
// load balancer for service1 again
feignLoadBalancer = polarisCachingSpringLoadBalanceFactory.create(service1);
Assert.assertNotNull(feignLoadBalancer);
verify(factory).getClientConfig(service1);
verify(factory).getClientConfig(service2);
verify(factory).getLoadBalancer(service1);
verify(factory).getLoadBalancer(service2);
verify(factory).getInstance(service1, ServerIntrospector.class);
verify(factory).getInstance(service2, ServerIntrospector.class);
Assert.assertEquals(loadBalancer, feignLoadBalancer2.getLoadBalancer());
Assert.assertEquals(service2, feignLoadBalancer2.getClientName());
}
}

@ -0,0 +1,121 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.polaris.router.feign;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.netflix.client.config.DefaultClientConfigImpl;
import com.netflix.loadbalancer.ILoadBalancer;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.router.PolarisRouterContext;
import com.tencent.cloud.polaris.router.RouterConstants;
import com.tencent.cloud.polaris.router.SimpleLoadBalancer;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.cloud.netflix.ribbon.DefaultServerIntrospector;
import org.springframework.cloud.netflix.ribbon.ServerIntrospector;
import static org.mockito.Mockito.anyString;
/**
* test for {@link PolarisFeignLoadBalancer}
* @author lepdou 2022-05-26
*/
@RunWith(MockitoJUnitRunner.class)
public class PolarisFeignLoadBalancerTest {
@Test
public void testHasRouterContext() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.loadDefaultValues();
ILoadBalancer loadBalancer = new SimpleLoadBalancer();
ServerIntrospector serverIntrospector = new DefaultServerIntrospector();
PolarisFeignLoadBalancer polarisFeignLoadBalancer = new PolarisFeignLoadBalancer(loadBalancer, config, serverIntrospector);
Map<String, String> labels = new HashMap<>();
labels.put("k1", "v1");
labels.put("k2", "v2");
List<String> headerValues = new ArrayList<>();
headerValues.add(JacksonUtils.serialize2Json(labels));
Map<String, Collection<String>> headers = new HashMap<>();
headers.put(RouterConstants.ROUTER_LABEL_HEADER, headerValues);
// mock ApplicationContextAwareUtils#getProperties
try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) {
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())).thenReturn("unit-test");
MetadataContext metadataContext = Mockito.mock(MetadataContext.class);
// mock MetadataContextHolder#get
try (MockedStatic<MetadataContextHolder> mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class)) {
mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext);
PolarisRouterContext routerContext = polarisFeignLoadBalancer.buildRouterContext(headers);
Assert.assertNotNull(routerContext);
Map<String, String> routerLabels = routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS);
Assert.assertNotNull(routerLabels);
Assert.assertEquals("v1", routerLabels.get("k1"));
Assert.assertEquals("v2", routerLabels.get("k2"));
Assert.assertNull(routerLabels.get("k3"));
}
}
}
@Test
public void testHasNoneRouterContext() {
DefaultClientConfigImpl config = new DefaultClientConfigImpl();
config.loadDefaultValues();
ILoadBalancer loadBalancer = new SimpleLoadBalancer();
ServerIntrospector serverIntrospector = new DefaultServerIntrospector();
PolarisFeignLoadBalancer polarisFeignLoadBalancer = new PolarisFeignLoadBalancer(loadBalancer, config, serverIntrospector);
Map<String, Collection<String>> headers = new HashMap<>();
// mock ApplicationContextAwareUtils#getProperties
try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) {
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())).thenReturn("unit-test");
MetadataContext metadataContext = Mockito.mock(MetadataContext.class);
// mock MetadataContextHolder#get
try (MockedStatic<MetadataContextHolder> mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class)) {
mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext);
PolarisRouterContext routerContext = polarisFeignLoadBalancer.buildRouterContext(headers);
Assert.assertNull(routerContext);
}
}
}
}

@ -0,0 +1,142 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.polaris.router.feign;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.common.util.ExpressionLabelUtils;
import com.tencent.cloud.common.util.JacksonUtils;
import com.tencent.cloud.polaris.router.RouterConstants;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
import feign.RequestTemplate;
import feign.Target;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
/**
* test for {@link RouterLabelFeignInterceptor}
* @author lepdou 2022-05-26
*/
@RunWith(MockitoJUnitRunner.class)
public class RouterLabelFeignInterceptorTest {
@Mock
private MetadataLocalProperties metadataLocalProperties;
@Mock
private RouterRuleLabelResolver routerRuleLabelResolver;
@Mock
private RouterLabelResolver routerLabelResolver;
@Test
public void testResolveRouterLabel() {
RouterLabelFeignInterceptor routerLabelFeignInterceptor = new RouterLabelFeignInterceptor(
Collections.singletonList(routerLabelResolver),
metadataLocalProperties, routerRuleLabelResolver);
// mock request template
RequestTemplate requestTemplate = new RequestTemplate();
String headerUidKey = "uid";
String headerUidValue = "1000";
requestTemplate.header(headerUidKey, headerUidValue);
String peerService = "peerService";
Target.EmptyTarget<Object> target = Target.EmptyTarget.create(Object.class, peerService);
requestTemplate.feignTarget(target);
// mock ApplicationContextAwareUtils#getProperties
try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) {
String testService = "callerService";
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn(testService);
MetadataContext metadataContext = Mockito.mock(MetadataContext.class);
// mock transitive metadata
Map<String, String> transitiveLabels = new HashMap<>();
transitiveLabels.put("k1", "v1");
transitiveLabels.put("k2", "v22");
when(metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE)).thenReturn(transitiveLabels);
// mock MetadataContextHolder#get
try (MockedStatic<MetadataContextHolder> mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class)) {
mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext);
// mock custom resolved labels from request
Map<String, String> customResolvedLabels = new HashMap<>();
customResolvedLabels.put("k2", "v2");
customResolvedLabels.put("k3", "v3");
when(routerLabelResolver.resolve(requestTemplate)).thenReturn(customResolvedLabels);
// mock expression rule labels
Set<String> expressionKeys = new HashSet<>();
expressionKeys.add("${http.header.uid}");
expressionKeys.add("${http.header.name}");
when(routerRuleLabelResolver.getExpressionLabelKeys(MetadataContext.LOCAL_NAMESPACE,
MetadataContext.LOCAL_SERVICE, peerService)).thenReturn(expressionKeys);
// mock local metadata
Map<String, String> localMetadata = new HashMap<>();
localMetadata.put("k3", "v31");
localMetadata.put("k4", "v4");
when(metadataLocalProperties.getContent()).thenReturn(localMetadata);
routerLabelFeignInterceptor.apply(requestTemplate);
Collection<String> routerLabels = requestTemplate.headers().get(RouterConstants.ROUTER_LABEL_HEADER);
Assert.assertNotNull(routerLabels);
for (String value : routerLabels) {
Map<String, String> labels = unescape(JacksonUtils.deserialize2Map(value));
Assert.assertEquals("v1", labels.get("k1"));
Assert.assertEquals("v22", labels.get("k2"));
Assert.assertEquals("v3", labels.get("k3"));
Assert.assertEquals("v4", labels.get("k4"));
Assert.assertEquals(headerUidValue, labels.get("${http.header.uid}"));
Assert.assertEquals("", labels.get("${http.header.name}"));
}
}
}
}
private Map<String, String> unescape(Map<String, String> labels) {
Map<String, String> result = new HashMap<>();
for (Map.Entry<String, String> entry : labels.entrySet()) {
result.put(ExpressionLabelUtils.unescape(entry.getKey()), ExpressionLabelUtils.unescape(entry.getValue()));
}
return result;
}
}

@ -0,0 +1,93 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.polaris.router.resttemplate;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.BeanFactoryUtils;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerInterceptor;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory;
import static org.mockito.Mockito.when;
/**
* Test for ${@link PolarisLoadBalancerBeanPostProcessor}
* @author lepdou 2022-05-26
*/
@RunWith(MockitoJUnitRunner.class)
public class PolarisLoadBalancerBeanPostProcessorTest {
@Mock
private LoadBalancerClient loadBalancerClient;
@Mock
private LoadBalancerRequestFactory loadBalancerRequestFactory;
@Mock
private MetadataLocalProperties metadataLocalProperties;
@Mock
private RouterRuleLabelResolver routerRuleLabelResolver;
@Mock
private BeanFactory beanFactory;
@Test
public void testWrapperLoadBalancerInterceptor() {
when(beanFactory.getBean(LoadBalancerRequestFactory.class)).thenReturn(loadBalancerRequestFactory);
when(beanFactory.getBean(LoadBalancerClient.class)).thenReturn(loadBalancerClient);
when(beanFactory.getBean(MetadataLocalProperties.class)).thenReturn(metadataLocalProperties);
when(beanFactory.getBean(RouterRuleLabelResolver.class)).thenReturn(routerRuleLabelResolver);
try (MockedStatic<BeanFactoryUtils> mockedBeanFactoryUtils = Mockito.mockStatic(BeanFactoryUtils.class)) {
mockedBeanFactoryUtils.when(() -> BeanFactoryUtils.getBeans(beanFactory, RouterLabelResolver.class))
.thenReturn(null);
LoadBalancerInterceptor loadBalancerInterceptor = new LoadBalancerInterceptor(loadBalancerClient, loadBalancerRequestFactory);
PolarisLoadBalancerBeanPostProcessor processor = new PolarisLoadBalancerBeanPostProcessor();
processor.setBeanFactory(beanFactory);
Object bean = processor.postProcessBeforeInitialization(loadBalancerInterceptor, "");
Assert.assertTrue(bean instanceof PolarisLoadBalancerInterceptor);
}
}
@Test
public void testNotWrapperLoadBalancerInterceptor() {
PolarisLoadBalancerBeanPostProcessor processor = new PolarisLoadBalancerBeanPostProcessor();
processor.setBeanFactory(beanFactory);
OtherBean otherBean = new OtherBean();
Object bean = processor.postProcessBeforeInitialization(otherBean, "");
Assert.assertFalse(bean instanceof PolarisLoadBalancerInterceptor);
Assert.assertTrue(bean instanceof OtherBean);
}
static class OtherBean {
}
}

@ -0,0 +1,250 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.polaris.router.resttemplate;
import java.io.IOException;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.cloud.common.metadata.config.MetadataLocalProperties;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.cloud.polaris.router.PolarisRouterContext;
import com.tencent.cloud.polaris.router.RouterRuleLabelResolver;
import com.tencent.cloud.polaris.router.spi.RouterLabelResolver;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest;
import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestFactory;
import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.mock.http.client.MockClientHttpResponse;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* test for {@link PolarisLoadBalancerInterceptor}
* @author lepdou 2022-05-26
*/
@RunWith(MockitoJUnitRunner.class)
public class PolarisLoadBalancerInterceptorTest {
@Mock
private RibbonLoadBalancerClient loadBalancerClient;
@Mock
private LoadBalancerRequestFactory loadBalancerRequestFactory;
@Mock
private RouterLabelResolver routerLabelResolver;
@Mock
private MetadataLocalProperties metadataLocalProperties;
@Mock
private RouterRuleLabelResolver routerRuleLabelResolver;
@Test
public void testProxyRibbonLoadBalance() throws Exception {
String callerService = "callerService";
String calleeService = "calleeService";
HttpRequest request = new MockedHttpRequest("http://" + calleeService + "/user/get");
// mock local metadata
Map<String, String> localMetadata = new HashMap<>();
localMetadata.put("k1", "v1");
localMetadata.put("k2", "v2");
when(metadataLocalProperties.getContent()).thenReturn(localMetadata);
// mock custom resolved from request
Map<String, String> customResolvedLabels = new HashMap<>();
customResolvedLabels.put("k3", "v3");
customResolvedLabels.put("k4", "v4");
when(routerLabelResolver.resolve(request, null)).thenReturn(customResolvedLabels);
// mock expression rule labels
Set<String> expressionKeys = new HashSet<>();
expressionKeys.add("${http.method}");
expressionKeys.add("${http.uri}");
when(routerRuleLabelResolver.getExpressionLabelKeys(callerService, callerService, calleeService)).thenReturn(expressionKeys);
try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) {
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn(callerService);
MetadataContext metadataContext = Mockito.mock(MetadataContext.class);
// mock transitive metadata
Map<String, String> transitiveLabels = new HashMap<>();
transitiveLabels.put("k1", "v1");
transitiveLabels.put("k2", "v22");
when(metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE)).thenReturn(transitiveLabels);
try (MockedStatic<MetadataContextHolder> mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class)) {
mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext);
LoadBalancerRequest<ClientHttpResponse> loadBalancerRequest = new MockedLoadBalancerRequest<>();
when(loadBalancerRequestFactory.createRequest(request, null, null)).thenReturn(loadBalancerRequest);
PolarisLoadBalancerInterceptor polarisLoadBalancerInterceptor = new PolarisLoadBalancerInterceptor(loadBalancerClient,
loadBalancerRequestFactory, Collections.singletonList(routerLabelResolver), metadataLocalProperties, routerRuleLabelResolver);
polarisLoadBalancerInterceptor.intercept(request, null, null);
verify(metadataLocalProperties).getContent();
verify(routerRuleLabelResolver).getExpressionLabelKeys(callerService, callerService, calleeService);
verify(routerLabelResolver).resolve(request, null);
}
}
}
@Test
public void testNotProxyRibbonLoadBalance() throws IOException {
String calleeService = "calleeService";
HttpRequest request = new MockedHttpRequest("http://" + calleeService + "/user/get");
LoadBalancerRequest<ClientHttpResponse> loadBalancerRequest = new MockedLoadBalancerRequest<>();
when(loadBalancerRequestFactory.createRequest(request, null, null)).thenReturn(loadBalancerRequest);
LoadBalancerClient notRibbonLoadBalancerClient = Mockito.mock(LoadBalancerClient.class);
ClientHttpResponse mockedResponse = new MockClientHttpResponse(new byte[] {}, HttpStatus.OK);
when(notRibbonLoadBalancerClient.execute(calleeService, loadBalancerRequest)).thenReturn(mockedResponse);
PolarisLoadBalancerInterceptor polarisLoadBalancerInterceptor = new PolarisLoadBalancerInterceptor(
notRibbonLoadBalancerClient, loadBalancerRequestFactory,
Collections.singletonList(routerLabelResolver), metadataLocalProperties,
routerRuleLabelResolver);
ClientHttpResponse response = polarisLoadBalancerInterceptor.intercept(request, null, null);
Assert.assertEquals(mockedResponse, response);
verify(loadBalancerRequestFactory).createRequest(request, null, null);
verify(notRibbonLoadBalancerClient).execute(calleeService, loadBalancerRequest);
}
@Test
public void testRouterContext() throws Exception {
String callerService = "callerService";
String calleeService = "calleeService";
HttpRequest request = new MockedHttpRequest("http://" + calleeService + "/user/get");
// mock local metadata
Map<String, String> localMetadata = new HashMap<>();
localMetadata.put("k1", "v1");
localMetadata.put("k2", "v2");
when(metadataLocalProperties.getContent()).thenReturn(localMetadata);
// mock custom resolved from request
Map<String, String> customResolvedLabels = new HashMap<>();
customResolvedLabels.put("k2", "v22");
customResolvedLabels.put("k4", "v4");
when(routerLabelResolver.resolve(request, null)).thenReturn(customResolvedLabels);
// mock expression rule labels
Set<String> expressionKeys = new HashSet<>();
expressionKeys.add("${http.method}");
expressionKeys.add("${http.uri}");
when(routerRuleLabelResolver.getExpressionLabelKeys(callerService, callerService, calleeService)).thenReturn(expressionKeys);
try (MockedStatic<ApplicationContextAwareUtils> mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class)) {
mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString()))
.thenReturn(callerService);
MetadataContext metadataContext = Mockito.mock(MetadataContext.class);
// mock transitive metadata
Map<String, String> transitiveLabels = new HashMap<>();
transitiveLabels.put("k1", "v1");
transitiveLabels.put("k2", "v22");
when(metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE)).thenReturn(transitiveLabels);
try (MockedStatic<MetadataContextHolder> mockedMetadataContextHolder = Mockito.mockStatic(MetadataContextHolder.class)) {
mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext);
PolarisLoadBalancerInterceptor polarisLoadBalancerInterceptor = new PolarisLoadBalancerInterceptor(loadBalancerClient,
loadBalancerRequestFactory, Collections.singletonList(routerLabelResolver), metadataLocalProperties, routerRuleLabelResolver);
PolarisRouterContext routerContext = polarisLoadBalancerInterceptor.genRouterContext(request, null, calleeService);
verify(metadataLocalProperties).getContent();
verify(routerRuleLabelResolver).getExpressionLabelKeys(callerService, callerService, calleeService);
verify(routerLabelResolver).resolve(request, null);
Assert.assertEquals("v1", routerContext.getLabels(PolarisRouterContext.TRANSITIVE_LABELS).get("k1"));
Assert.assertEquals("v22", routerContext.getLabels(PolarisRouterContext.TRANSITIVE_LABELS).get("k2"));
Assert.assertEquals("v1", routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS).get("k1"));
Assert.assertEquals("v22", routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS).get("k2"));
Assert.assertEquals("v4", routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS).get("k4"));
Assert.assertEquals("GET", routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS).get("${http.method}"));
Assert.assertEquals("/user/get", routerContext.getLabels(PolarisRouterContext.RULE_ROUTER_LABELS).get("${http.uri}"));
}
}
}
static class MockedLoadBalancerRequest<T> implements LoadBalancerRequest<T> {
@Override
public T apply(ServiceInstance instance) throws Exception {
return null;
}
}
static class MockedHttpRequest implements HttpRequest {
private URI uri;
MockedHttpRequest(String url) {
this.uri = URI.create(url);
}
@Override
public String getMethodValue() {
return HttpMethod.GET.name();
}
@Override
public URI getURI() {
return uri;
}
@Override
public HttpHeaders getHeaders() {
return null;
}
}
}

@ -20,8 +20,11 @@ package com.tencent.cloud.common.util;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.util.StringUtils;
/**
* the utils of parse address.
*
@ -36,6 +39,9 @@ public final class AddressUtils {
}
public static List<String> parseAddressList(String addressInfo) {
if (StringUtils.isEmpty(addressInfo)) {
return Collections.emptyList();
}
List<String> addressList = new ArrayList<>();
String[] addresses = addressInfo.split(ADDRESS_SEPARATOR);
for (String address : addresses) {

@ -87,7 +87,7 @@ public class ExpressionLabelUtils {
/**
* the escape prefix of label.
*/
public static final String LABEL_ESCAPE_PREFIX = "$$$$";
public static final String LABEL_ESCAPE_PREFIX = "##@$@##";
public static boolean isExpressionLabel(String labelKey) {
if (StringUtils.isEmpty(labelKey)) {
@ -119,6 +119,9 @@ public class ExpressionLabelUtils {
Map<String, String> labels = new HashMap<>();
for (String labelKey : labelKeys) {
if (!isExpressionLabel(labelKey)) {
continue;
}
if (StringUtils.startsWithIgnoreCase(labelKey, LABEL_HEADER_PREFIX)) {
String headerKey = parseHeaderKey(labelKey);
if (StringUtils.isBlank(headerKey)) {
@ -159,6 +162,9 @@ public class ExpressionLabelUtils {
Map<String, String> labels = new HashMap<>();
for (String labelKey : labelKeys) {
if (!isExpressionLabel(labelKey)) {
continue;
}
if (StringUtils.startsWithIgnoreCase(labelKey, LABEL_HEADER_PREFIX)) {
String headerKey = parseHeaderKey(labelKey);
if (StringUtils.isBlank(headerKey)) {
@ -199,6 +205,9 @@ public class ExpressionLabelUtils {
Map<String, String> labels = new HashMap<>();
for (String labelKey : labelKeys) {
if (!isExpressionLabel(labelKey)) {
continue;
}
if (StringUtils.startsWithIgnoreCase(labelKey, LABEL_HEADER_PREFIX)) {
String headerKey = parseHeaderKey(labelKey);
if (StringUtils.isBlank(headerKey)) {

@ -0,0 +1,66 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.common.util;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
/**
* test for {@link AddressUtils}
*@author lepdou 2022-05-27
*/
@RunWith(MockitoJUnitRunner.class)
public class AddressUtilsTest {
@Test
public void testEmptyStr() {
List<String> result = AddressUtils.parseAddressList("");
Assert.assertEquals(0, result.size());
}
@Test
public void testNullStr() {
List<String> result = AddressUtils.parseAddressList(null);
Assert.assertEquals(0, result.size());
}
@Test
public void testOneStr() {
String host1 = "http://localhost";
List<String> result = AddressUtils.parseAddressList(host1);
Assert.assertEquals(1, result.size());
Assert.assertTrue(result.contains("localhost"));
}
@Test
public void testMultiStr() {
String host1 = "http://localhost";
String host2 = "http://localhost2";
String host3 = "http://localhost3";
List<String> result = AddressUtils.parseAddressList(host1 + "," + host2 + "," + host3);
Assert.assertEquals(3, result.size());
Assert.assertTrue(result.contains("localhost"));
Assert.assertTrue(result.contains("localhost2"));
Assert.assertTrue(result.contains("localhost3"));
}
}

@ -0,0 +1,246 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.common.util;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.Sets;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpMethod;
import org.springframework.mock.http.client.MockClientHttpRequest;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.MockCookie;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
/**
* test for {@link ExpressionLabelUtils}
*@author lepdou 2022-05-27
*/
@RunWith(MockitoJUnitRunner.class)
public class ExpressionLabelUtilsTest {
@Test
public void testExpressionLabel() {
String validLabel1 = "${http.query.uid}";
String validLabel2 = "${http.header.uid}";
String validLabel3 = "${http.cookie.uid}";
String validLabel4 = "${http.method}";
String validLabel5 = "${http.uri}";
String invalidLabel1 = "${http.queryuid}";
String invalidLabel2 = "{http.query.uid}";
String invalidLabel3 = "${http.query.uid";
String invalidLabel4 = "$ {http.query.uid}";
String invalidLabel5 = "${ http.query.uid}";
String invalidLabel6 = "${query.uid}";
String invalidLabel7 = "http.query.uid";
String invalidLabel8 = "$${http.uri}";
String invalidLabel9 = "#{http.uri}";
Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(validLabel1));
Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(validLabel2));
Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(validLabel3));
Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(validLabel4));
Assert.assertTrue(ExpressionLabelUtils.isExpressionLabel(validLabel5));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel1));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel2));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel3));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel4));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel5));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel6));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel7));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel8));
Assert.assertFalse(ExpressionLabelUtils.isExpressionLabel(invalidLabel9));
}
@Test
public void testEscape() {
String validLabel1 = "${http.query.uid}";
String validLabel2 = "${http.header.uid}";
String validLabel3 = "${http.cookie.uid}";
String validLabel4 = "${http.method}";
String validLabel5 = "${http.uri}";
String invalidLabel1 = "${http.queryuid}";
String invalidLabel2 = "{http.query.uid}";
String invalidLabel3 = "${http.query.uid";
String invalidLabel4 = "$ {http.query.uid}";
String invalidLabel5 = "${ http.query.uid}";
String invalidLabel6 = "${query.uid}";
String invalidLabel7 = "http.query.uid";
String invalidLabel8 = "$${http.uri}";
String invalidLabel9 = "#{http.uri}";
Assert.assertEquals(validLabel1, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(validLabel1)));
Assert.assertEquals(validLabel2, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(validLabel2)));
Assert.assertEquals(validLabel3, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(validLabel3)));
Assert.assertEquals(validLabel4, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(validLabel4)));
Assert.assertEquals(validLabel5, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(validLabel5)));
Assert.assertEquals(invalidLabel1, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel1)));
Assert.assertEquals(invalidLabel2, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel2)));
Assert.assertEquals(invalidLabel3, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel3)));
Assert.assertEquals(invalidLabel4, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel4)));
Assert.assertEquals(invalidLabel5, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel5)));
Assert.assertEquals(invalidLabel6, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel6)));
Assert.assertEquals(invalidLabel7, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel7)));
Assert.assertEquals(invalidLabel8, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel8)));
Assert.assertEquals(invalidLabel9, ExpressionLabelUtils.unescape(ExpressionLabelUtils.escape(invalidLabel9)));
}
@Test
public void testResolveHttpServletRequest() {
String validLabel1 = "${http.query.uid}";
String validLabel2 = "${http.header.uid}";
String validLabel3 = "${http.cookie.uid}";
String validLabel4 = "${http.method}";
String validLabel5 = "${http.uri}";
String invalidLabel1 = "${http.queryuid}";
String invalidLabel2 = "{http.query.uid}";
String invalidLabel3 = "${http.query.uid";
String invalidLabel4 = "$ {http.query.uid}";
String invalidLabel5 = "${ http.query.uid}";
String invalidLabel6 = "${query.uid}";
String invalidLabel7 = "http.query.uid";
String invalidLabel8 = "$${http.uri}";
String invalidLabel9 = "#{http.uri}";
Set<String> labelKeys = Sets.newHashSet(validLabel1, validLabel2, validLabel3, validLabel4, validLabel5,
invalidLabel1, invalidLabel2, invalidLabel3, invalidLabel4, invalidLabel5, invalidLabel6, invalidLabel7,
invalidLabel8, invalidLabel9);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setQueryString("uid=zhangsan");
request.addHeader("uid", "zhangsan");
request.setCookies(new MockCookie("uid", "zhangsan"));
request.setMethod(HttpMethod.GET.name());
request.setRequestURI("/users");
Map<String, String> result = ExpressionLabelUtils.resolve(request, labelKeys);
Assert.assertEquals("zhangsan", result.get(validLabel1));
Assert.assertEquals("zhangsan", result.get(validLabel2));
Assert.assertEquals("zhangsan", result.get(validLabel3));
Assert.assertEquals("GET", result.get(validLabel4));
Assert.assertEquals("/users", result.get(validLabel5));
Assert.assertNull(result.get(invalidLabel1));
Assert.assertNull(result.get(invalidLabel2));
Assert.assertNull(result.get(invalidLabel3));
Assert.assertNull(result.get(invalidLabel4));
Assert.assertNull(result.get(invalidLabel5));
Assert.assertNull(result.get(invalidLabel6));
Assert.assertNull(result.get(invalidLabel7));
Assert.assertNull(result.get(invalidLabel8));
Assert.assertNull(result.get(invalidLabel9));
}
@Test
public void testResolveServerWebExchange() {
String validLabel1 = "${http.query.uid}";
String validLabel2 = "${http.header.uid}";
String validLabel3 = "${http.cookie.uid}";
String validLabel4 = "${http.method}";
String validLabel5 = "${http.uri}";
String invalidLabel1 = "${http.queryuid}";
String invalidLabel2 = "{http.query.uid}";
String invalidLabel3 = "${http.query.uid";
String invalidLabel4 = "$ {http.query.uid}";
String invalidLabel5 = "${ http.query.uid}";
String invalidLabel6 = "${query.uid}";
String invalidLabel7 = "http.query.uid";
String invalidLabel8 = "$${http.uri}";
String invalidLabel9 = "#{http.uri}";
Set<String> labelKeys = Sets.newHashSet(validLabel1, validLabel2, validLabel3, validLabel4, validLabel5,
invalidLabel1, invalidLabel2, invalidLabel3, invalidLabel4, invalidLabel5, invalidLabel6, invalidLabel7,
invalidLabel8, invalidLabel9);
MockServerHttpRequest httpRequest = MockServerHttpRequest.get("http://calleeService/user/get?uid=zhangsan")
.header("uid", "zhangsan")
.cookie(new HttpCookie("uid", "zhangsan")).build();
MockServerWebExchange exchange = new MockServerWebExchange.Builder(httpRequest).build();
Map<String, String> result = ExpressionLabelUtils.resolve(exchange, labelKeys);
Assert.assertEquals("zhangsan", result.get(validLabel1));
Assert.assertEquals("zhangsan", result.get(validLabel2));
Assert.assertEquals("zhangsan", result.get(validLabel3));
Assert.assertEquals("GET", result.get(validLabel4));
Assert.assertEquals("/user/get", result.get(validLabel5));
Assert.assertNull(result.get(invalidLabel1));
Assert.assertNull(result.get(invalidLabel2));
Assert.assertNull(result.get(invalidLabel3));
Assert.assertNull(result.get(invalidLabel4));
Assert.assertNull(result.get(invalidLabel5));
Assert.assertNull(result.get(invalidLabel6));
Assert.assertNull(result.get(invalidLabel7));
Assert.assertNull(result.get(invalidLabel8));
Assert.assertNull(result.get(invalidLabel9));
}
@Test
public void testResolveHttpRequest() {
String validLabel1 = "${http.query.uid}";
String validLabel2 = "${http.header.uid}";
String validLabel3 = "${http.cookie.uid}";
String validLabel4 = "${http.method}";
String validLabel5 = "${http.uri}";
String invalidLabel1 = "${http.queryuid}";
String invalidLabel2 = "{http.query.uid}";
String invalidLabel3 = "${http.query.uid";
String invalidLabel4 = "$ {http.query.uid}";
String invalidLabel5 = "${ http.query.uid}";
String invalidLabel6 = "${query.uid}";
String invalidLabel7 = "http.query.uid";
String invalidLabel8 = "$${http.uri}";
String invalidLabel9 = "#{http.uri}";
Set<String> labelKeys = Sets.newHashSet(validLabel1, validLabel2, validLabel3, validLabel4, validLabel5,
invalidLabel1, invalidLabel2, invalidLabel3, invalidLabel4, invalidLabel5, invalidLabel6, invalidLabel7,
invalidLabel8, invalidLabel9);
MockClientHttpRequest request = new MockClientHttpRequest();
request.setMethod(HttpMethod.GET);
request.setURI(URI.create("http://calleeService/user/get?uid=zhangsan"));
request.getHeaders().add("uid", "zhangsan");
Map<String, String> result = ExpressionLabelUtils.resolve(request, labelKeys);
Assert.assertEquals("zhangsan", result.get(validLabel1));
Assert.assertEquals("zhangsan", result.get(validLabel2));
Assert.assertNull(result.get(validLabel3));
Assert.assertEquals("GET", result.get(validLabel4));
Assert.assertEquals("/user/get", result.get(validLabel5));
Assert.assertNull(result.get(invalidLabel1));
Assert.assertNull(result.get(invalidLabel2));
Assert.assertNull(result.get(invalidLabel3));
Assert.assertNull(result.get(invalidLabel4));
Assert.assertNull(result.get(invalidLabel5));
Assert.assertNull(result.get(invalidLabel6));
Assert.assertNull(result.get(invalidLabel7));
Assert.assertNull(result.get(invalidLabel8));
Assert.assertNull(result.get(invalidLabel9));
}
}

@ -0,0 +1,50 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.common.util;
import java.util.HashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
/**
* test for {@link JacksonUtils}
*@author lepdou 2022-05-27
*/
@RunWith(MockitoJUnitRunner.class)
public class JacksonUtilsTest {
@Test
public void test() {
Map<String, String> sourceMap = new HashMap<>();
sourceMap.put("k1", "v1");
sourceMap.put("k2", "v2");
sourceMap.put("k3", "v3");
Map<String, String> map = JacksonUtils.deserialize2Map(JacksonUtils.serialize2Json(sourceMap));
Assert.assertEquals(sourceMap.size(), map.size());
Assert.assertEquals(sourceMap.get("k1"), map.get("k1"));
Assert.assertEquals(sourceMap.get("k2"), map.get("k2"));
Assert.assertEquals(sourceMap.get("k3"), map.get("k3"));
}
}

@ -0,0 +1,46 @@
/*
* Tencent is pleased to support the open source community by making Spring Cloud Tencent available.
*
* Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.common.util;
import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
/**
* test for {@link ResourceFileUtils}
*@author lepdou 2022-05-27
*/
@RunWith(MockitoJUnitRunner.class)
public class ResourceFileUtilsTest {
@Test
public void testReadExistedFile() throws IOException {
String content = ResourceFileUtils.readFile("test.txt");
Assert.assertEquals("just for test\n", content);
}
@Test
public void testReadNotExistedFile() throws IOException {
String content = ResourceFileUtils.readFile("not_existed_test.txt");
Assert.assertEquals("", content);
}
}

@ -73,6 +73,8 @@
<revision>1.5.0-Hoxton.SR9-SNAPSHOT</revision>
<polaris.version>1.6.0-SNAPSHOT</polaris.version>
<powermock.version>2.0.0</powermock.version>
<mocktio.version>4.5.1</mocktio.version>
<byte-buddy.version>1.12.10</byte-buddy.version>
<!-- Maven Plugin Versions -->
<maven-source-plugin.version>3.2.0</maven-source-plugin.version>
@ -158,6 +160,27 @@
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>${mocktio.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mocktio.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>${byte-buddy.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

Loading…
Cancel
Save