diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/pom.xml b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/pom.xml index 04fe730f86..51ae0cd70b 100644 --- a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/pom.xml +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/pom.xml @@ -55,7 +55,11 @@ true - + + com.alibaba.csp + sentinel-datasource-extension + test + junit junit diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/ConfigConstantsTest.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/ConfigConstantsTest.java new file mode 100644 index 0000000000..df98a7da30 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/ConfigConstantsTest.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.sentinel.gateway; + +import org.junit.Assert; +import org.junit.Test; + +public class ConfigConstantsTest { + @Test + public void testConfigConstants() { + Assert.assertEquals("11", ConfigConstants.APP_TYPE_SCG_GATEWAY); + Assert.assertEquals("spring.cloud.sentinel.scg", ConfigConstants.GATEWAY_PREFIX); + Assert.assertEquals("response", ConfigConstants.FALLBACK_MSG_RESPONSE); + Assert.assertEquals("redirect", ConfigConstants.FALLBACK_REDIRECT); + } +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/FallbackPropertiesTest.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/FallbackPropertiesTest.java new file mode 100644 index 0000000000..f7e41382a6 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/FallbackPropertiesTest.java @@ -0,0 +1,62 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.sentinel.gateway; + +import org.junit.Assert; +import org.junit.Test; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +public class FallbackPropertiesTest { + + /** + * Tests the correct setting and retrieval of fallback properties. + * This test case verifies that the FallbackProperties class correctly sets and retrieves + * various properties for fallback responses, including the response mode, redirect URL, + * response body content, HTTP status code, and content type. + */ + @Test + public void testFallbackProperties() { + FallbackProperties properties = new FallbackProperties() + .setMode("response") + .setRedirect("http://example.com") + .setResponseBody("{'message': 'Fallback response'}") + .setResponseStatus(HttpStatus.TOO_EARLY.value()) + .setContentType("application/json"); + + Assert.assertEquals("response", properties.getMode()); + Assert.assertEquals("http://example.com", properties.getRedirect()); + Assert.assertEquals("{'message': 'Fallback response'}", properties.getResponseBody()); + Assert.assertEquals(HttpStatus.TOO_EARLY.value(), properties.getResponseStatus().intValue()); + Assert.assertEquals("application/json", properties.getContentType()); + } + + /** + * This test method checks the default values of a FallbackProperties object. + * It verifies that certain properties are not set (null) and others have default values. + */ + @Test + public void testDefaultValues() { + FallbackProperties properties = new FallbackProperties(); + Assert.assertNull(properties.getMode()); + Assert.assertNull(properties.getRedirect()); + Assert.assertNull(properties.getResponseBody()); + Assert.assertEquals(HttpStatus.TOO_MANY_REQUESTS.value(), properties.getResponseStatus().intValue()); + Assert.assertEquals(MediaType.APPLICATION_JSON.toString(), properties.getContentType()); + } +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/GatewayEnvironmentPostProcessorTest.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/GatewayEnvironmentPostProcessorTest.java new file mode 100644 index 0000000000..8aaeb03f5f --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/GatewayEnvironmentPostProcessorTest.java @@ -0,0 +1,78 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.sentinel.gateway; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +import org.springframework.boot.SpringApplication; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MapPropertySource; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class GatewayEnvironmentPostProcessorTest { + /** + * Tests the custom property source processing logic. + * This test case verifies whether the custom property source is correctly added during the environment post-processing. + * Specifically, it checks if the configuration property "spring.cloud.sentinel.filter.enabled" is properly added. + */ + @Test + public void testPostProcessEnvironment() { + ConfigurableEnvironment environment = mock(ConfigurableEnvironment.class); + MutablePropertySources propertySources = new MutablePropertySources(); + when(environment.getPropertySources()).thenReturn(propertySources); + + GatewayEnvironmentPostProcessor postProcessor = new GatewayEnvironmentPostProcessor(); + postProcessor.postProcessEnvironment(environment, mock(SpringApplication.class)); + + PropertySource propertySource = propertySources.get("defaultProperties"); + Assert.assertNotNull(propertySource); + Assert.assertNotNull(propertySource.getProperty("spring.cloud.sentinel.filter.enabled")); + } + + /** + * Tests the logic of processing an environment that already contains a property source. + * This test case simulates an environment with an existing property source and checks if the post-processor can interact correctly with these property sources. + */ + @Test + public void testPostProcessEnvironmentWithExistingPropertySource() { + ConfigurableEnvironment environment = mock(ConfigurableEnvironment.class); + MutablePropertySources propertySources = new MutablePropertySources(); + when(environment.getPropertySources()).thenReturn(propertySources); + + Map existingProperties = new HashMap<>(); + existingProperties.put("existing.property", "value"); + MapPropertySource existingPropertySource = new MapPropertySource("defaultProperties", existingProperties); + propertySources.addFirst(existingPropertySource); + + GatewayEnvironmentPostProcessor postProcessor = new GatewayEnvironmentPostProcessor(); + postProcessor.postProcessEnvironment(environment, mock(SpringApplication.class)); + + PropertySource propertySource = propertySources.get("defaultProperties"); + Assert.assertNotNull(propertySource); + Assert.assertEquals("value", propertySource.getProperty("existing.property")); + Assert.assertEquals("false", propertySource.getProperty("spring.cloud.sentinel.filter.enabled")); + } + +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/SentinelGatewayAutoConfigurationTest.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/SentinelGatewayAutoConfigurationTest.java new file mode 100644 index 0000000000..e2b8cb9f9c --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/SentinelGatewayAutoConfigurationTest.java @@ -0,0 +1,114 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.sentinel.gateway; + +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collection; + +import com.alibaba.cloud.commons.io.FileUtils; +import com.alibaba.cloud.sentinel.datasource.converter.JsonConverter; +import com.alibaba.cloud.sentinel.datasource.converter.XmlConverter; +import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition; +import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.util.ResourceUtils; +import org.springframework.util.StringUtils; + +public class SentinelGatewayAutoConfigurationTest { + + private SentinelGatewayAutoConfiguration.SentinelConverterConfiguration.SentinelJsonConfiguration json; + private SentinelGatewayAutoConfiguration.SentinelConverterConfiguration.SentinelXmlConfiguration xml; + + /** + * Setup method to initialize test configurations. + */ + @Before + public void setup() { + json = new SentinelGatewayAutoConfiguration.SentinelConverterConfiguration.SentinelJsonConfiguration(); + xml = new SentinelGatewayAutoConfiguration.SentinelConverterConfiguration.SentinelXmlConfiguration(); + } + + /** + * Tests the JSON gateway flow rule converter. + * Reads JSON content from a file, converts it to GatewayFlowRule collection, and validates the result. + */ + @Test + public void testJsonGatewayFlowConverter() { + JsonConverter jsonGatewayFlowConverter = json.jsonGatewayFlowConverter(); + Collection gatewayFlowRules = jsonGatewayFlowConverter.convert(readFileContent("classpath: gatewayflowrule.json")); + Assert.assertEquals(1, gatewayFlowRules.size()); + Assert.assertEquals("test", new ArrayList<>(gatewayFlowRules).get(0).getResource()); + } + + /** + * Tests the JSON API definition converter. + * Reads JSON content from a file, converts it to ApiDefinition collection, and validates the result. + */ + @Test + public void testJsonApiConverter() { + JsonConverter jsonApiConverter = json.jsonApiConverter(); + Collection apiDefinitions = jsonApiConverter.convert(readFileContent("classpath: apidefinition.json")); + Assert.assertEquals(1, apiDefinitions.size()); + Assert.assertEquals("test", new ArrayList<>(apiDefinitions).get(0).getApiName()); + } + + /** + * Tests the XML gateway flow rule converter. + * Reads XML content from a file, converts it to GatewayFlowRule collection, and validates the result. + */ + @Test + public void testXmlGatewayFlowConverter() { + XmlConverter xmlGatewayFlowConverter = xml.xmlGatewayFlowConverter(); + Collection gatewayFlowRules = xmlGatewayFlowConverter.convert(readFileContent("classpath: gatewayflowrule.xml")); + Assert.assertEquals(1, gatewayFlowRules.size()); + Assert.assertEquals("test", new ArrayList<>(gatewayFlowRules).get(0).getResource()); + } + + /** + * Tests the XML API definition converter. + * Reads XML content from a file, converts it to ApiDefinition collection, and validates the result. + */ + @Test + public void testSentinelXmlConfiguration() { + XmlConverter xmlApiConverter = xml.xmlApiConverter(); + Collection apiDefinitions = xmlApiConverter.convert(readFileContent("classpath: apidefinition.xml")); + Assert.assertEquals(1, apiDefinitions.size()); + Assert.assertEquals("test", new ArrayList<>(apiDefinitions).get(0).getApiName()); + } + + /** + * Reads the content of a file. + * + * @param file the classpath location of the file + * @return the content of the file as a string + */ + private String readFileContent(String file) { + try { + return FileUtils.readFileToString( + ResourceUtils.getFile(StringUtils.trimAllWhitespace(file)), + Charset.defaultCharset()); + } + catch (IOException e) { + return ""; + } + } +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelGatewayPropertiesTest.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelGatewayPropertiesTest.java new file mode 100644 index 0000000000..c1dfe9132c --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelGatewayPropertiesTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.sentinel.gateway.scg; + +import com.alibaba.cloud.sentinel.gateway.FallbackProperties; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import org.springframework.core.Ordered; + +public class SentinelGatewayPropertiesTest { + + private SentinelGatewayProperties properties; + + @Before + public void setUp() { + properties = new SentinelGatewayProperties(); + } + + @Test + public void testDefaultOrder() { + Assert.assertEquals(Ordered.HIGHEST_PRECEDENCE, properties.getOrder().intValue()); + } + + @Test + public void testSetOrder() { + int newOrder = 100; + properties.setOrder(newOrder); + Assert.assertEquals(newOrder, properties.getOrder().intValue()); + } + + @Test + public void testFallbackPropertiesInitialization() { + Assert.assertNull(properties.getFallback()); + } + + @Test + public void testSetFallbackProperties() { + FallbackProperties newFallback = new FallbackProperties(); + properties.setFallback(newFallback); + Assert.assertSame(newFallback, properties.getFallback()); + } +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelSCGAutoConfigurationTest.java b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelSCGAutoConfigurationTest.java new file mode 100644 index 0000000000..fe09065682 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/java/com/alibaba/cloud/sentinel/gateway/scg/SentinelSCGAutoConfigurationTest.java @@ -0,0 +1,119 @@ +/* + * Copyright 2013-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.alibaba.cloud.sentinel.gateway.scg; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import com.alibaba.cloud.sentinel.gateway.ConfigConstants; +import com.alibaba.cloud.sentinel.gateway.FallbackProperties; +import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import reactor.core.publisher.Mono; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.codec.ServerCodecConfigurer; +import org.springframework.web.reactive.function.server.ServerResponse; +import org.springframework.web.reactive.result.view.ViewResolver; +import org.springframework.web.server.ServerWebExchange; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class SentinelSCGAutoConfigurationTest { + + @Mock + private ObjectProvider> viewResolversProvider; + + @Mock + private ServerCodecConfigurer serverCodecConfigurer; + + @Mock + private SentinelGatewayProperties gatewayProperties; + + private SentinelSCGAutoConfiguration config; + + @Before + public void setup() throws Exception { + MockitoAnnotations.openMocks(this).close(); + config = new SentinelSCGAutoConfiguration(viewResolversProvider, serverCodecConfigurer); + Field optional = SentinelSCGAutoConfiguration.class.getDeclaredField("blockRequestHandlerOptional"); + optional.setAccessible(true); + optional.set(config, Optional.empty()); + Field properties = SentinelSCGAutoConfiguration.class.getDeclaredField("gatewayProperties"); + properties.setAccessible(true); + properties.set(config, this.gatewayProperties); + } + + /** + * Tests the initialization method to ensure that fallback properties are fetched + * and the block exception handler and gateway filter are properly configured. + */ + @Test + public void testInit() { + config.init(); + verify(gatewayProperties).getFallback(); // Check if fallback properties are fetched + Assert.assertNotNull(config.sentinelGatewayBlockExceptionHandler()); + Assert.assertNotNull(config.sentinelGatewayFilter()); + } + + /** + * Tests the initialization method when the fallback mode is set to return a custom response message. + * Verifies that the response status, content type, and body match the expected values. + */ + @Test + public void testInitWithFallbackMsgResponse() { + FallbackProperties fallbackProperties = mock(FallbackProperties.class); + when(gatewayProperties.getFallback()).thenReturn(fallbackProperties); + when(fallbackProperties.getMode()).thenReturn(ConfigConstants.FALLBACK_MSG_RESPONSE); + when(fallbackProperties.getResponseStatus()).thenReturn(200); + when(fallbackProperties.getContentType()).thenReturn(MediaType.APPLICATION_JSON.toString()); + when(fallbackProperties.getResponseBody()).thenReturn("test"); + config.init(); + Mono responseMono = GatewayCallbackManager.getBlockHandler() + .handleRequest(mock(ServerWebExchange.class), null); + Assert.assertEquals(200, Objects.requireNonNull(responseMono.block()).statusCode().value()); + } + + /** + * Tests the initialization method when the fallback mode is set to redirect to another URL. + * Verifies that the response contains the correct redirect location header. + */ + @Test + public void testInitWithFallbackRedirect() { + FallbackProperties fallbackProperties = mock(FallbackProperties.class); + when(gatewayProperties.getFallback()).thenReturn(fallbackProperties); + when(fallbackProperties.getMode()).thenReturn(ConfigConstants.FALLBACK_REDIRECT); + when(fallbackProperties.getRedirect()).thenReturn("/test"); + config.init(); + Mono responseMono = GatewayCallbackManager.getBlockHandler() + .handleRequest(mock(ServerWebExchange.class), null); + HttpHeaders headers = Objects.requireNonNull(responseMono.block()).headers(); + List location = headers.get("Location"); + Assert.assertNotNull(location); + Assert.assertEquals("/test", location.get(0)); + } +} diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/apidefinition.json b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/apidefinition.json new file mode 100644 index 0000000000..9e665591b4 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/apidefinition.json @@ -0,0 +1,5 @@ +[ + { + "apiName": "test" + } +] diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/apidefinition.xml b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/apidefinition.xml new file mode 100644 index 0000000000..8dd85edb0a --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/apidefinition.xml @@ -0,0 +1,6 @@ + + + + test + + \ No newline at end of file diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/gatewayflowrule.json b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/gatewayflowrule.json new file mode 100644 index 0000000000..4a9f2a87b8 --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/gatewayflowrule.json @@ -0,0 +1,12 @@ +[ + { + "resource": "test", + "resourceMode": 0, + "grade": 1, + "count": 1, + "intervalSec": 1, + "controlBehavior": 1, + "burst": 1, + "maxQueueingTimeoutMs": 100 + } +] diff --git a/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/gatewayflowrule.xml b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/gatewayflowrule.xml new file mode 100644 index 0000000000..cb8bce483e --- /dev/null +++ b/spring-cloud-alibaba-starters/spring-cloud-alibaba-sentinel-gateway/src/test/resources/gatewayflowrule.xml @@ -0,0 +1,6 @@ + + + + test + + \ No newline at end of file