Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RESTEasy Reactive JAX-RS scenario #178

Merged
merged 2 commits into from
Aug 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,27 +129,30 @@ The following command will execute the whole test suite including serverless tes

## Existing tests

### `http-minimum`
### `http/http-minimum`
Verifies that you can deploy a simple HTTP endpoint to OpenShift and access it.
It also verifies multiple deployment strategies like:
- Serverless
- Using OpenShift quarkus extension
- Using OpenShift quarkus extension and Docker Build strategy

### `http-advanced`
### `http/http-advanced`
Verifies Server/Client http_2/1.1, Grpc and http redirections.

### `http-static`
### `http/http-static`
Verifies access to static pages and big static files over http.

### `servlet-undertow`
### `http/servlet-undertow`
This module covers basic scenarios about HTTP servlets under `quarkus-undertow` server more in details:
- Http session eviction
- Undertow web.xml configuration

### `jaxrs`
### `http/jaxrs`
Simple bootstrap project created by *quarkus-maven-plugin*

### `http/jaxrs-reactive`
RESTEasy Reactive equivalent of `http/jaxrs`. Tests simple and multipart endpoints.

### `http/rest-client`
Verifies Rest Client configuration using `quarkus-rest-client-jaxb` (XML support) and `quarkus-rest-client-jsonb` (JSON support).
This module will setup a very minimal configuration (only `quarkus-resteasy`) and have four endpoints:
Expand All @@ -160,11 +163,11 @@ This module will setup a very minimal configuration (only `quarkus-resteasy`) an
* *@Deprecated* annotation has been added for test regression purposes to ensure `java.lang` annotations are allowed for resources
* Resource with multipart body support, provided parts are text, image and binary data, charset checked with `us-ascii` and `utf-8`

### `reactive-routes`
### `http/reactive-routes`
This module covers some basic scenarios around reactive routes in general and also:
- Validation on request params, request body and responses.

### `vertx-web-client`
### `http/vertx-web-client`
Vert.x Mutiny webClient exploratory test.
* Vert.x WebClient
* Quarkus Resteasy Mutiny / Jsonb
Expand Down
23 changes: 23 additions & 0 deletions http/jaxrs-reactive/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.quarkus.ts.qe</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<artifactId>jaxrs-reactive</artifactId>
<packaging>jar</packaging>
<name>Quarkus QE TS: HTTP: jaxrs-reactive</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-reactive</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package io.quarkus.ts.jaxrs.reactive;

import java.io.File;

import javax.ws.rs.core.MediaType;

import org.jboss.resteasy.reactive.PartType;
import org.jboss.resteasy.reactive.RestForm;

public class MultipartBody {

@RestForm("text")
@PartType(MediaType.TEXT_PLAIN)
public String text;

@RestForm("image")
@PartType("image/png")
public File image;

@RestForm("data")
@PartType(MediaType.APPLICATION_OCTET_STREAM)
public File data;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.quarkus.ts.jaxrs.reactive;

import java.io.IOException;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.apache.commons.io.IOUtils;
import org.jboss.resteasy.reactive.MultipartForm;

@Path("/multipart")
public class MultipartResource {

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.MULTIPART_FORM_DATA)
public MultipartBody postForm(@MultipartForm MultipartBody multipartBody) {
return multipartBody;
}

@POST
@Path("/text")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN)
public String postFormReturnText(@MultipartForm MultipartBody multipartBody) {
return multipartBody.text;
}

@POST
@Path("/image")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public byte[] postFormReturnFile(@MultipartForm MultipartBody multipartBody) throws IOException {
return IOUtils.toByteArray(multipartBody.image.toURI());
}

@POST
@Path("/data")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_OCTET_STREAM)
public byte[] postFormReturnData(@MultipartForm MultipartBody multipartBody) throws IOException {
return IOUtils.toByteArray(multipartBody.data.toURI());
}

