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

zhfeng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git


The following commit(s) were added to refs/heads/main by this push:
     new c614dc6  Fix #2745 Expand AWS S3 test coverage (#3077)
c614dc6 is described below

commit c614dc68f912514b36d8ff749ca9815acc18a067
Author: Amos Feng <[email protected]>
AuthorDate: Fri Sep 10 21:21:46 2021 +0800

    Fix #2745 Expand AWS S3 test coverage (#3077)
    
    * Fix #2745 Expand AWS S3 test coverage
    * Multipart upload
    * copyObject
    * listBuckets
    * deleteBucket
    * downloadLink
    * getObjectRange
    
    * Fix multipart upload test
---
 integration-test-groups/aws2/aws2-s3/pom.xml       |   4 +
 .../quarkus/component/aws2/Aws2S3Resource.java     | 149 +++++++++++++++++++-
 .../src/main/resources/application.properties      |   1 -
 .../camel/quarkus/component/aws2/Aws2S3Test.java   | 155 +++++++++++++++++++++
 integration-tests/aws2-grouped/pom.xml             |   4 +
 5 files changed, 307 insertions(+), 6 deletions(-)

diff --git a/integration-test-groups/aws2/aws2-s3/pom.xml 
b/integration-test-groups/aws2/aws2-s3/pom.xml
index fe36bbe..f839478 100644
--- a/integration-test-groups/aws2/aws2-s3/pom.xml
+++ b/integration-test-groups/aws2/aws2-s3/pom.xml
@@ -52,6 +52,10 @@
         </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-multipart</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
             <artifactId>quarkus-resteasy-jackson</artifactId>
         </dependency>
 
diff --git 
a/integration-test-groups/aws2/aws2-s3/src/main/java/org/apache/camel/quarkus/component/aws2/Aws2S3Resource.java
 
b/integration-test-groups/aws2/aws2-s3/src/main/java/org/apache/camel/quarkus/component/aws2/Aws2S3Resource.java
index 8d7903f..e3794c1 100644
--- 
a/integration-test-groups/aws2/aws2-s3/src/main/java/org/apache/camel/quarkus/component/aws2/Aws2S3Resource.java
+++ 
b/integration-test-groups/aws2/aws2-s3/src/main/java/org/apache/camel/quarkus/component/aws2/Aws2S3Resource.java
@@ -16,19 +16,31 @@
  */
 package org.apache.camel.quarkus.component.aws2;
 
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.io.Reader;
 import java.net.URI;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.StandardOpenOption;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.DELETE;
+import javax.ws.rs.FormParam;
 import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
@@ -37,6 +49,10 @@ import org.apache.camel.ProducerTemplate;
 import org.apache.camel.component.aws2.s3.AWS2S3Constants;
 import org.apache.camel.component.aws2.s3.AWS2S3Operations;
 import org.eclipse.microprofile.config.inject.ConfigProperty;
+import software.amazon.awssdk.core.ResponseInputStream;
+import software.amazon.awssdk.services.s3.model.Bucket;
+import software.amazon.awssdk.services.s3.model.GetObjectResponse;
+import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
 import software.amazon.awssdk.services.s3.model.S3Object;
 
 @Path("/aws2")
