This is an automated email from the ASF dual-hosted git repository.

xiaoyu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new 16f4fdc  [ISSUE #2910] Add integrated test for Resilience4j plugin 
(#2943)
16f4fdc is described below

commit 16f4fdc6c5ac558661a52bded091e002350e4bd1
Author: Han Gao <[email protected]>
AuthorDate: Sun Feb 27 10:43:12 2022 +0800

    [ISSUE #2910] Add integrated test for Resilience4j plugin (#2943)
    
    * add integrated test for resilience4j plugin
    
    * add circuit tests
    
    * upate some configurations
    
    * add resilience4j plugin dependency
---
 .../http/controller/HttpTestController.java        |  68 ++++++--
 .../shenyu-integrated-test-http/pom.xml            |   8 +
 .../http/combination/Resilience4JPluginTest.java   | 178 +++++++++++++++++++++
 3 files changed, 240 insertions(+), 14 deletions(-)

diff --git 
a/shenyu-examples/shenyu-examples-http/src/main/java/org/apache/shenyu/examples/http/controller/HttpTestController.java
 
b/shenyu-examples/shenyu-examples-http/src/main/java/org/apache/shenyu/examples/http/controller/HttpTestController.java
index 9f7384e..ad660e6 100644
--- 
a/shenyu-examples/shenyu-examples-http/src/main/java/org/apache/shenyu/examples/http/controller/HttpTestController.java
+++ 
b/shenyu-examples/shenyu-examples-http/src/main/java/org/apache/shenyu/examples/http/controller/HttpTestController.java
@@ -29,17 +29,18 @@ import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.http.codec.multipart.FilePart;
-import org.springframework.web.bind.annotation.CookieValue;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestPart;
-import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.CookieValue;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.bind.annotation.ResponseStatus;
 import org.springframework.web.server.ServerWebExchange;
 import reactor.core.publisher.Mono;
 
@@ -61,7 +62,7 @@ import java.util.Map;
 @ShenyuSpringMvcClient(path = "/test/**")
 public class HttpTestController {
 
-    private static final Logger logger = 
LoggerFactory.getLogger(HttpTestController.class);
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(HttpTestController.class);
 
     /**
      * Post user dto.
@@ -89,6 +90,7 @@ public class HttpTestController {
      * Find by user id string.
      *
      * @param userId the user id
+     * @param name name
      * @return the string
      */
     @GetMapping("/findByUserIdName")
@@ -265,7 +267,7 @@ public class HttpTestController {
      * @param cookie           cookie
      * @param requestHeader    header
      * @param requestParameter parameter
-     * @return
+     * @return result
      */
     @PostMapping(path = "/modifyRequest")
     public Map<String, Object> modifyRequest(@RequestBody final UserDTO 
userDTO,
@@ -285,7 +287,7 @@ public class HttpTestController {
      *
      * @param body file content
      * @return file
-     * @throws IOException
+     * @throws IOException io exception
      */
     @GetMapping(path = "/download")
     public ResponseEntity<byte[]> downloadFile(@RequestParam(value = "body", 
defaultValue = "") final String body) throws IOException {
@@ -304,23 +306,61 @@ public class HttpTestController {
      *
      * @param filePart upload file
      * @return OK
-     * @throws IOException
+     * @throws IOException io exception
      */
     @PostMapping(path = "/upload", consumes = 
MediaType.MULTIPART_FORM_DATA_VALUE)
-    public String downloadFile(@RequestPart("file") FilePart filePart) throws 
IOException {
-        logger.info("file name: {}", filePart.filename());
+    public String downloadFile(@RequestPart("file") final FilePart filePart) 
throws IOException {
+        LOGGER.info("file name: {}", filePart.filename());
         Path tempFile = 
Files.createTempFile(String.valueOf(System.currentTimeMillis()), 
filePart.filename());
         filePart.transferTo(tempFile.toFile());
         try (BufferedReader bufferedReader = new BufferedReader(new 
FileReader(tempFile.toFile()))) {
             String line = bufferedReader.readLine();
             while (line != null) {
-                logger.info(line);
+                LOGGER.info(line);
                 line = bufferedReader.readLine();
             }
         }
         return "OK";
     }
 
+    /**
+     * Return bad request code.
+     *
+     * @return response. result bean
+     */
+    @GetMapping("/request/badrequest")
+    @ResponseStatus(HttpStatus.BAD_REQUEST)
+    public ResultBean badRequest() {
+        ResultBean response = new ResultBean();
+        response.setCode(400);
+        return response;
+    }
+
+    /**
+     * Return bad request code.
+     *
+     * @return response. result bean
+     */
+    @GetMapping("/request/accepted")
+    @ResponseStatus(HttpStatus.ACCEPTED)
+    public ResultBean accepted() {
+        ResultBean response = new ResultBean();
+        response.setCode(202);
+        return response;
+    }
+
+    /**
+     * Return bad request code.
+     *
+     * @return response. result bean
+     */
+    @GetMapping("/success")
+    public ResultBean success() {
+        ResultBean response = new ResultBean();
+        response.setCode(200);
+        return response;
+    }
+
     private UserDTO buildUser(final String id, final String name) {
         UserDTO userDTO = new UserDTO();
         userDTO.setUserId(id);
diff --git a/shenyu-integrated-test/shenyu-integrated-test-http/pom.xml 
b/shenyu-integrated-test/shenyu-integrated-test-http/pom.xml
index 80de60a..330e931 100644
--- a/shenyu-integrated-test/shenyu-integrated-test-http/pom.xml
+++ b/shenyu-integrated-test/shenyu-integrated-test-http/pom.xml
@@ -122,6 +122,14 @@
         </dependency>
         <!-- apache shenyu request plugin end-->
 
+        <!-- apache shenyu resilience4j plugin start-->
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            
<artifactId>shenyu-spring-boot-starter-plugin-resilience4j</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <!-- apache shenyu resilience4j plugin end-->
+
         <dependency>
             <groupId>org.apache.shenyu</groupId>
             <artifactId>shenyu-integrated-test-common</artifactId>
diff --git 
a/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/Resilience4JPluginTest.java
 
b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/Resilience4JPluginTest.java
new file mode 100644
index 0000000..7e905d9
--- /dev/null
+++ 
b/shenyu-integrated-test/shenyu-integrated-test-http/src/test/java/org/apache/shenyu/integrated/test/http/combination/Resilience4JPluginTest.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ *     http://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 org.apache.shenyu.integrated.test.http.combination;
+
+import com.google.common.collect.Lists;
+import org.apache.shenyu.common.dto.ConditionData;
+import org.apache.shenyu.common.dto.convert.rule.Resilience4JHandle;
+import org.apache.shenyu.common.enums.OperatorEnum;
+import org.apache.shenyu.common.enums.ParamTypeEnum;
+import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.common.utils.JsonUtils;
+import org.apache.shenyu.integratedtest.common.AbstractPluginDataInit;
+import org.apache.shenyu.integratedtest.common.helper.HttpHelper;
+import org.apache.shenyu.integratedtest.common.result.ResultBean;
+import org.apache.shenyu.web.controller.LocalPluginController;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+public final class Resilience4JPluginTest extends AbstractPluginDataInit {
+
+    private static final String TEST_RESILIENCE4J_SUCCESS_OUT_SCOPE_PATH = 
"/http/test/success";
+
+    private static final String TEST_RESILIENCE4J_SUCCESS_PATH = 
"/http/test/request/accepted";
+
+    private static final String TEST_RESILIENCE4J_BAD_REQUEST_PATH = 
"/http/test/request/badrequest";
+
+    @BeforeEach
+    public void setup() throws IOException {
+        String pluginResult = initPlugin(PluginEnum.RESILIENCE4J.getName(), 
null);
+        assertThat(pluginResult, is("success"));
+    }
+
+    @Test
+    public void testRateLimiterPass() throws InterruptedException, 
ExecutionException, IOException {
+        String selectorAndRulesResult =
+                initSelectorAndRules(PluginEnum.RESILIENCE4J.getName(), "",
+                        buildSelectorConditionList(), 
buildRuleLocalDataList(0, 3, null));
+        assertThat(selectorAndRulesResult, is("success"));
+
+        Set<Integer> resultSet = new HashSet<>();
+        Future<ResultBean> resp1 = this.getService().submit(() -> 
HttpHelper.INSTANCE.getFromGateway(TEST_RESILIENCE4J_SUCCESS_PATH, 
ResultBean.class));
+        Future<ResultBean> resp2 = this.getService().submit(() -> 
HttpHelper.INSTANCE.getFromGateway(TEST_RESILIENCE4J_SUCCESS_PATH, 
ResultBean.class));
+        Future<ResultBean> resp3 = this.getService().submit(() -> 
HttpHelper.INSTANCE.getFromGateway(TEST_RESILIENCE4J_SUCCESS_PATH, 
ResultBean.class));
+        resultSet.add(resp1.get().getCode());
+        resultSet.add(resp2.get().getCode());
+        resultSet.add(resp3.get().getCode());
+        assertTrue(resultSet.contains(202));
+    }
+
+    @Test
+    public void testRateLimiter() throws InterruptedException, 
ExecutionException, IOException {
+        String selectorAndRulesResult =
+                initSelectorAndRules(PluginEnum.RESILIENCE4J.getName(), "",
+                        buildSelectorConditionList(), 
buildRuleLocalDataList(0, 1, null));
+        assertThat(selectorAndRulesResult, is("success"));
+
+        Set<Integer> resultSet = new HashSet<>();
+        Future<ResultBean> resp1 = this.getService().submit(() -> 
HttpHelper.INSTANCE.getFromGateway(TEST_RESILIENCE4J_SUCCESS_PATH, 
ResultBean.class));
+        Future<ResultBean> resp2 = this.getService().submit(() -> 
HttpHelper.INSTANCE.getFromGateway(TEST_RESILIENCE4J_SUCCESS_PATH, 
ResultBean.class));
+        Future<ResultBean> resp3 = this.getService().submit(() -> 
HttpHelper.INSTANCE.getFromGateway(TEST_RESILIENCE4J_SUCCESS_PATH, 
ResultBean.class));
+        resultSet.add(resp1.get().getCode());
+        resultSet.add(resp2.get().getCode());
+        resultSet.add(resp3.get().getCode());
+        assertTrue(resultSet.contains(202));
+        assertTrue(resultSet.contains(429));
+    }
+
+    @Test
+    public void testCircuitBreaker() throws IOException {
+        String selectorAndRulesResult =
+                initSelectorAndRules(PluginEnum.RESILIENCE4J.getName(), "",
+                        buildSelectorConditionList(), 
buildRuleLocalDataList(1, 5000, null));
+        assertThat(selectorAndRulesResult, is("success"));
+
+        List<Integer> rets = new ArrayList<>();
+        for (int i = 0; i < 2; i++) {
+            ResultBean resp = 
HttpHelper.INSTANCE.getFromGateway(TEST_RESILIENCE4J_SUCCESS_PATH, 
ResultBean.class);
+            rets.add(resp.getCode());
+        }
+        for (int i = 0; i < 5; i++) {
+            ResultBean resp = 
HttpHelper.INSTANCE.getFromGateway(TEST_RESILIENCE4J_BAD_REQUEST_PATH, 
ResultBean.class);
+            rets.add(resp.getCode());
+        }
+        assertTrue(rets.contains(202));
+        assertTrue(rets.contains(400));
+        assertTrue(rets.contains(-103));
+    }
+
+    @Test
+    public void testCircuitBreakerFallbackUri() throws IOException {
+        String selectorAndRulesResult =
+                initSelectorAndRules(PluginEnum.RESILIENCE4J.getName(), "",
+                        buildSelectorConditionList(), 
buildRuleLocalDataList(1, 5000, TEST_RESILIENCE4J_SUCCESS_OUT_SCOPE_PATH));
+        assertThat(selectorAndRulesResult, is("success"));
+
+        List<Integer> rets = new ArrayList<>();
+        for (int i = 0; i < 2; i++) {
+            ResultBean resp = 
HttpHelper.INSTANCE.getFromGateway(TEST_RESILIENCE4J_SUCCESS_PATH, 
ResultBean.class);
+            rets.add(resp.getCode());
+        }
+        for (int i = 0; i < 5; i++) {
+            ResultBean resp = 
HttpHelper.INSTANCE.getFromGateway(TEST_RESILIENCE4J_BAD_REQUEST_PATH, 
ResultBean.class);
+            rets.add(resp.getCode());
+        }
+        assertTrue(rets.contains(202));
+        assertTrue(rets.contains(400));
+        assertTrue(rets.contains(200));
+    }
+
+    @AfterEach
+    public void clean() throws IOException {
+        cleanPluginData(PluginEnum.RESILIENCE4J.getName());
+    }
+
+    private static List<ConditionData> buildSelectorConditionList() {
+        ConditionData conditionData = new ConditionData();
+        conditionData.setParamType(ParamTypeEnum.URI.getName());
+        conditionData.setOperator(OperatorEnum.MATCH.getAlias());
+        conditionData.setParamValue("/http/test/**");
+        return Collections.singletonList(conditionData);
+    }
+
+    private static List<LocalPluginController.RuleLocalData> 
buildRuleLocalDataList(final int circuitEnable, final int limitForPeriod, final 
String fallbackUri) {
+        final LocalPluginController.RuleLocalData ruleLocalData = new 
LocalPluginController.RuleLocalData();
+        Resilience4JHandle resilience4JHandle = new Resilience4JHandle();
+        // set parameters for rate limiter
+        resilience4JHandle.setTimeoutDuration(5000);
+        resilience4JHandle.setLimitRefreshPeriod(500000);
+        resilience4JHandle.setLimitForPeriod(limitForPeriod);
+
+        // set parameters for circuit breaker
+        resilience4JHandle.setCircuitEnable(circuitEnable);
+        resilience4JHandle.setFallbackUri(fallbackUri);
+        resilience4JHandle.setMinimumNumberOfCalls(1);
+        resilience4JHandle.setFailureRateThreshold(50);
+
+        ruleLocalData.setRuleHandler(JsonUtils.toJson(resilience4JHandle));
+
+        ConditionData conditionData = new ConditionData();
+        conditionData.setParamType(ParamTypeEnum.URI.getName());
+        conditionData.setOperator(OperatorEnum.MATCH.getAlias());
+        conditionData.setParamValue("/http/test/request/**");
+
+        
ruleLocalData.setConditionDataList(Collections.singletonList(conditionData));
+
+        return Lists.newArrayList(ruleLocalData);
+    }
+
+}

Reply via email to