@POST
@Path("/echo")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_PLAIN)
public String echo(String requestBody) {
return requestBody;
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.quarkus.ts.jaxrs.reactive;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;

import java.nio.charset.StandardCharsets;

import org.junit.jupiter.api.Test;

import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.services.QuarkusApplication;
import io.restassured.builder.MultiPartSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.specification.MultiPartSpecification;

@QuarkusScenario
public class AsciiMultipartResourceIT {

public static final String TEXT_WITH_DIACRITICS = "Přikrášlený žloťoučký kůň úpěl ďábelské ódy.";
private static final String EXPECTED_ASCII_TEXT = new String(TEXT_WITH_DIACRITICS.getBytes(StandardCharsets.UTF_8),
StandardCharsets.US_ASCII);

@QuarkusApplication
static RestService app = new RestService().withProperties("us-asscii.properties");

@Test
public void testMultipartText() {
MultiPartSpecification multiPartSpecification = new MultiPartSpecBuilder(TEXT_WITH_DIACRITICS)
.controlName("text")
.header("Content-Type", "text/plain")
.charset(StandardCharsets.UTF_8)
.build();

app.given().multiPart(multiPartSpecification)
.post("/multipart/text")
.then()
.statusCode(200)
.contentType(ContentType.TEXT)
.body(not(equalTo(TEXT_WITH_DIACRITICS)))
.body(equalTo(EXPECTED_ASCII_TEXT));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package io.quarkus.ts.jaxrs.reactive;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Random;

import javax.ws.rs.core.MediaType;

import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import io.quarkus.test.scenarios.QuarkusScenario;
import io.restassured.RestAssured;
import io.restassured.builder.MultiPartSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.response.ValidatableResponse;
import io.restassured.specification.MultiPartSpecification;

@QuarkusScenario
public class MultipartResourceIT {

private static final String IMAGE_FILE_NAME = "/quarkus.png";
private static final String TEXT_WITH_DIACRITICS = "Přikrášlený žloťoučký kůň úpěl ďábelské ódy.";
private static byte[] randomBytes = new byte[120];
private static File imageFile;
private static byte[] imageBytes;

@BeforeAll
public static void beforeAll() throws IOException {
imageFile = new File(MultipartResourceIT.class.getResource(IMAGE_FILE_NAME).getFile());
imageBytes = IOUtils.toByteArray(MultipartResourceIT.class.getResourceAsStream(IMAGE_FILE_NAME));
new Random().nextBytes(randomBytes);
}

@Test
public void testMultipartIsSendAndReceived() {
whenSendMultipartData("/multipart")
.contentType("multipart/form-data");
}

@Test
public void testTextVersionOfMultipart() {
whenSendMultipartData("/multipart/echo")
.contentType(ContentType.TEXT)
.body(
containsString("Content-Disposition: form-data; name=\"text\""),
containsString("Content-Disposition: form-data; name=\"data\"; filename=\"random.dat\""),
containsString("Content-Disposition: form-data; name=\"image\"; filename=\"quarkus.png\""),
containsString(TEXT_WITH_DIACRITICS));
}

@Test
public void testTextPartFromMultipart() {
whenSendMultipartData("/multipart/text")
.contentType(ContentType.TEXT)
.body(equalTo(TEXT_WITH_DIACRITICS));
}

@Test
public void testImagePartFromMultipart() {
byte[] receivedBytes = whenSendMultipartData("/multipart/image")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.extract().asByteArray();
assertThat(receivedBytes, equalTo(imageBytes));
}

@Test
public void testDataPartFromMultipart() {
byte[] receivedBytes = whenSendMultipartData("/multipart/data")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.extract().asByteArray();
assertThat(receivedBytes, equalTo(randomBytes));
}

private ValidatableResponse whenSendMultipartData(String path) {
MultiPartSpecification textSpec = new MultiPartSpecBuilder(TEXT_WITH_DIACRITICS)
.controlName("text")
.mimeType("text/plain")
.charset(StandardCharsets.UTF_8)
.build();
MultiPartSpecification dataSpec = new MultiPartSpecBuilder(randomBytes)
.controlName("data")
.fileName("random.dat")
.header("Content-Type", "application/octet-stream")
.build();
MultiPartSpecification imageSpec = new MultiPartSpecBuilder(imageFile)
.controlName("image")
.fileName("quarkus.png")
.mimeType("image/png")
.build();

return RestAssured.given()
.contentType("multipart/form-data")
.multiPart(textSpec)
.multiPart(imageSpec)
.multiPart(dataSpec)
.post(path)
.then()
.statusCode(200);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.quarkus.ts.jaxrs.reactive;

import io.quarkus.test.scenarios.OpenShiftScenario;

@OpenShiftScenario
public class OpenShiftMultipartResourceIT extends MultipartResourceIT {
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
quarkus.resteasy-reactive.multipart.input-part.default-charset=us-ascii
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void verifyIfUserIsInformedAboutAmqpDevServicePulling() {
public void verifyAmqpImage() {
Image postgresImg = DockerUtils.getImage(AMQP_IMAGE, AMQP_VERSION);
Assertions.assertFalse(postgresImg.getId().isEmpty(), String.format("%s:%s not found. " +
"Notice that user set his own custom image by 'quarkus.keycloak.devservices.image-name' property",
"Notice that user set his own custom image by 'quarkus.keycloak.devservices.image-name' property",
AMQP_IMAGE, AMQP_VERSION));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void verifyIfUserIsInformedAboutRedPandaDevServicePulling() {
public void verifyRedPandaImage() {
Image postgresImg = DockerUtils.getImage(RED_PANDA_IMAGE, RED_PANDA_VERSION);
Assertions.assertFalse(postgresImg.getId().isEmpty(), String.format("%s:%s not found. " +
"Notice that user set his own custom image by 'quarkus.datasource.devservices.image-name' property",
"Notice that user set his own custom image by 'quarkus.datasource.devservices.image-name' property",
RED_PANDA_IMAGE, RED_PANDA_VERSION));
}
}
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@
<module>http/http-advanced</module>
<module>http/http-static</module>
<module>http/jaxrs</module>
<module>http/jaxrs-reactive</module>
<module>http/reactive-routes</module>
<module>http/rest-client</module>
<module>http/servlet-undertow</module>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.scenarios.annotations.DisabledOnNative;
import io.quarkus.test.services.DevModeQuarkusApplication;

@Tag("QUARKUS-959")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void verifyIfUserIsInformedAboutMariadbDevServicePulling() {
public void verifyMysqlImage() {
Image postgresImg = DockerUtils.getImage(MARIA_DB_NAME, MARIA_DB_VERSION);
Assertions.assertFalse(postgresImg.getId().isEmpty(), String.format("%s:%s not found. " +
"Notice that user set his own custom image by 'quarkus.datasource.devservices.image-name' property",
"Notice that user set his own custom image by 'quarkus.datasource.devservices.image-name' property",
MARIA_DB_NAME, MARIA_DB_VERSION));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.scenarios.annotations.DisabledOnNative;
import io.quarkus.test.services.DevModeQuarkusApplication;

@Tag("QUARKUS-959")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public void verifyIfUserIsInformedAboutMssqlDevServicePulling() {
public void verifyMssqlImage() {
Image postgresImg = DockerUtils.getImage(MSSQL_NAME, MSSQL_VERSION);
Assertions.assertFalse(postgresImg.getId().isEmpty(), String.format("%s:%s not found. " +
"Notice that user set his own custom image by 'quarkus.datasource.devservices.image-name' property",
"Notice that user set his own custom image by 'quarkus.datasource.devservices.image-name' property",
MSSQL_NAME, MSSQL_VERSION));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.scenarios.annotations.DisabledOnNative;
import io.quarkus.test.services.DevModeQuarkusApplication;

@Tag("QUARKUS-959")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void verifyIfUserIsInformedAboutMysqlDevServicePulling() {
public void verifyMysqlImage() {
Image postgresImg = DockerUtils.getImage(MYSQL_NAME, MYSQL_VERSION);
Assertions.assertFalse(postgresImg.getId().isEmpty(), String.format("%s:%s not found. " +
"Notice that user set his own custom image by 'quarkus.datasource.devservices.image-name' property",
"Notice that user set his own custom image by 'quarkus.datasource.devservices.image-name' property",
MYSQL_NAME, MYSQL_VERSION));
}
}
Loading