Code optimize & add junit tests (#702)

pull/711/head
DerekYRC 2 years ago committed by GitHub
parent 8bd30f3269
commit c7d37d6e58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -5,3 +5,4 @@
- [Optimize: Register the service with the ProviderAPI#registerInstance method.](https://github.com/Tencent/spring-cloud-tencent/pull/687)
- [Optimize:optimize spring annotation.](https://github.com/Tencent/spring-cloud-tencent/pull/689)
- [docs:update PR template.](https://github.com/Tencent/spring-cloud-tencent/pull/692)
- [Code optimize & add junit tests.](https://github.com/Tencent/spring-cloud-tencent/pull/702)

@ -31,7 +31,6 @@ public final class ConditionUtils {
}
public static boolean match(Map<String, String> actualValues, List<Condition> conditions) {
boolean allMatched = true;
for (Condition condition : conditions) {
List<String> expectedValues = condition.getValues();
String operation = condition.getOperation();
@ -39,10 +38,9 @@ public final class ConditionUtils {
String actualValue = actualValues.get(key);
if (!Operation.match(expectedValues, actualValue, operation)) {
allMatched = false;
break;
return false;
}
}
return allMatched;
return true;
}
}

@ -30,5 +30,11 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

@ -20,7 +20,6 @@ package com.tencent.cloud.plugin.gateway;
import java.util.List;
import com.tencent.cloud.plugin.gateway.staining.StainingProperties;
import com.tencent.cloud.plugin.gateway.staining.TrafficStainer;
import com.tencent.cloud.plugin.gateway.staining.TrafficStainingGatewayFilter;
import com.tencent.cloud.plugin.gateway.staining.rule.RuleStainingExecutor;
@ -45,44 +44,33 @@ import org.springframework.context.annotation.Configuration;
public class SCGPluginsAutoConfiguration {
@Configuration
@ConditionalOnProperty("spring.cloud.tencent.plugin.scg.staining.enabled")
public static class StainingPluginConfiguration {
@ConditionalOnProperty("spring.cloud.tencent.plugin.scg.staining.rule-staining.enabled")
@ConditionalOnPolarisConfigEnabled
public static class RuleStainingPluginConfiguration {
@Bean
public StainingProperties stainingProperties() {
return new StainingProperties();
public RuleStainingProperties ruleStainingProperties() {
return new RuleStainingProperties();
}
@Configuration
@ConditionalOnPolarisConfigEnabled
@ConditionalOnProperty(value = "spring.cloud.tencent.plugin.scg.staining.rule-staining.enabled", matchIfMissing = true)
public static class RuleStainingPluginConfiguration {
@Bean
public RuleStainingProperties ruleStainingProperties() {
return new RuleStainingProperties();
}
@Bean
public StainingRuleManager stainingRuleManager(RuleStainingProperties stainingProperties, ConfigFileService configFileService) {
return new StainingRuleManager(stainingProperties, configFileService);
}
@Bean
public StainingRuleManager stainingRuleManager(RuleStainingProperties stainingProperties, ConfigFileService configFileService) {
return new StainingRuleManager(stainingProperties, configFileService);
}
@Bean
public TrafficStainingGatewayFilter trafficStainingGatewayFilter(List<TrafficStainer> trafficStainer) {
return new TrafficStainingGatewayFilter(trafficStainer);
}
@Bean
public TrafficStainingGatewayFilter trafficStainingGatewayFilter(List<TrafficStainer> trafficStainer) {
return new TrafficStainingGatewayFilter(trafficStainer);
}
@Bean
public RuleStainingExecutor ruleStainingExecutor() {
return new RuleStainingExecutor();
}
@Bean
public RuleStainingExecutor ruleStainingExecutor() {
return new RuleStainingExecutor();
}
@Bean
public RuleTrafficStainer ruleTrafficStainer(StainingRuleManager stainingRuleManager,
RuleStainingExecutor ruleStainingExecutor) {
return new RuleTrafficStainer(stainingRuleManager, ruleStainingExecutor);
}
@Bean
public RuleTrafficStainer ruleTrafficStainer(StainingRuleManager stainingRuleManager, RuleStainingExecutor ruleStainingExecutor) {
return new RuleTrafficStainer(stainingRuleManager, ruleStainingExecutor);
}
}
}

@ -1,39 +0,0 @@
/*
* 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.plugin.gateway.staining;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* The properties for traffic staining.
* @author lepdou 2022-07-07
*/
@ConfigurationProperties("spring.cloud.tencent.plugin.scg.staining")
public class StainingProperties {
private boolean enabled;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

@ -0,0 +1,72 @@
/*
* 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.plugin.gateway;
import com.tencent.cloud.plugin.gateway.staining.TrafficStainingGatewayFilter;
import com.tencent.cloud.plugin.gateway.staining.rule.RuleStainingExecutor;
import com.tencent.cloud.plugin.gateway.staining.rule.RuleStainingProperties;
import com.tencent.cloud.plugin.gateway.staining.rule.RuleTrafficStainer;
import com.tencent.cloud.plugin.gateway.staining.rule.StainingRuleManager;
import com.tencent.polaris.client.api.SDKContext;
import com.tencent.polaris.configuration.api.core.ConfigFileService;
import com.tencent.polaris.configuration.factory.ConfigFileServiceFactory;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.junit4.SpringRunner;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.DEFINED_PORT;
/**
* Test for {@link SCGPluginsAutoConfiguration}.
* @author derek.yi 2022-11-03
*/
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = DEFINED_PORT, classes = SCGPluginsAutoConfigurationTest.TestApplication.class,
properties = {"server.port=8081", "spring.config.location = classpath:application-test.yml",
"spring.cloud.tencent.plugin.scg.staining.rule-staining.enabled = true"})
public class SCGPluginsAutoConfigurationTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void testAutoConfiguration() {
Assert.assertEquals(1, applicationContext.getBeansOfType(RuleStainingProperties.class).size());
Assert.assertEquals(1, applicationContext.getBeansOfType(StainingRuleManager.class).size());
Assert.assertEquals(1, applicationContext.getBeansOfType(TrafficStainingGatewayFilter.class).size());
Assert.assertEquals(1, applicationContext.getBeansOfType(RuleStainingExecutor.class).size());
Assert.assertEquals(1, applicationContext.getBeansOfType(RuleTrafficStainer.class).size());
}
@SpringBootApplication
public static class TestApplication {
@Bean
public ConfigFileService configFileService(SDKContext sdkContext) {
return ConfigFileServiceFactory.createConfigFileService(sdkContext);
}
}
}

@ -1,89 +0,0 @@
/*
* 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.plugin.gateway.staining;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import reactor.core.publisher.Mono;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* Test for {@link TrafficStainingGatewayFilter}.
* @author lepdou 2022-07-12
*/
@RunWith(MockitoJUnitRunner.class)
public class TrafficStainerGatewayFilterTest {
@Mock
private GatewayFilterChain chain;
@Mock
private ServerWebExchange exchange;
@Test
public void testNoneTrafficStainingImplement() {
TrafficStainingGatewayFilter filter = new TrafficStainingGatewayFilter(null);
when(chain.filter(exchange)).thenReturn(Mono.empty());
filter.filter(exchange, chain);
verify(chain).filter(exchange);
}
@Test
public void testMultiStaining() {
TrafficStainer trafficStainer1 = Mockito.mock(TrafficStainer.class);
TrafficStainer trafficStainer2 = Mockito.mock(TrafficStainer.class);
when(trafficStainer1.getOrder()).thenReturn(1);
when(trafficStainer2.getOrder()).thenReturn(2);
Map<String, String> labels1 = new HashMap<>();
labels1.put("k1", "v1");
labels1.put("k2", "v2");
when(trafficStainer1.apply(exchange)).thenReturn(labels1);
Map<String, String> labels2 = new HashMap<>();
labels2.put("k1", "v11");
labels2.put("k3", "v3");
when(trafficStainer2.apply(exchange)).thenReturn(labels2);
TrafficStainingGatewayFilter filter = new TrafficStainingGatewayFilter(Arrays.asList(trafficStainer1, trafficStainer2));
Map<String, String> result = filter.getStainedLabels(exchange);
Assert.assertFalse(CollectionUtils.isEmpty(result));
Assert.assertEquals("v1", result.get("k1"));
Assert.assertEquals("v2", result.get("k2"));
Assert.assertEquals("v3", result.get("k3"));
}
}

@ -0,0 +1,176 @@
/*
* 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.plugin.gateway.staining;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
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.plugin.gateway.staining.rule.RuleStainingExecutor;
import com.tencent.cloud.plugin.gateway.staining.rule.RuleStainingProperties;
import com.tencent.cloud.plugin.gateway.staining.rule.RuleTrafficStainer;
import com.tencent.cloud.plugin.gateway.staining.rule.StainingRuleManager;
import com.tencent.polaris.configuration.api.core.ConfigFile;
import com.tencent.polaris.configuration.api.core.ConfigFileService;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import reactor.core.publisher.Mono;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
* Test for {@link TrafficStainingGatewayFilter}.
* @author lepdou 2022-07-12
*/
@RunWith(MockitoJUnitRunner.class)
public class TrafficStainingGatewayFilterTest {
@Mock
private GatewayFilterChain chain;
@Mock
private ServerWebExchange exchange;
@Mock
private ConfigFileService configFileService;
private final String testNamespace = "testNamespace";
private final String testGroup = "testGroup";
private final String testFileName = "rule.json";
@BeforeClass
public static void before() {
Mockito.mockStatic(ApplicationContextAwareUtils.class);
when(ApplicationContextAwareUtils
.getProperties(any())).thenReturn("fooBar");
}
@Test
public void testNoneTrafficStainingImplement() {
TrafficStainingGatewayFilter filter = new TrafficStainingGatewayFilter(null);
when(chain.filter(exchange)).thenReturn(Mono.empty());
filter.filter(exchange, chain);
verify(chain).filter(exchange);
}
@Test
public void testMultiStaining() {
TrafficStainer trafficStainer1 = Mockito.mock(TrafficStainer.class);
TrafficStainer trafficStainer2 = Mockito.mock(TrafficStainer.class);
when(trafficStainer1.getOrder()).thenReturn(1);
when(trafficStainer2.getOrder()).thenReturn(2);
Map<String, String> labels1 = new HashMap<>();
labels1.put("k1", "v1");
labels1.put("k2", "v2");
when(trafficStainer1.apply(exchange)).thenReturn(labels1);
Map<String, String> labels2 = new HashMap<>();
labels2.put("k1", "v11");
labels2.put("k3", "v3");
when(trafficStainer2.apply(exchange)).thenReturn(labels2);
TrafficStainingGatewayFilter filter = new TrafficStainingGatewayFilter(Arrays.asList(trafficStainer1, trafficStainer2));
Map<String, String> result = filter.getStainedLabels(exchange);
Assert.assertFalse(CollectionUtils.isEmpty(result));
Assert.assertEquals("v1", result.get("k1"));
Assert.assertEquals("v2", result.get("k2"));
Assert.assertEquals("v3", result.get("k3"));
}
@Test
public void testNoTrafficStainers() {
MetadataContext metadataContext = new MetadataContext();
MetadataContextHolder.set(metadataContext);
TrafficStainingGatewayFilter filter = new TrafficStainingGatewayFilter(null);
filter.filter(exchange, chain);
Map<String, String> map = metadataContext.getTransitiveMetadata();
Assert.assertTrue(CollectionUtils.isEmpty(map));
}
@Test
public void testWithTrafficStainers() {
MetadataContext metadataContext = new MetadataContext();
MetadataContextHolder.set(metadataContext);
RuleStainingProperties ruleStainingProperties = new RuleStainingProperties();
ruleStainingProperties.setNamespace(testNamespace);
ruleStainingProperties.setGroup(testGroup);
ruleStainingProperties.setFileName(testFileName);
ConfigFile configFile = Mockito.mock(ConfigFile.class);
when(configFile.getContent()).thenReturn("{\n"
+ " \"rules\":[\n"
+ " {\n"
+ " \"conditions\":[\n"
+ " {\n"
+ " \"key\":\"${http.query.uid}\",\n"
+ " \"values\":[\"1000\"],\n"
+ " \"operation\":\"EQUALS\"\n"
+ " }\n"
+ " ],\n"
+ " \"labels\":[\n"
+ " {\n"
+ " \"key\":\"env\",\n"
+ " \"value\":\"blue\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}");
when(configFileService.getConfigFile(testNamespace, testGroup, testFileName)).thenReturn(configFile);
StainingRuleManager stainingRuleManager = new StainingRuleManager(ruleStainingProperties, configFileService);
RuleStainingExecutor ruleStainingExecutor = new RuleStainingExecutor();
RuleTrafficStainer ruleTrafficStainer = new RuleTrafficStainer(stainingRuleManager, ruleStainingExecutor);
TrafficStainingGatewayFilter filter = new TrafficStainingGatewayFilter(Collections.singletonList(ruleTrafficStainer));
MockServerHttpRequest request = MockServerHttpRequest.get("/users")
.queryParam("uid", "1000").build();
MockServerWebExchange exchange = new MockServerWebExchange.Builder(request).build();
filter.filter(exchange, chain);
Map<String, String> map = metadataContext.getTransitiveMetadata();
Assert.assertNotNull(map);
Assert.assertEquals(1, map.size());
Assert.assertEquals("blue", map.get("env"));
}
}

@ -32,6 +32,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.util.CollectionUtils;
/**
* Test for {@link RuleStainingExecutor}.
@ -178,4 +179,11 @@ public class RuleStainingExecutorTest {
Assert.assertEquals("value1", stainedLabels.get("label1"));
Assert.assertEquals("value2", stainedLabels.get("label2"));
}
@Test
public void testNoStainingRule() {
RuleStainingExecutor executor = new RuleStainingExecutor();
Assert.assertTrue(CollectionUtils.isEmpty(executor.execute(null, null)));
Assert.assertTrue(CollectionUtils.isEmpty(executor.execute(null, new StainingRule())));
}
}

@ -0,0 +1,112 @@
/*
* 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.plugin.gateway.staining.rule;
import java.util.Map;
import com.tencent.polaris.configuration.api.core.ConfigFile;
import com.tencent.polaris.configuration.api.core.ConfigFileService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.util.CollectionUtils;
import static org.mockito.Mockito.when;
/**
* Test for {@link RuleTrafficStainer}.
* @author derek.yi 2022-11-03
*/
@RunWith(MockitoJUnitRunner.class)
public class RuleTrafficStainerTest {
@Mock
private ConfigFileService configFileService;
private final String testNamespace = "testNamespace";
private final String testGroup = "testGroup";
private final String testFileName = "rule.json";
@Test
public void testNoStainingRule() {
RuleStainingProperties ruleStainingProperties = new RuleStainingProperties();
ruleStainingProperties.setNamespace(testNamespace);
ruleStainingProperties.setGroup(testGroup);
ruleStainingProperties.setFileName(testFileName);
ConfigFile configFile = Mockito.mock(ConfigFile.class);
when(configFile.getContent()).thenReturn("");
when(configFileService.getConfigFile(testNamespace, testGroup, testFileName)).thenReturn(configFile);
StainingRuleManager stainingRuleManager = new StainingRuleManager(ruleStainingProperties, configFileService);
RuleStainingExecutor ruleStainingExecutor = new RuleStainingExecutor();
RuleTrafficStainer ruleTrafficStainer = new RuleTrafficStainer(stainingRuleManager, ruleStainingExecutor);
Map<String, String> map = ruleTrafficStainer.apply(null);
Assert.assertTrue(CollectionUtils.isEmpty(map));
}
@Test
public void testWithStainingRule() {
RuleStainingProperties ruleStainingProperties = new RuleStainingProperties();
ruleStainingProperties.setNamespace(testNamespace);
ruleStainingProperties.setGroup(testGroup);
ruleStainingProperties.setFileName(testFileName);
ConfigFile configFile = Mockito.mock(ConfigFile.class);
when(configFile.getContent()).thenReturn("{\n"
+ " \"rules\":[\n"
+ " {\n"
+ " \"conditions\":[\n"
+ " {\n"
+ " \"key\":\"${http.query.uid}\",\n"
+ " \"values\":[\"1000\"],\n"
+ " \"operation\":\"EQUALS\"\n"
+ " }\n"
+ " ],\n"
+ " \"labels\":[\n"
+ " {\n"
+ " \"key\":\"env\",\n"
+ " \"value\":\"blue\"\n"
+ " }\n"
+ " ]\n"
+ " }\n"
+ " ]\n"
+ "}");
when(configFileService.getConfigFile(testNamespace, testGroup, testFileName)).thenReturn(configFile);
StainingRuleManager stainingRuleManager = new StainingRuleManager(ruleStainingProperties, configFileService);
RuleStainingExecutor ruleStainingExecutor = new RuleStainingExecutor();
RuleTrafficStainer ruleTrafficStainer = new RuleTrafficStainer(stainingRuleManager, ruleStainingExecutor);
MockServerHttpRequest request = MockServerHttpRequest.get("/users")
.queryParam("uid", "1000").build();
MockServerWebExchange exchange = new MockServerWebExchange.Builder(request).build();
Map<String, String> map = ruleTrafficStainer.apply(exchange);
Assert.assertNotNull(map);
Assert.assertEquals(1, map.size());
Assert.assertEquals("blue", map.get("env"));
}
}

@ -37,11 +37,12 @@ import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class StainingRuleManagerTest {
@Mock
private ConfigFileService configFileService;
private final String testNamespace = "testNamespace";
private final String testGroup = "testGroup";
private final String testFileName = "rule.json";
@Mock
private ConfigFileService configFileService;
@Test
public void testNormalRule() {

@ -0,0 +1,9 @@
spring:
application:
name: test
cloud:
polaris:
address: grpc://127.0.0.1:8091
namespace: default
config:
connect-remote-server: false
Loading…
Cancel
Save