@@ -66,9 +82,13 @@ public class Aws2S3Resource {
     @Path("s3/object/{key}")
     @GET
     @Produces(MediaType.TEXT_PLAIN)
-    public String get(@PathParam("key") String key) throws Exception {
+    public String get(@PathParam("key") String key, @QueryParam("bucket") 
String bucket) throws Exception {
+        if (bucket == null) {
+            bucket = bucketName;
+        }
+
         return producerTemplate.requestBodyAndHeader(
-                componentUri(AWS2S3Operations.getObject),
+                componentUri(bucket, AWS2S3Operations.getObject),
                 null,
                 AWS2S3Constants.KEY,
                 key,
@@ -97,18 +117,137 @@ public class Aws2S3Resource {
     @Path("s3/object-keys")
     @GET
     @Produces(MediaType.APPLICATION_JSON)
-    public List<String> objectKey() throws Exception {
+    public List<String> objectKey(@QueryParam("bucket") String bucket) throws 
Exception {
+        if (bucket == null) {
+            bucket = bucketName;
+        }
+
         final List<S3Object> objects = (List<S3Object>) 
producerTemplate.requestBody(
-                componentUri(AWS2S3Operations.listObjects),
+                componentUri(bucket, AWS2S3Operations.listObjects) + 
"&autoCreateBucket=true",
                 null,
                 List.class);
         return 
objects.stream().map(S3Object::key).collect(Collectors.toList());
     }
 
-    private String componentUri(final AWS2S3Operations operation) {
+    @Path("s3/upload/{key}")
+    @POST
+    @Consumes(MediaType.TEXT_PLAIN)
+    @Produces(MediaType.TEXT_PLAIN)
+    public String upload(@PathParam("key") String key, String content) throws 
Exception {
+        File file = File.createTempFile("aws2-", ".tmp");
+        Files.writeString(file.toPath(), content, StandardOpenOption.WRITE);
+        int partSize = 5 * 1024 * 1024;
+
+        producerTemplate.sendBodyAndHeader(
+                componentUri() + "?multiPartUpload=true&partSize=" + partSize 
+ "&autoCreateBucket=true",
+                file,
+                AWS2S3Constants.KEY,
+                key);
+
+        return key;
+    }
+
+    @Path("s3/copy/{key}")
+    @POST
+    @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response copyObject(@PathParam("key") String key,
+            @FormParam("dest_key") String dest_key, @FormParam("dest_bucket") 
String dest_bucket) {
+        Map<String, Object> headers = new LinkedHashMap<>();
+        headers.put(AWS2S3Constants.KEY, key);
+        headers.put(AWS2S3Constants.DESTINATION_KEY, dest_key);
+        headers.put(AWS2S3Constants.BUCKET_DESTINATION_NAME, dest_bucket);
+
+        producerTemplate.sendBodyAndHeaders(
+                componentUri(AWS2S3Operations.copyObject),
+                null, headers);
+
+        return Response.noContent().build();
+    }
+
+    @Path("s3/bucket")
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public List<String> listBuckets() throws Exception {
+        List<Bucket> buckets = (List<Bucket>) producerTemplate.requestBody(
+                componentUri(AWS2S3Operations.listBuckets),
+                null,
+                List.class);
+        return buckets.stream().map(Bucket::name).collect(Collectors.toList());
+    }
+
+    @Path("s3/bucket/{name}")
+    @DELETE
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response deleteBucket(@PathParam("name") String bucketName) {
+        try {
+            producerTemplate.sendBodyAndHeader(
+                    componentUri(bucketName, AWS2S3Operations.deleteBucket),
+                    null,
+                    AWS2S3Constants.BUCKET_NAME,
+                    bucketName);
+        } catch (NoSuchBucketException e) {
+            return Response.status(Response.Status.NOT_FOUND).build();
+        }
+
+        return Response.noContent().build();
+    }
+
+    @Path("s3/downloadlink/{key}")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String downloadLink(@PathParam("key") String key, 
@QueryParam("bucket") String bucket) {
+        if (bucket == null) {
+            bucket = bucketName;
+        }
+
+        String link = producerTemplate.requestBodyAndHeader(
+                componentUri(bucket, AWS2S3Operations.createDownloadLink),
+                null,
+                AWS2S3Constants.KEY,
+                key,
+                String.class);
+
+        return link;
+    }
+
+    @Path("s3/object/range/{key}")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public String objectRange(@PathParam("key") String key,
+            @QueryParam("start") Integer start,
+            @QueryParam("end") Integer end) throws Exception {
+        Map<String, Object> headers = new LinkedHashMap<>();
+        headers.put(AWS2S3Constants.KEY, key);
+        headers.put(AWS2S3Constants.RANGE_START, start);
+        headers.put(AWS2S3Constants.RANGE_END, end);
+
+        ResponseInputStream<GetObjectResponse> s3Object = 
producerTemplate.requestBodyAndHeaders(
+                componentUri(AWS2S3Operations.getObjectRange) + 
"&autoCreateBucket=false",
+                null,
+                headers,
+                ResponseInputStream.class);
+
+        StringBuilder textBuilder = new StringBuilder();
+        try (Reader reader = new BufferedReader(
+                new InputStreamReader(s3Object, 
Charset.forName(StandardCharsets.UTF_8.name())))) {
+            int c = 0;
+            while ((c = reader.read()) != -1) {
+                textBuilder.append((char) c);
+            }
+        }
+
+        return textBuilder.toString();
+    }
+
+    private String componentUri(String bucketName, final AWS2S3Operations 
operation) {
         return String.format("aws2-s3://%s?operation=%s", bucketName, 
operation);
     }
 
+    private String componentUri(final AWS2S3Operations operation) {
+        return componentUri(bucketName, operation);
+    }
+
     private String componentUri() {
         return String.format("aws2-s3://%s", bucketName);
     }
diff --git 
a/integration-test-groups/aws2/aws2-s3/src/main/resources/application.properties
 
b/integration-test-groups/aws2/aws2-s3/src/main/resources/application.properties
index 967305c..745bd72 100644
--- 
a/integration-test-groups/aws2/aws2-s3/src/main/resources/application.properties
+++ 
b/integration-test-groups/aws2/aws2-s3/src/main/resources/application.properties
@@ -14,7 +14,6 @@
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
 ## ---------------------------------------------------------------------------
-
 #
 # Camel :: AWS2 options
 #
diff --git 
a/integration-test-groups/aws2/aws2-s3/src/test/java/org/apache/camel/quarkus/component/aws2/Aws2S3Test.java
 
b/integration-test-groups/aws2/aws2-s3/src/test/java/org/apache/camel/quarkus/component/aws2/Aws2S3Test.java
index 372818b..2113683 100644
--- 
a/integration-test-groups/aws2/aws2-s3/src/test/java/org/apache/camel/quarkus/component/aws2/Aws2S3Test.java
+++ 
b/integration-test-groups/aws2/aws2-s3/src/test/java/org/apache/camel/quarkus/component/aws2/Aws2S3Test.java
@@ -24,10 +24,12 @@ import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
 import io.restassured.http.ContentType;
 import org.apache.camel.quarkus.test.support.aws2.Aws2TestResource;
+import org.apache.commons.lang3.RandomStringUtils;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertEquals;
 
 @QuarkusTest
 @QuarkusTestResource(Aws2TestResource.class)
@@ -125,4 +127,157 @@ class Aws2S3Test {
         }
     }
 
+    @Test
+    public void upload() throws Exception {
+        final String oid = UUID.randomUUID().toString();
+        final String content = RandomStringUtils.randomAlphabetic(8 * 1024 * 
1024);
+
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .body(content)
+                .post("/aws2/s3/upload/" + oid)
+                .then()
+                .statusCode(200);
+
+        String result = RestAssured.get("/aws2/s3/object/" + oid)
+                .then()
+                .statusCode(200)
+                .extract().asString();
+
+        // strip the chuck-signature
+        result = result.replaceAll("\\s*[0-9]+;chunk-signature=\\w{64}\\s*", 
"");
+        assertEquals(content, result);
+    }
+
+    @Test
+    public void copyObject() throws Exception {
+        final String oid1 = UUID.randomUUID().toString();
+        final String oid2 = UUID.randomUUID().toString();
+        final String blobContent = "Hello " + oid1;
+        final String bucket = "mycamel";
+
+        // Create
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .body(blobContent)
+                .post("/aws2/s3/object/" + oid1)
+                .then()
+                .statusCode(201);
+
+        // Check the dest bucket does not contain oid2
+        final String[] objects = getAllObjects(bucket);
+        Assertions.assertTrue(Stream.of(objects).noneMatch(key -> 
key.equals(oid2)));
+
+        // Copy
+        RestAssured.given()
+                .contentType(ContentType.URLENC)
+                .formParam("dest_key", oid2)
+                .formParam("dest_bucket", bucket)
+                .post("/aws2/s3/copy/" + oid1)
+                .then()
+                .statusCode(204);
+
+        // Verify the object
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .get("/aws2/s3/object/" + oid2 + "?bucket=" + bucket)
+                .then()
+                .statusCode(200)
+                .body(is(blobContent));
+
+    }
+
+    @Test
+    void listBuckets() throws Exception {
+        final String[] buckets = getAllBuckets();
+
+        Assertions.assertTrue(Stream.of(buckets).anyMatch(key -> 
key.startsWith("camel-quarkus")));
+    }
+
+    @Test
+    void deleteBucket() throws Exception {
+        final String bucket = "mycamel-delete";
+
+        String[] objects = getAllObjects(bucket);
+        Assertions.assertTrue(objects.length == 0);
+
+        String[] buckets = getAllBuckets();
+        Assertions.assertTrue(Stream.of(buckets).anyMatch(key -> 
key.equals("mycamel-delete")));
+
+        RestAssured.delete("/aws2/s3/bucket/" + bucket)
+                .then()
+                .statusCode(204);
+
+        buckets = getAllBuckets();
+        Assertions.assertTrue(Stream.of(buckets).noneMatch(key -> 
key.equals("mycamel-delete")));
+    }
+
+    @Test
+    public void downloadLink() throws Exception {
+        final String oid = UUID.randomUUID().toString();
+        final String blobContent = "Hello " + oid;
+
+        // Create
+        createObject(oid, blobContent);
+
+        // Download link
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .get("/aws2/s3/downloadlink/" + oid)
+                .then()
+                .statusCode(200);
+
+    }
+
+    @Test
+    public void objectRange() {
+        final String oid = UUID.randomUUID().toString();
+        final String blobContent = "Hello " + oid;
+
+        // Create
+        createObject(oid, blobContent);
+
+        // Object range
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .param("start", "0").param("end", "4")
+                .get("/aws2/s3/object/range/" + oid)
+                .then()
+                .statusCode(200)
+                .body(is("Hello"));
+    }
+
+    private void createObject(String oid, String blobContent) {
+        RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .body(blobContent)
+                .post("/aws2/s3/object/" + oid)
+                .then()
+                .statusCode(201);
+    }
+
+    private String[] getAllObjects(String bucket) {
+        final String[] objects = RestAssured.given()
+                .param("bucket", bucket)
+                .get("/aws2/s3/object-keys")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body().as(String[].class);
+
+        return objects;
+    }
+
+    private String[] getAllBuckets() {
+        String[] buckets = RestAssured.given()
+                .contentType(ContentType.TEXT)
+                .get("/aws2/s3/bucket")
+                .then()
+                .statusCode(200)
+                .extract()
+                .body().as(String[].class);
+
+        return buckets;
+    }
+
 }
diff --git a/integration-tests/aws2-grouped/pom.xml 
b/integration-tests/aws2-grouped/pom.xml
index 04cf58b..cfe3e10 100644
--- a/integration-tests/aws2-grouped/pom.xml
+++ b/integration-tests/aws2-grouped/pom.xml
@@ -56,6 +56,10 @@
             <artifactId>quarkus-resteasy-jackson</artifactId>
         </dependency>
         <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-resteasy-multipart</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.apache.camel.quarkus</groupId>
             <artifactId>camel-quarkus-aws2-cw</artifactId>
         </dependency>

Reply via email to