From 8a07d69b5264e5274726241123968f87c0a1b81f Mon Sep 17 00:00:00 2001 From: shedfreewu Date: Thu, 5 Dec 2024 11:12:57 +0800 Subject: [PATCH] ut --- .../reporter/CircuitBreakerPluginTest.java | 171 ++++++++++++++++++ .../ExceptionCircuitBreakerReporterTest.java | 68 +++++++ .../SuccessCircuitBreakerReporterTest.java | 70 ++++++- .../lossless/LosslessRegistryAspectTest.java | 144 +++++++++++++++ ...acosDiscoveryAdapterAutoConfiguration.java | 1 - .../config/LosslessAutoConfiguration.java | 27 ++- .../loadbalancer/PolarisLoadBalancerTest.java | 4 +- .../RpcEnhancementAutoConfiguration.java | 1 - .../plugin/DefaultEnhancedPluginRunner.java | 3 +- .../feign/EnhancedFeignClientTest.java | 77 +++++++- .../plugin/EnhancedPluginContextTest.java | 3 +- 11 files changed, 543 insertions(+), 26 deletions(-) create mode 100644 spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/CircuitBreakerPluginTest.java diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/CircuitBreakerPluginTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/CircuitBreakerPluginTest.java new file mode 100644 index 000000000..94e499c9f --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/CircuitBreakerPluginTest.java @@ -0,0 +1,171 @@ +/* + * 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.circuitbreaker.reporter; + +import java.net.URI; +import java.util.HashMap; + +import com.tencent.cloud.common.metadata.MetadataContext; +import com.tencent.cloud.common.util.ApplicationContextAwareUtils; +import com.tencent.cloud.polaris.circuitbreaker.PolarisCircuitBreaker; +import com.tencent.cloud.polaris.circuitbreaker.common.PolarisCircuitBreakerConfigBuilder; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; +import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; +import com.tencent.polaris.api.core.ConsumerAPI; +import com.tencent.polaris.api.pojo.CircuitBreakerStatus; +import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; +import com.tencent.polaris.circuitbreak.api.InvokeHandler; +import com.tencent.polaris.circuitbreak.api.pojo.InvokeContext; +import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import org.springframework.cloud.client.DefaultServiceInstance; +import org.springframework.cloud.client.circuitbreaker.CircuitBreakerFactory; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; + +import static com.tencent.polaris.test.common.Consts.NAMESPACE_TEST; +import static com.tencent.polaris.test.common.Consts.SERVICE_PROVIDER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * CircuitBreakerPluginTest. + * + * @author Shedfree Wu + */ +@ExtendWith(MockitoExtension.class) +public class CircuitBreakerPluginTest { + + private static MockedStatic mockedApplicationContextAwareUtils; + @InjectMocks + private CircuitBreakerPlugin circuitBreakerPlugin; + @Mock + private CircuitBreakAPI circuitBreakAPI; + @Mock + private CircuitBreakerFactory circuitBreakerFactory; + + @Mock + private ConsumerAPI consumerAPI; + + + @BeforeAll + static void beforeAll() { + mockedApplicationContextAwareUtils = Mockito.mockStatic(ApplicationContextAwareUtils.class); + mockedApplicationContextAwareUtils.when(() -> ApplicationContextAwareUtils.getProperties(anyString())) + .thenReturn("unit-test"); + } + + @AfterAll + static void afterAll() { + mockedApplicationContextAwareUtils.close(); + } + + @BeforeEach + void setUp() { + MetadataContext.LOCAL_NAMESPACE = NAMESPACE_TEST; + MetadataContext.LOCAL_SERVICE = SERVICE_PROVIDER; + } + + @Test + public void testGetName() { + assertThat(circuitBreakerPlugin.getName()).isEqualTo(CircuitBreakerPlugin.class.getName()); + } + + @Test + public void testType() { + assertThat(circuitBreakerPlugin.getType()).isEqualTo(EnhancedPluginType.Client.PRE); + } + + @Test + public void testRun() throws Throwable { + when(circuitBreakAPI.makeInvokeHandler(any())).thenReturn(new MockInvokeHandler()); + + PolarisCircuitBreakerConfigBuilder polarisCircuitBreakerConfigBuilder = new PolarisCircuitBreakerConfigBuilder(); + PolarisCircuitBreaker polarisCircuitBreaker = new PolarisCircuitBreaker(polarisCircuitBreakerConfigBuilder.build(), consumerAPI, circuitBreakAPI); + when(circuitBreakerFactory.create(anyString())).thenReturn(polarisCircuitBreaker); + + + EnhancedPluginContext pluginContext = new EnhancedPluginContext(); + EnhancedRequestContext request = EnhancedRequestContext.builder() + .httpMethod(HttpMethod.GET) + .url(URI.create("http://0.0.0.0/")) + .httpHeaders(new HttpHeaders()) + .build(); + EnhancedResponseContext response = EnhancedResponseContext.builder() + .httpStatus(200) + .build(); + DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); + serviceInstance.setServiceId(SERVICE_PROVIDER); + + pluginContext.setRequest(request); + pluginContext.setResponse(response); + pluginContext.setTargetServiceInstance(serviceInstance, null); + pluginContext.setThrowable(new RuntimeException()); + + assertThatThrownBy(() -> circuitBreakerPlugin.run(pluginContext)).isExactlyInstanceOf(CallAbortedException.class); + circuitBreakerPlugin.getOrder(); + circuitBreakerPlugin.getName(); + circuitBreakerPlugin.getType(); + } + + @Test + public void testHandlerThrowable() { + // mock request + EnhancedRequestContext request = mock(EnhancedRequestContext.class); + // mock response + EnhancedResponseContext response = mock(EnhancedResponseContext.class); + + EnhancedPluginContext context = new EnhancedPluginContext(); + context.setRequest(request); + context.setResponse(response); + circuitBreakerPlugin.handlerThrowable(context, new RuntimeException("Mock exception.")); + } + + static class MockInvokeHandler implements InvokeHandler { + @Override + public void acquirePermission() { + throw new CallAbortedException("mock", new CircuitBreakerStatus.FallbackInfo(0, new HashMap<>(), "")); + } + + @Override + public void onSuccess(InvokeContext.ResponseContext responseContext) { + + } + + @Override + public void onError(InvokeContext.ResponseContext responseContext) { + + } + } +} diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporterTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporterTest.java index 4f2382c9f..487978f8f 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporterTest.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/ExceptionCircuitBreakerReporterTest.java @@ -19,8 +19,11 @@ package com.tencent.cloud.polaris.circuitbreaker.reporter; import java.net.URI; +import com.tencent.cloud.common.constant.ContextConstant; 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.polaris.circuitbreaker.PolarisCircuitBreaker; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; @@ -28,6 +31,7 @@ import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.client.api.SDKContext; +import com.tencent.polaris.metadata.core.MetadataType; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -69,6 +73,8 @@ public class ExceptionCircuitBreakerReporterTest { private ExceptionCircuitBreakerReporter exceptionCircuitBreakerReporter; @Mock private CircuitBreakAPI circuitBreakAPI; + @Mock + private PolarisCircuitBreaker polarisCircuitBreaker; @BeforeAll static void beforeAll() { @@ -142,4 +148,66 @@ public class ExceptionCircuitBreakerReporterTest { context.setResponse(response); exceptionCircuitBreakerReporter.handlerThrowable(context, new RuntimeException("Mock exception.")); } + + @Test + public void testExistCircuitBreaker() throws Throwable { + + doReturn(true).when(reporterProperties).isEnabled(); + + EnhancedPluginContext pluginContext = new EnhancedPluginContext(); + EnhancedRequestContext request = EnhancedRequestContext.builder() + .httpMethod(HttpMethod.GET) + .url(URI.create("http://0.0.0.0/")) + .build(); + EnhancedResponseContext response = EnhancedResponseContext.builder() + .httpStatus(300) + .build(); + DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); + serviceInstance.setServiceId(SERVICE_PROVIDER); + + pluginContext.setRequest(request); + pluginContext.setResponse(response); + pluginContext.setTargetServiceInstance(serviceInstance, null); + pluginContext.setThrowable(new RuntimeException()); + + MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true). + putMetadataObjectValue(ContextConstant.CircuitBreaker.POLARIS_CIRCUIT_BREAKER, polarisCircuitBreaker); + MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true). + putMetadataObjectValue(ContextConstant.CircuitBreaker.CIRCUIT_BREAKER_START_TIME, System.currentTimeMillis()); + + exceptionCircuitBreakerReporter.run(pluginContext); + + response = EnhancedResponseContext.builder() + .httpStatus(500) + .build(); + pluginContext.setResponse(response); + exceptionCircuitBreakerReporter.run(pluginContext); + } + + @Test + public void testExistCircuitBreaker2() throws Throwable { + + doReturn(true).when(reporterProperties).isEnabled(); + + EnhancedPluginContext pluginContext = new EnhancedPluginContext(); + EnhancedRequestContext request = EnhancedRequestContext.builder() + .httpMethod(HttpMethod.GET) + .url(URI.create("http://0.0.0.0/")) + .build(); + EnhancedResponseContext response = EnhancedResponseContext.builder() + .httpStatus(300) + .build(); + DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); + serviceInstance.setServiceId(SERVICE_PROVIDER); + + pluginContext.setRequest(request); + pluginContext.setResponse(response); + pluginContext.setTargetServiceInstance(serviceInstance, null); + pluginContext.setThrowable(new RuntimeException()); + // not exist circuit CIRCUIT_BREAKER_START_TIME + MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true). + putMetadataObjectValue(ContextConstant.CircuitBreaker.POLARIS_CIRCUIT_BREAKER, polarisCircuitBreaker); + + exceptionCircuitBreakerReporter.run(pluginContext); + } } diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporterTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporterTest.java index 7a79d8058..4545e7cf1 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporterTest.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/reporter/SuccessCircuitBreakerReporterTest.java @@ -20,11 +20,13 @@ package com.tencent.cloud.polaris.circuitbreaker.reporter; import java.lang.reflect.Field; import java.net.URI; +import com.tencent.cloud.common.constant.ContextConstant; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.metadata.MetadataContextHolder; import com.tencent.cloud.common.metadata.StaticMetadataManager; import com.tencent.cloud.common.metadata.config.MetadataLocalProperties; import com.tencent.cloud.common.util.ApplicationContextAwareUtils; +import com.tencent.cloud.polaris.circuitbreaker.PolarisCircuitBreaker; import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementReporterProperties; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; @@ -32,6 +34,7 @@ import com.tencent.cloud.rpc.enhancement.plugin.EnhancedRequestContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedResponseContext; import com.tencent.polaris.circuitbreak.api.CircuitBreakAPI; import com.tencent.polaris.client.api.SDKContext; +import com.tencent.polaris.metadata.core.MetadataType; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -66,16 +69,15 @@ public class SuccessCircuitBreakerReporterTest { private static MockedStatic mockedApplicationContextAwareUtils; @Mock - private SDKContext sdkContext; - @Mock private RpcEnhancementReporterProperties reporterProperties; + @Mock + private SDKContext sdkContext; @InjectMocks private SuccessCircuitBreakerReporter successCircuitBreakerReporter; @Mock private CircuitBreakAPI circuitBreakAPI; - @Mock - private MetadataLocalProperties metadataLocalProperties; + private PolarisCircuitBreaker polarisCircuitBreaker; @BeforeAll static void beforeAll() throws Exception { @@ -160,4 +162,64 @@ public class SuccessCircuitBreakerReporterTest { context.setResponse(response); successCircuitBreakerReporter.handlerThrowable(context, new RuntimeException("Mock exception.")); } + + @Test + public void testExistCircuitBreaker() throws Throwable { + + doReturn(true).when(reporterProperties).isEnabled(); + + EnhancedPluginContext pluginContext = new EnhancedPluginContext(); + EnhancedRequestContext request = EnhancedRequestContext.builder() + .httpMethod(HttpMethod.GET) + .url(URI.create("http://0.0.0.0/")) + .build(); + EnhancedResponseContext response = EnhancedResponseContext.builder() + .httpStatus(300) + .build(); + DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); + serviceInstance.setServiceId(SERVICE_PROVIDER); + + pluginContext.setRequest(request); + pluginContext.setResponse(response); + pluginContext.setTargetServiceInstance(serviceInstance, null); + + MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true). + putMetadataObjectValue(ContextConstant.CircuitBreaker.POLARIS_CIRCUIT_BREAKER, polarisCircuitBreaker); + MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true). + putMetadataObjectValue(ContextConstant.CircuitBreaker.CIRCUIT_BREAKER_START_TIME, System.currentTimeMillis()); + + successCircuitBreakerReporter.run(pluginContext); + + response = EnhancedResponseContext.builder() + .httpStatus(500) + .build(); + pluginContext.setResponse(response); + successCircuitBreakerReporter.run(pluginContext); + } + + @Test + public void testExistCircuitBreaker2() throws Throwable { + + doReturn(true).when(reporterProperties).isEnabled(); + + EnhancedPluginContext pluginContext = new EnhancedPluginContext(); + EnhancedRequestContext request = EnhancedRequestContext.builder() + .httpMethod(HttpMethod.GET) + .url(URI.create("http://0.0.0.0/")) + .build(); + EnhancedResponseContext response = EnhancedResponseContext.builder() + .httpStatus(300) + .build(); + DefaultServiceInstance serviceInstance = new DefaultServiceInstance(); + serviceInstance.setServiceId(SERVICE_PROVIDER); + + pluginContext.setRequest(request); + pluginContext.setResponse(response); + pluginContext.setTargetServiceInstance(serviceInstance, null); + // not exist circuit CIRCUIT_BREAKER_START_TIME + MetadataContextHolder.get().getMetadataContainer(MetadataType.APPLICATION, true). + putMetadataObjectValue(ContextConstant.CircuitBreaker.POLARIS_CIRCUIT_BREAKER, polarisCircuitBreaker); + + successCircuitBreakerReporter.run(pluginContext); + } } diff --git a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspectTest.java b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspectTest.java index f8e1c2e98..f9a6eb77a 100644 --- a/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspectTest.java +++ b/spring-cloud-starter-tencent-polaris-discovery/src/test/java/com/tencent/cloud/plugin/lossless/LosslessRegistryAspectTest.java @@ -17,7 +17,10 @@ package com.tencent.cloud.plugin.lossless; +import java.lang.reflect.Field; +import java.net.URI; import java.util.Collections; +import java.util.Map; import com.tencent.cloud.common.util.OkHttpUtil; import com.tencent.cloud.plugin.lossless.config.LosslessAutoConfiguration; @@ -28,6 +31,7 @@ import com.tencent.cloud.polaris.discovery.PolarisDiscoveryAutoConfiguration; import com.tencent.cloud.polaris.discovery.PolarisDiscoveryClientConfiguration; import com.tencent.cloud.polaris.registry.PolarisRegistration; import com.tencent.cloud.polaris.registry.PolarisServiceRegistry; +import com.tencent.cloud.rpc.enhancement.transformer.RegistrationTransformer; import com.tencent.polaris.api.pojo.ServiceKey; import com.tencent.polaris.test.mock.discovery.NamingServer; import org.junit.jupiter.api.AfterAll; @@ -40,6 +44,9 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.runner.WebApplicationContextRunner; import org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration; import org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationUtils; +import org.springframework.cloud.client.serviceregistry.Registration; +import org.springframework.cloud.client.serviceregistry.ServiceRegistry; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import static org.assertj.core.api.Assertions.assertThat; @@ -106,6 +113,31 @@ public class LosslessRegistryAspectTest { .withPropertyValues("spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST) .withPropertyValues("spring.cloud.polaris.discovery.token=xxxxxx"); + private final WebApplicationContextRunner contextRunner3 = new WebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of( + MockDiscoveryConfiguration.class, + LosslessAutoConfiguration.class, + LosslessPropertiesBootstrapConfiguration.class, + PolarisContextAutoConfiguration.class, + PolarisPropertiesConfiguration.class, + PolarisDiscoveryClientConfiguration.class, + PolarisDiscoveryAutoConfiguration.class)) + .withPropertyValues("spring.cloud.nacos.discovery.enabled=false") + .withPropertyValues("spring.cloud.polaris.lossless.enabled=true") + .withPropertyValues("spring.cloud.polaris.lossless.healthCheckInterval=1000") + .withPropertyValues("spring.cloud.polaris.lossless.healthCheckPath=/test") + .withPropertyValues("spring.cloud.polaris.admin.port=28082") + .withPropertyValues("spring.application.name=" + SERVICE_PROVIDER) + .withPropertyValues("server.port=" + APPLICATION_PORT) + .withPropertyValues("spring.cloud.polaris.localIpAddress=" + HOST) + .withPropertyValues("spring.cloud.polaris.localPort=" + APPLICATION_PORT) + .withPropertyValues("spring.cloud.polaris.address=grpc://127.0.0.1:10081") + .withPropertyValues("spring.cloud.polaris.discovery.namespace=" + NAMESPACE_TEST) + .withPropertyValues("spring.cloud.polaris.discovery.token=xxxxxx") + .withPropertyValues("spring.autoconfigure.exclude=" + + "org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration"); + + @BeforeAll static void beforeAll() throws Exception { namingServer = NamingServer.startNamingServer(10081); @@ -185,9 +217,121 @@ public class LosslessRegistryAspectTest { }); } + @Test + public void testRegister3() { + this.contextRunner3.run(context -> { + + AbstractAutoServiceRegistration autoServiceRegistration = context.getBean(AbstractAutoServiceRegistration.class); + + assertThatCode(() -> { + AutoServiceRegistrationUtils.register(autoServiceRegistration); + }).doesNotThrowAnyException(); + + Thread.sleep(2000); + + assertThatCode(() -> { + AutoServiceRegistrationUtils.deRegister(autoServiceRegistration); + }).doesNotThrowAnyException(); + + LosslessRegistryAspect losslessRegistryAspect = context.getBean(LosslessRegistryAspect.class); + Field field = LosslessRegistryAspect.class.getDeclaredField("registrationTransformer"); + field.setAccessible(true); + RegistrationTransformer registrationTransformer = (RegistrationTransformer) field.get(losslessRegistryAspect); + assertThat(registrationTransformer.getClass().getName().contains("PolarisRegistrationTransformer")); + + field = LosslessRegistryAspect.class.getDeclaredField("registration"); + field.setAccessible(true); + Registration registration = (Registration) field.get(losslessRegistryAspect); + assertThat(registration.getClass().getName().contains("PolarisRegistration")); + + field = LosslessRegistryAspect.class.getDeclaredField("serviceRegistry"); + field.setAccessible(true); + ServiceRegistry serviceRegistry = (ServiceRegistry) field.get(losslessRegistryAspect); + assertThat(serviceRegistry.getClass().getName().contains("PolarisServiceRegistry")); + }); + } + @Configuration @EnableAutoConfiguration static class PolarisPropertiesConfiguration { } + + @Configuration + static class MockDiscoveryConfiguration { + @Bean + public ServiceRegistry mockServiceRegistry() { + return new ServiceRegistry() { + @Override + public void register(Registration registration) { + + } + + @Override + public void deregister(Registration registration) { + + } + + @Override + public void close() { + + } + + @Override + public void setStatus(Registration registration, String status) { + + } + + @Override + public Object getStatus(Registration registration) { + return null; + } + }; + } + + @Bean + public Registration mockRegistration() { + return new Registration() { + @Override + public String getServiceId() { + return null; + } + + @Override + public String getHost() { + return null; + } + + @Override + public int getPort() { + return 0; + } + + @Override + public boolean isSecure() { + return false; + } + + @Override + public URI getUri() { + return null; + } + + @Override + public Map getMetadata() { + return null; + } + }; + } + + @Bean + public RegistrationTransformer mockRegistrationTransformer() { + return new RegistrationTransformer() { + @Override + public String getRegistry() { + return null; + } + }; + } + } } diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java index aa5a45514..b704ba783 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-starter-tencent-discovery-adapter-plugin/src/main/java/com/tencent/cloud/plugin/discovery/adapter/config/NacosDiscoveryAdapterAutoConfiguration.java @@ -45,7 +45,6 @@ public class NacosDiscoveryAdapterAutoConfiguration { } @Bean - @ConditionalOnMissingBean @ConditionalOnClass(name = "com.alibaba.cloud.nacos.registry.NacosRegistration") public RegistrationTransformer registrationTransformer() { return new NacosRegistrationTransformer(); diff --git a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessAutoConfiguration.java b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessAutoConfiguration.java index d34a88711..37e4272d1 100644 --- a/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessAutoConfiguration.java +++ b/spring-cloud-tencent-plugin-starters/spring-cloud-tencent-lossless-plugin/src/main/java/com/tencent/cloud/plugin/lossless/config/LosslessAutoConfiguration.java @@ -47,33 +47,32 @@ public class LosslessAutoConfiguration { public LosslessRegistryAspect losslessRegistryAspect( List serviceRegistryList, List registrationList, List registrationTransformerList, PolarisContextProperties properties, LosslessProperties losslessProperties, PolarisSDKContextManager polarisSDKContextManager) { - // if contains multiple service registry, we need to find the polaris service registry - ServiceRegistry targetServiceRegistry = null; - Registration targetRegistration = null; - RegistrationTransformer targetRegistrationTransformer = null; - if (serviceRegistryList.size() == 1 && registrationList.size() == 1 && registrationTransformerList.size() == 1) { - targetServiceRegistry = serviceRegistryList.get(0); - targetRegistration = registrationList.get(0); - targetRegistrationTransformer = registrationTransformerList.get(0); - } - else { + + ServiceRegistry targetServiceRegistry = serviceRegistryList.size() > 0 ? serviceRegistryList.get(0) : null; + Registration targetRegistration = registrationList.size() > 0 ? registrationList.get(0) : null; + RegistrationTransformer targetRegistrationTransformer = registrationTransformerList.size() > 0 ? registrationTransformerList.get(0) : null; + // if contains multiple service registry, find the polaris service registr + if (serviceRegistryList.size() > 1) { for (ServiceRegistry serviceRegistry : serviceRegistryList) { - if (serviceRegistry.getClass().getSimpleName().contains("Polaris")) { + if (serviceRegistry.getClass().getName().contains("PolarisServiceRegistry")) { targetServiceRegistry = serviceRegistry; } } + } + if (registrationList.size() > 1) { for (Registration registration : registrationList) { - if (registration.getClass().getSimpleName().contains("Polaris")) { + if (registration.getClass().getName().contains("PolarisRegistration")) { targetRegistration = registration; } } + } + if (registrationTransformerList.size() > 1) { for (RegistrationTransformer registrationTransformer : registrationTransformerList) { - if (registrationTransformer.getClass().getSimpleName().contains("Polaris")) { + if (registrationTransformer.getClass().getName().contains("PolarisRegistrationTransformer")) { targetRegistrationTransformer = registrationTransformer; } } } - return new LosslessRegistryAspect(targetServiceRegistry, targetRegistration, properties, losslessProperties, polarisSDKContextManager, targetRegistrationTransformer); } diff --git a/spring-cloud-tencent-polaris-loadbalancer/src/test/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerTest.java b/spring-cloud-tencent-polaris-loadbalancer/src/test/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerTest.java index c490e2bfe..8cf2443e8 100644 --- a/spring-cloud-tencent-polaris-loadbalancer/src/test/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerTest.java +++ b/spring-cloud-tencent-polaris-loadbalancer/src/test/java/com/tencent/cloud/polaris/loadbalancer/PolarisLoadBalancerTest.java @@ -23,6 +23,7 @@ import java.util.stream.Stream; import com.netflix.client.config.DefaultClientConfigImpl; import com.netflix.client.config.IClientConfig; +import com.netflix.loadbalancer.ConfigurationBasedServerList; import com.netflix.loadbalancer.DummyPing; import com.netflix.loadbalancer.Server; import com.netflix.loadbalancer.ServerList; @@ -103,7 +104,8 @@ public class PolarisLoadBalancerTest { .thenReturn("TestServer"); PolarisLoadBalancerProperties properties = new PolarisLoadBalancerProperties(); - ServerList emptyServerList = new StaticServerList<>(); + ConfigurationBasedServerList emptyServerList = new ConfigurationBasedServerList(); + emptyServerList.initWithNiwsConfig(config); PolarisLoadBalancer balancer = new PolarisLoadBalancer(config, rule, new DummyPing(), emptyServerList, consumerAPI, properties, null); diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java index 50a415422..ddcc715c8 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/config/RpcEnhancementAutoConfiguration.java @@ -94,7 +94,6 @@ public class RpcEnhancementAutoConfiguration { } @Bean - @ConditionalOnMissingBean @ConditionalOnClass(name = "com.tencent.cloud.polaris.registry.PolarisRegistration") public RegistrationTransformer registrationTransformer() { return new PolarisRegistrationTransformer(); diff --git a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/DefaultEnhancedPluginRunner.java b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/DefaultEnhancedPluginRunner.java index d6f84805b..f45e29689 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/DefaultEnhancedPluginRunner.java +++ b/spring-cloud-tencent-rpc-enhancement/src/main/java/com/tencent/cloud/rpc/enhancement/plugin/DefaultEnhancedPluginRunner.java @@ -104,9 +104,8 @@ public class DefaultEnhancedPluginRunner implements EnhancedPluginRunner { if (CollectionUtils.isEmpty(registration)) { return null; } - for (Registration reg : registration) { - if (reg.getClass().getCanonicalName().equals("com.tencent.cloud.polaris.registry.PolarisRegistration")) { + if ("com.tencent.cloud.polaris.registry.PolarisRegistration".equals(reg.getClass().getName())) { return reg; } } diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClientTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClientTest.java index debbd1d94..396a26c4e 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClientTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/feign/EnhancedFeignClientTest.java @@ -20,6 +20,7 @@ package com.tencent.cloud.rpc.enhancement.feign; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import com.tencent.cloud.polaris.context.PolarisSDKContextManager; @@ -27,6 +28,8 @@ import com.tencent.cloud.rpc.enhancement.plugin.DefaultEnhancedPluginRunner; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPlugin; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginContext; import com.tencent.cloud.rpc.enhancement.plugin.EnhancedPluginType; +import com.tencent.polaris.api.pojo.CircuitBreakerStatus; +import com.tencent.polaris.circuitbreak.client.exception.CallAbortedException; import feign.Client; import feign.Request; import feign.RequestTemplate; @@ -81,7 +84,7 @@ public class EnhancedFeignClientTest { List enhancedPlugins = getMockEnhancedFeignPlugins(); try { new EnhancedFeignClient(mock(Client.class), - new DefaultEnhancedPluginRunner(enhancedPlugins, null, polarisSDKContextManager.getSDKContext())); + new DefaultEnhancedPluginRunner(enhancedPlugins, new ArrayList<>(), polarisSDKContextManager.getSDKContext())); } catch (Throwable e) { fail("Exception encountered.", e); @@ -111,7 +114,7 @@ public class EnhancedFeignClientTest { requestTemplate.feignTarget(target); EnhancedFeignClient polarisFeignClient = new EnhancedFeignClient(delegate, - new DefaultEnhancedPluginRunner(getMockEnhancedFeignPlugins(), null, polarisSDKContextManager.getSDKContext())); + new DefaultEnhancedPluginRunner(getMockEnhancedFeignPlugins(), new ArrayList<>(), polarisSDKContextManager.getSDKContext())); // 200 Response response = polarisFeignClient.execute(Request.create(Request.HttpMethod.GET, "http://localhost:8080/test", @@ -135,6 +138,52 @@ public class EnhancedFeignClientTest { } } + @Test + public void testExecuteCallAbortedException() throws IOException { + // mock Client.class + Client delegate = mock(Client.class); + doAnswer(invocation -> { + Request request = invocation.getArgument(0); + if (request.httpMethod().equals(Request.HttpMethod.GET)) { + return Response.builder().request(request).status(200).build(); + } + else if (request.httpMethod().equals(Request.HttpMethod.POST)) { + return Response.builder().request(request).status(502).build(); + } + throw new IOException("Mock exception."); + }).when(delegate).execute(any(Request.class), nullable(Request.Options.class)); + + // mock target + Target target = Target.EmptyTarget.create(Object.class); + + // mock RequestTemplate.class + RequestTemplate requestTemplate = new RequestTemplate(); + requestTemplate.feignTarget(target); + + EnhancedFeignClient polarisFeignClient = new EnhancedFeignClient(delegate, + new DefaultEnhancedPluginRunner(getMockCallAbortedExceptionEnhancedFeignPlugins(null), new ArrayList<>(), polarisSDKContextManager.getSDKContext())); + + // Exception + try { + polarisFeignClient.execute(Request.create(Request.HttpMethod.GET, "http://localhost:8080/test", + Collections.emptyMap(), null, requestTemplate), null); + fail("CallAbortedException should be thrown."); + } + catch (CallAbortedException t) { + assertThat(t).isInstanceOf(CallAbortedException.class); + assertThat(t.getMessage()).contains("Mock CallAbortedException"); + } + + polarisFeignClient = new EnhancedFeignClient(delegate, + new DefaultEnhancedPluginRunner(getMockCallAbortedExceptionEnhancedFeignPlugins( + new CircuitBreakerStatus.FallbackInfo(200, new HashMap<>(), "mock ok")), new ArrayList<>(), polarisSDKContextManager.getSDKContext())); + + // fallback 200 + Response response = polarisFeignClient.execute(Request.create(Request.HttpMethod.GET, "http://localhost:8080/test", + Collections.emptyMap(), null, requestTemplate), null); + assertThat(response.status()).isEqualTo(200); + } + private List getMockEnhancedFeignPlugins() { List enhancedPlugins = new ArrayList<>(); @@ -230,6 +279,30 @@ public class EnhancedFeignClientTest { } + private List getMockCallAbortedExceptionEnhancedFeignPlugins(CircuitBreakerStatus.FallbackInfo fallbackInfo) { + List enhancedPlugins = new ArrayList<>(); + + enhancedPlugins.add(new EnhancedPlugin() { + + @Override + public int getOrder() { + return 0; + } + + @Override + public EnhancedPluginType getType() { + return EnhancedPluginType.Client.PRE; + } + + @Override + public void run(EnhancedPluginContext context) throws Throwable { + throw new CallAbortedException("Mock CallAbortedException", fallbackInfo); + } + }); + + return enhancedPlugins; + } + @SpringBootApplication protected static class TestApplication { diff --git a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContextTest.java b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContextTest.java index 4c2aa5ed5..28319b884 100644 --- a/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContextTest.java +++ b/spring-cloud-tencent-rpc-enhancement/src/test/java/com/tencent/cloud/rpc/enhancement/plugin/EnhancedPluginContextTest.java @@ -19,6 +19,7 @@ package com.tencent.cloud.rpc.enhancement.plugin; import java.net.URI; import java.net.URISyntaxException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -150,7 +151,7 @@ public class EnhancedPluginContextTest { doReturn(configuration).when(sdkContext).getConfig(); - enhancedPluginRunner = new DefaultEnhancedPluginRunner(Collections.singletonList(enhancedPlugin2), null, sdkContext); + enhancedPluginRunner = new DefaultEnhancedPluginRunner(Collections.singletonList(enhancedPlugin2), new ArrayList<>(), sdkContext); enhancedPluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext); }