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

liubao pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git

commit b6b5855910daa64be64accb69b90d5fbe868d348
Author: wujimin <[email protected]>
AuthorDate: Thu Nov 1 15:18:05 2018 +0800

    [SCB-1001] add IT.
---
 .../common/rest/AbstractRestInvocation.java        | 11 +++--
 integration-tests/it-consumer/pom.xml              |  6 +++
 .../org/apache/servicecomb/it/ConsumerMain.java    |  7 ++++
 .../it/testcase/TestDownloadSlowStreamEdge.java    | 48 ++++++++++++++++++++++
 .../it-edge/src/main/resources/microservice.yaml   | 15 +++++++
 .../servicecomb/it/schema/DownloadSchema.java      | 47 +++++++++++++++++++++
 6 files changed, 131 insertions(+), 3 deletions(-)

diff --git 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/AbstractRestInvocation.java
 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/AbstractRestInvocation.java
index 6d95820..932aef4 100644
--- 
a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/AbstractRestInvocation.java
+++ 
b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/AbstractRestInvocation.java
@@ -17,7 +17,6 @@
 
 package org.apache.servicecomb.common.rest;
 
-import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.List;
@@ -268,12 +267,18 @@ public abstract class AbstractRestInvocation {
 
     try {
       responseEx.flushBuffer();
-    } catch (IOException flushException) {
+    } catch (Throwable flushException) {
       LOGGER.error("Failed to flush rest response, operation:{}, request 
uri:{}",
           getMicroserviceQualifiedName(), requestEx.getRequestURI(), 
flushException);
     }
 
-    requestEx.getAsyncContext().complete();
+    try {
+      requestEx.getAsyncContext().complete();
+    } catch (Throwable completeException) {
+      LOGGER.error("Failed to complete async rest response, operation:{}, 
request uri:{}",
+          getMicroserviceQualifiedName(), requestEx.getRequestURI(), 
completeException);
+    }
+
     // if failed to locate path, then will not create invocation
     // TODO: statistics this case
     if (invocation != null) {
diff --git a/integration-tests/it-consumer/pom.xml 
b/integration-tests/it-consumer/pom.xml
index 9821cab..7e743a8 100644
--- a/integration-tests/it-consumer/pom.xml
+++ b/integration-tests/it-consumer/pom.xml
@@ -34,6 +34,12 @@
       <artifactId>it-common</artifactId>
     </dependency>
     <dependency>
+      <groupId>com.squareup.okhttp3</groupId>
+      <artifactId>okhttp</artifactId>
+      <scope>compile</scope>
+    </dependency>
+
+    <dependency>
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-model</artifactId>
       <version>3.3.9</version>
diff --git 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
index 48da9cd..cbc00d7 100644
--- 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
+++ 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/ConsumerMain.java
@@ -29,6 +29,7 @@ import 
org.apache.servicecomb.it.testcase.TestDataTypePrimitive;
 import org.apache.servicecomb.it.testcase.TestDefaultJsonValueJaxrsSchema;
 import org.apache.servicecomb.it.testcase.TestDefaultValue;
 import org.apache.servicecomb.it.testcase.TestDownload;
+import org.apache.servicecomb.it.testcase.TestDownloadSlowStreamEdge;
 import org.apache.servicecomb.it.testcase.TestIgnoreMethod;
 import org.apache.servicecomb.it.testcase.TestIgnoreStaticMethod;
 import org.apache.servicecomb.it.testcase.TestParamCodec;
@@ -141,6 +142,9 @@ public class ConsumerMain {
     // about url len, different deploy have different url len, so only test 
standalone
     ITJUnitUtils.runWithRest(TestRestServerConfig.class);
     ITJUnitUtils.run(TestRestServerConfigEdge.class);
+
+    // currently, only support vertx download
+    ITJUnitUtils.run(TestDownloadSlowStreamEdge.class);
   }
 
   private static void testH2CStandalone() throws Throwable {
@@ -161,6 +165,9 @@ public class ConsumerMain {
 
   private static void testSpringBoot2Standalone() throws Throwable {
     runShareTestCases();
+
+    // currently, only support vertx download
+    ITJUnitUtils.run(TestDownloadSlowStreamEdge.class);
   }
 
   private static void testSpringBoot2Servlet() throws Throwable {
diff --git 
a/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestDownloadSlowStreamEdge.java
 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestDownloadSlowStreamEdge.java
new file mode 100644
index 0000000..8c9cfa5
--- /dev/null
+++ 
b/integration-tests/it-consumer/src/main/java/org/apache/servicecomb/it/testcase/TestDownloadSlowStreamEdge.java
@@ -0,0 +1,48 @@
+/*
+ * 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.servicecomb.it.testcase;
+
+import java.io.IOException;
+
+import org.apache.servicecomb.it.extend.engine.GateRestTemplate;
+import org.junit.Test;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+
+public class TestDownloadSlowStreamEdge {
+  static GateRestTemplate client = 
GateRestTemplate.createEdgeRestTemplate("download");
+
+  @Test
+  public void clearInputStreamAfterDisconnect() throws IOException {
+//    URL url = new URL(client.getUrlPrefix() + "/slowInputStream");
+//    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+//    conn.getInputStream().close();
+//    conn.disconnect();
+
+    OkHttpClient httpClient = new OkHttpClient();
+    Request request = new Request.Builder().url(client.getUrlPrefix() + 
"/slowInputStream")
+        .build();
+    Response response = httpClient.newCall(request).execute();
+
+    response.body().byteStream();
+    response.body().close();
+
+    client.getForObject("/waitSlowInputStreamClosed", Void.class);
+  }
+}
diff --git a/integration-tests/it-edge/src/main/resources/microservice.yaml 
b/integration-tests/it-edge/src/main/resources/microservice.yaml
index 476f3e9..888f1dd 100644
--- a/integration-tests/it-edge/src/main/resources/microservice.yaml
+++ b/integration-tests/it-edge/src/main/resources/microservice.yaml
@@ -34,30 +34,45 @@ servicecomb:
   #        emptyAsNull: true
   operation:
     it-producer:
+      download:
+        slowInputStream:
+          transport: rest
       defaultJsonValueJaxrs:
         jsonInput:
           transport: rest
         queryInput:
           transport: rest
     it-producer-h2:
+      download:
+        slowInputStream:
+          transport: rest
       defaultJsonValueJaxrs:
         jsonInput:
           transport: rest
         queryInput:
           transport: rest
     it-producer-h2c:
+      download:
+        slowInputStream:
+          transport: rest
       defaultJsonValueJaxrs:
         jsonInput:
           transport: rest
         queryInput:
           transport: rest
     it-producer-deploy-springboot2-servlet:
+      download:
+        slowInputStream:
+          transport: rest
       defaultJsonValueJaxrs:
         jsonInput:
           transport: rest
         queryInput:
           transport: rest
     it-producer-deploy-springboot2-standalone:
+      download:
+        slowInputStream:
+          transport: rest
       defaultJsonValueJaxrs:
         jsonInput:
           transport: rest
diff --git 
a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java
 
b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java
index 89a5d1a..b1123b6 100644
--- 
a/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java
+++ 
b/integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/DownloadSchema.java
@@ -20,6 +20,9 @@ import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.lang.Thread.State;
 import java.net.HttpURLConnection;
 import java.net.URI;
 import java.net.URL;
@@ -27,15 +30,18 @@ import java.net.URLDecoder;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.UUID;
+import java.util.concurrent.TimeUnit;
 
 import javax.servlet.http.Part;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.impl.bootstrap.HttpServer;
 import org.apache.http.impl.bootstrap.ServerBootstrap;
 import org.apache.servicecomb.core.BootListener;
 import org.apache.servicecomb.foundation.common.part.FilePart;
+import org.apache.servicecomb.it.ITUtils;
 import org.apache.servicecomb.provider.rest.common.RestSchema;
 import org.springframework.core.io.ByteArrayResource;
 import org.springframework.core.io.Resource;
@@ -194,4 +200,45 @@ public class DownloadSchema implements BootListener {
     conn.disconnect();
     return responseEntity;
   }
+
+  private Thread slowInputStreamThread;
+
+  @GetMapping(path = "/waitSlowInputStreamClosed")
+  public void waitSlowInputStreamClosed() {
+    while (!slowInputStreamThread.getState().equals(State.TERMINATED)) {
+      ITUtils.forceWait(TimeUnit.MILLISECONDS, 500);
+    }
+  }
+
+  @ApiResponses({@ApiResponse(code = 200, response = File.class, message = 
"")})
+  @GetMapping(path = "/slowInputStream")
+  public ResponseEntity<InputStream> slowInputStream() throws IOException {
+    PipedInputStream in = new PipedInputStream();
+    PipedOutputStream out = new PipedOutputStream();
+    in.connect(out);
+
+    slowInputStreamThread = new Thread(() -> {
+      Thread.currentThread().setName("download thread");
+      byte[] bytes = "1".getBytes();
+      for (; ; ) {
+        try {
+          out.write(bytes);
+          out.flush();
+          Thread.sleep(1000);
+        } catch (Throwable e) {
+          break;
+        }
+      }
+
+      IOUtils.closeQuietly(out);
+    });
+    slowInputStreamThread.start();
+
+    ResponseEntity<InputStream> responseEntity = ResponseEntity
+        .ok()
+        .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
+        .header(HttpHeaders.CONTENT_DISPOSITION, 
"attachment;filename=slowInputStream.txt")
+        .body(in);
+    return responseEntity;
+  }
 }

Reply via email to