parent
b39cfe0116
commit
dfc7264ade
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
just for test
|
Loading…
Reference in new issue