diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpoint.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpoint.java index b2ff0eeff..f9ada5121 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpoint.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/main/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpoint.java @@ -27,12 +27,14 @@ import com.google.protobuf.util.JsonFormat; import com.tencent.cloud.common.metadata.MetadataContext; import com.tencent.cloud.common.util.JacksonUtils; import com.tencent.cloud.polaris.context.ServiceRuleManager; +import com.tencent.polaris.api.utils.CollectionUtils; import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.actuate.endpoint.annotation.Endpoint; import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; +import org.springframework.boot.actuate.endpoint.annotation.Selector; /** * Endpoint of polaris circuit breaker, include circuit breaker rules. @@ -51,36 +53,38 @@ public class PolarisCircuitBreakerEndpoint { } @ReadOperation - public Map circuitBreaker() { - CircuitBreakerProto.CircuitBreaker circuitBreaker = serviceRuleManager.getServiceCircuitBreakerRule( + public Map circuitBreaker(@Selector String dstService) { + List rules = serviceRuleManager.getServiceCircuitBreakerRule( MetadataContext.LOCAL_NAMESPACE, - MetadataContext.LOCAL_SERVICE + MetadataContext.LOCAL_SERVICE, + dstService ); Map polarisCircuitBreakerInfo = new HashMap<>(); polarisCircuitBreakerInfo.put("namespace", MetadataContext.LOCAL_NAMESPACE); polarisCircuitBreakerInfo.put("service", MetadataContext.LOCAL_SERVICE); - polarisCircuitBreakerInfo.put("circuitBreakerRules", parseCircuitBreakerRule(circuitBreaker)); - return polarisCircuitBreakerInfo; - } + List circuitBreakerRules = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(rules)) { + for (CircuitBreakerProto.CircuitBreakerRule rule : rules) { + circuitBreakerRules.add(parseCircuitBreakerRule(rule)); - private List parseCircuitBreakerRule(CircuitBreakerProto.CircuitBreaker circuitBreaker) { - List circuitBreakerRuleList = new ArrayList<>(); - - for (CircuitBreakerProto.CircuitBreakerRule circuitBreakerRule : circuitBreaker.getRulesList()) { - String ruleJson; - try { - ruleJson = JsonFormat.printer().print(circuitBreakerRule); - } - catch (InvalidProtocolBufferException e) { - LOG.error("rule to Json failed. check rule {}.", circuitBreakerRule, e); - throw new RuntimeException("Json failed.", e); } - circuitBreakerRuleList.add(JacksonUtils.deserialize2Map(ruleJson)); } + polarisCircuitBreakerInfo.put("circuitBreakerRules", circuitBreakerRules); + return polarisCircuitBreakerInfo; + } - return circuitBreakerRuleList; + private Object parseCircuitBreakerRule(CircuitBreakerProto.CircuitBreakerRule circuitBreakerRule) { + String ruleJson; + try { + ruleJson = JsonFormat.printer().print(circuitBreakerRule); + } + catch (InvalidProtocolBufferException e) { + LOG.error("rule to Json failed. check rule {}.", circuitBreakerRule, e); + throw new RuntimeException("Json failed.", e); + } + return JacksonUtils.deserialize2Map(ruleJson); } } diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointAutoConfigurationTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointAutoConfigurationTest.java new file mode 100644 index 000000000..48e23ecdd --- /dev/null +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointAutoConfigurationTest.java @@ -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.polaris.circuitbreaker.endpoint; + +import com.tencent.cloud.polaris.circuitbreaker.config.PolarisCircuitBreakerAutoConfiguration; +import com.tencent.cloud.polaris.context.config.PolarisContextAutoConfiguration; +import com.tencent.cloud.rpc.enhancement.config.RpcEnhancementAutoConfiguration; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.runner.WebApplicationContextRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Test for {@link PolarisCircuitBreakerEndpointAutoConfiguration}. + * + * @author wenxuan70 + */ +public class PolarisCircuitBreakerEndpointAutoConfigurationTest { + + private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner() + .withConfiguration(AutoConfigurations.of( + PolarisContextAutoConfiguration.class, + RpcEnhancementAutoConfiguration.class, + PolarisCircuitBreakerAutoConfiguration.class, + PolarisCircuitBreakerEndpointAutoConfiguration.class + )) + .withPropertyValues("management.endpoints.web.exposure.include=polaris-circuit-breaker"); + + @Test + public void testEndpointInitialization() { + contextRunner.run(context -> assertThat(context).hasSingleBean(PolarisCircuitBreakerEndpoint.class)); + } +} diff --git a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointTest.java b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointTest.java index 23913957e..b253ac96b 100644 --- a/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointTest.java +++ b/spring-cloud-starter-tencent-polaris-circuitbreaker/src/test/java/com/tencent/cloud/polaris/circuitbreaker/endpoint/PolarisCircuitBreakerEndpointTest.java @@ -56,7 +56,7 @@ public class PolarisCircuitBreakerEndpointTest { @BeforeEach void setUp() { serviceRuleManager = mock(ServiceRuleManager.class); - when(serviceRuleManager.getServiceCircuitBreakerRule(anyString(), anyString())).thenAnswer(invocation -> { + when(serviceRuleManager.getServiceCircuitBreakerRule(anyString(), anyString(), anyString())).thenAnswer(invocation -> { CircuitBreakerProto.CircuitBreakerRule.Builder ruleBuilder = CircuitBreakerProto.CircuitBreakerRule.newBuilder(); ruleBuilder.setName("test_for_circuit_breaker"); ruleBuilder.setEnable(true); @@ -66,7 +66,7 @@ public class PolarisCircuitBreakerEndpointTest { ModelProto.MatchString.newBuilder().setValue(StringValue.newBuilder().setValue("*").build()).build()).build()); rmBuilder.setSource(CircuitBreakerProto.RuleMatcher.SourceService.newBuilder().setNamespace("*").setService("*").build()); ruleBuilder.setRuleMatcher(rmBuilder.build()); - return CircuitBreakerProto.CircuitBreaker.newBuilder().addRules(ruleBuilder.build()).build(); + return CircuitBreakerProto.CircuitBreaker.newBuilder().addRules(ruleBuilder.build()).build().getRulesList(); }); } @@ -74,7 +74,7 @@ public class PolarisCircuitBreakerEndpointTest { public void testPolarisCircuitBreaker() { contextRunner.run(context -> { PolarisCircuitBreakerEndpoint endpoint = new PolarisCircuitBreakerEndpoint(serviceRuleManager); - Map circuitBreakerInfo = endpoint.circuitBreaker(); + Map circuitBreakerInfo = endpoint.circuitBreaker("test"); assertThat(circuitBreakerInfo).isNotNull(); assertThat(circuitBreakerInfo.get("namespace")).isNotNull(); assertThat(circuitBreakerInfo.get("service")).isNotNull(); diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-feign-example/pom.xml b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-feign-example/pom.xml index 6f7382e7b..a45ce9336 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-feign-example/pom.xml +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-feign-example/pom.xml @@ -43,6 +43,11 @@ org.springframework.cloud spring-cloud-starter-bootstrap + + + org.springframework.boot + spring-boot-starter-actuator + diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-feign-example/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-feign-example/src/main/resources/bootstrap.yml index a7966baf6..0afe7375d 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-feign-example/src/main/resources/bootstrap.yml +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-feign-example/src/main/resources/bootstrap.yml @@ -22,3 +22,9 @@ logging: root: info com.tencent.cloud: debug +management: + endpoints: + web: + exposure: + include: + - polaris-circuit-breaker diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-gateway-example/pom.xml b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-gateway-example/pom.xml index 9064f5b88..833f2e51e 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-gateway-example/pom.xml +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-gateway-example/pom.xml @@ -53,6 +53,11 @@ org.springframework.cloud spring-cloud-starter-bootstrap + + + org.springframework.boot + spring-boot-starter-actuator + diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-gateway-example/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-gateway-example/src/main/resources/bootstrap.yml index 3ea326fab..1c946649c 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-gateway-example/src/main/resources/bootstrap.yml +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-gateway-example/src/main/resources/bootstrap.yml @@ -57,3 +57,9 @@ logging: com.tencent.polaris.plugins.registry: off com.tencent.cloud: debug +management: + endpoints: + web: + exposure: + include: + - polaris-circuit-breaker diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/pom.xml b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/pom.xml index f86372777..942c7587f 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/pom.xml +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/pom.xml @@ -38,6 +38,11 @@ org.springframework.cloud spring-cloud-starter-bootstrap + + + org.springframework.boot + spring-boot-starter-actuator + diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/resources/bootstrap.yml index 4687ea9da..9cd52b817 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/resources/bootstrap.yml +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-resttemplate-example/src/main/resources/bootstrap.yml @@ -18,3 +18,9 @@ logging: root: info com.tencent.cloud: debug +management: + endpoints: + web: + exposure: + include: + - polaris-circuit-breaker diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-webclient-example/pom.xml b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-webclient-example/pom.xml index 3305c2c58..5e85be2d8 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-webclient-example/pom.xml +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-webclient-example/pom.xml @@ -38,6 +38,11 @@ org.springframework.cloud spring-cloud-starter-bootstrap + + + org.springframework.boot + spring-boot-starter-actuator + diff --git a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-webclient-example/src/main/resources/bootstrap.yml b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-webclient-example/src/main/resources/bootstrap.yml index a6b162df9..9c6f22fde 100644 --- a/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-webclient-example/src/main/resources/bootstrap.yml +++ b/spring-cloud-tencent-examples/polaris-circuitbreaker-example/polaris-circuitbreaker-webclient-example/src/main/resources/bootstrap.yml @@ -18,3 +18,9 @@ logging: root: info com.tencent.cloud: debug +management: + endpoints: + web: + exposure: + include: + - polaris-circuit-breaker diff --git a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java index 826d4fbe2..abf932191 100644 --- a/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java +++ b/spring-cloud-tencent-polaris-context/src/main/java/com/tencent/cloud/polaris/context/ServiceRuleManager.java @@ -89,18 +89,30 @@ public class ServiceRuleManager { return rules; } - public CircuitBreakerProto.CircuitBreaker getServiceCircuitBreakerRule(String namespace, String service) { - LOG.debug("Get service circuit breaker rules with namespace:{} and service:{}.", namespace, service); + public List getServiceCircuitBreakerRule(String namespace, String sourceService, String dstService) { + LOG.debug("Get service circuit breaker rules with namespace:{} and sourceService:{} and dstService:{}.", namespace, sourceService, dstService); - ServiceRule serviceRule = getServiceRule(namespace, service, ServiceEventKey.EventType.CIRCUIT_BREAKING); - if (serviceRule != null) { - Object rule = serviceRule.getRule(); + List rules = new ArrayList<>(); + + // get source service circuit breaker rules. + ServiceRule sourceServiceRule = getServiceRule(namespace, sourceService, ServiceEventKey.EventType.CIRCUIT_BREAKING); + if (sourceServiceRule != null) { + Object rule = sourceServiceRule.getRule(); if (rule instanceof CircuitBreakerProto.CircuitBreaker) { - return (CircuitBreakerProto.CircuitBreaker) rule; + rules.addAll(((CircuitBreakerProto.CircuitBreaker) rule).getRulesList()); } } - return null; + // get peer service circuit breaker rules. + ServiceRule dstServiceRule = getServiceRule(namespace, dstService, ServiceEventKey.EventType.CIRCUIT_BREAKING); + if (dstServiceRule != null) { + Object rule = dstServiceRule.getRule(); + if (rule instanceof CircuitBreakerProto.CircuitBreaker) { + rules.addAll(((CircuitBreakerProto.CircuitBreaker) rule).getRulesList()); + } + } + + return rules; } private ServiceRule getServiceRule(String namespace, String service, ServiceEventKey.EventType eventType) { diff --git a/spring-cloud-tencent-polaris-context/src/test/java/com/tencent/cloud/polaris/context/ServiceRuleManagerTest.java b/spring-cloud-tencent-polaris-context/src/test/java/com/tencent/cloud/polaris/context/ServiceRuleManagerTest.java new file mode 100644 index 000000000..43c61d3b3 --- /dev/null +++ b/spring-cloud-tencent-polaris-context/src/test/java/com/tencent/cloud/polaris/context/ServiceRuleManagerTest.java @@ -0,0 +1,169 @@ +/* + * 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.context; + +import java.util.List; + +import com.tencent.polaris.api.core.ConsumerAPI; +import com.tencent.polaris.api.pojo.ServiceEventKey; +import com.tencent.polaris.api.pojo.ServiceRule; +import com.tencent.polaris.api.rpc.ServiceRuleResponse; +import com.tencent.polaris.client.api.SDKContext; +import com.tencent.polaris.client.pojo.ServiceRuleByProto; +import com.tencent.polaris.specification.api.v1.fault.tolerance.CircuitBreakerProto; +import com.tencent.polaris.specification.api.v1.traffic.manage.RateLimitProto; +import com.tencent.polaris.specification.api.v1.traffic.manage.RoutingProto; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.when; + +/** + * Test for {@link ServiceRuleManager}. + * + * @author wenxuan70 + */ +@ExtendWith(MockitoExtension.class) +public class ServiceRuleManagerTest { + + @Mock(answer = Answers.RETURNS_DEEP_STUBS) + private SDKContext sdkContext; + + @Mock + private ConsumerAPI consumerAPI; + + @BeforeEach + public void setUp() { + when(sdkContext.getConfig().getGlobal().getAPI().getTimeout()).thenReturn(500L); + } + + @Test + public void testGetServiceCircuitBreakerRule() { + final String testNamespace = "testNamespace"; + final String testSourceService = "testSourceService"; + final String testDstService = "testDstService"; + + CircuitBreakerProto.CircuitBreaker circuitBreaker = CircuitBreakerProto.CircuitBreaker.newBuilder() + .addRules(CircuitBreakerProto.CircuitBreakerRule.newBuilder().build()) + .build(); + ServiceRuleByProto serviceRule = new ServiceRuleByProto(circuitBreaker, + "111", + false, + ServiceEventKey.EventType.CIRCUIT_BREAKING); + ServiceRuleResponse serviceRuleResponse = new ServiceRuleResponse(serviceRule); + + // source + when(consumerAPI.getServiceRule( + argThat(request -> request != null + && testNamespace.equals(request.getNamespace()) + && testSourceService.equals(request.getService()) + && ServiceEventKey.EventType.CIRCUIT_BREAKING.equals(request.getRuleType())) + )).thenReturn(serviceRuleResponse); + + ServiceRuleResponse emptyRuleResponse = new ServiceRuleResponse(null); + + // destination + when(consumerAPI.getServiceRule( + argThat(request -> request != null + && testNamespace.equals(request.getNamespace()) + && testDstService.equals(request.getService()) + && ServiceEventKey.EventType.CIRCUIT_BREAKING.equals(request.getRuleType())) + )).thenReturn(emptyRuleResponse); + + ServiceRuleManager serviceRuleManager = new ServiceRuleManager(sdkContext, consumerAPI); + List serviceCircuitBreakerRule = serviceRuleManager.getServiceCircuitBreakerRule(testNamespace, + testSourceService, + testDstService); + + assertThat(serviceCircuitBreakerRule).hasSize(1); + } + + @Test + public void testGetServiceRouterRule() { + final String testNamespace = "testNamespace"; + final String testSourceService = "testSourceService"; + final String testDstService = "testDstService"; + + RoutingProto.Routing routing = RoutingProto.Routing.newBuilder() + .addOutbounds(RoutingProto.Route.newBuilder().build()) + .build(); + ServiceRule serviceRule = new ServiceRuleByProto(routing, + "111", + false, + ServiceEventKey.EventType.ROUTING); + ServiceRuleResponse serviceRuleResponse = new ServiceRuleResponse(serviceRule); + + // source + when(consumerAPI.getServiceRule( + argThat(request -> request != null + && testNamespace.equals(request.getNamespace()) + && testSourceService.equals(request.getService()) + && ServiceEventKey.EventType.ROUTING.equals(request.getRuleType())) + )).thenReturn(serviceRuleResponse); + + + ServiceRuleResponse emptyRuleResponse = new ServiceRuleResponse(null); + + // destination + when(consumerAPI.getServiceRule( + argThat(request -> request != null + && testNamespace.equals(request.getNamespace()) + && testDstService.equals(request.getService()) + && ServiceEventKey.EventType.ROUTING.equals(request.getRuleType())) + )).thenReturn(emptyRuleResponse); + + ServiceRuleManager serviceRuleManager = new ServiceRuleManager(sdkContext, consumerAPI); + List serviceRouterRule = serviceRuleManager.getServiceRouterRule(testNamespace, + testSourceService, + testDstService); + + assertThat(serviceRouterRule).hasSize(1); + } + + @Test + public void testGetServiceRateLimitRule() { + final String testNamespace = "testNamespace"; + final String testService = "testService"; + + RateLimitProto.RateLimit rateLimit = RateLimitProto.RateLimit.getDefaultInstance(); + ServiceRule serviceRule = new ServiceRuleByProto(rateLimit, + "111", + false, + ServiceEventKey.EventType.ROUTING); + ServiceRuleResponse serviceRuleResponse = new ServiceRuleResponse(serviceRule); + + when(consumerAPI.getServiceRule( + argThat(request -> request != null + && testNamespace.equals(request.getNamespace()) + && testService.equals(request.getService()) + && ServiceEventKey.EventType.RATE_LIMITING.equals(request.getRuleType())) + )).thenReturn(serviceRuleResponse); + + ServiceRuleManager serviceRuleManager = new ServiceRuleManager(sdkContext, consumerAPI); + RateLimitProto.RateLimit rateLimitRule = serviceRuleManager.getServiceRateLimitRule(testNamespace, testService); + + assertThat(rateLimitRule).isNotNull(); + } +}