From b840c77c778cfc2d961976cbbd5c1540207c76be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Vav=C5=99=C3=ADk?= Date: Thu, 5 Sep 2024 15:30:34 +0200 Subject: [PATCH] Test TLS Registry integration with gRPC --- .../ts/http/grpc/GrpcReflectionResponse.java | 14 +++- .../src/main/resources/application.properties | 18 +++++ .../java/io/quarkus/ts/http/grpc/GRPCIT.java | 22 +++--- .../grpc/GrpcMutualTlsSeparateServerIT.java | 79 +++++++++++++++++++ .../ts/http/grpc/GrpcTlsSeparateServerIT.java | 48 ++++++----- .../http/grpc/OpenShiftExtensionGRPCIT.java | 6 +- .../quarkus/ts/http/grpc/OpenShiftGRPCIT.java | 6 +- .../ts/http/grpc/ReflectionHttpIT.java | 31 ++++---- .../io/quarkus/ts/http/grpc/SameServerIT.java | 19 ++++- .../ts/http/grpc/SeparateServerIT.java | 19 ++++- .../quarkus/ts/http/grpc/StreamingHttpIT.java | 34 +++----- 11 files changed, 218 insertions(+), 78 deletions(-) create mode 100644 http/grpc/src/test/java/io/quarkus/ts/http/grpc/GrpcMutualTlsSeparateServerIT.java diff --git a/http/grpc/src/main/java/io/quarkus/ts/http/grpc/GrpcReflectionResponse.java b/http/grpc/src/main/java/io/quarkus/ts/http/grpc/GrpcReflectionResponse.java index bb86462ca..e20a24b06 100644 --- a/http/grpc/src/main/java/io/quarkus/ts/http/grpc/GrpcReflectionResponse.java +++ b/http/grpc/src/main/java/io/quarkus/ts/http/grpc/GrpcReflectionResponse.java @@ -3,8 +3,11 @@ import java.util.List; public final class GrpcReflectionResponse { - private final int serviceCount; - private final List serviceList; + private int serviceCount; + private List serviceList; + + public GrpcReflectionResponse() { + } public GrpcReflectionResponse(int serviceCount, List serviceList) { this.serviceCount = serviceCount; @@ -19,4 +22,11 @@ public int getServiceCount() { return serviceCount; } + public void setServiceCount(int serviceCount) { + this.serviceCount = serviceCount; + } + + public void setServiceList(List serviceList) { + this.serviceList = serviceList; + } } diff --git a/http/grpc/src/main/resources/application.properties b/http/grpc/src/main/resources/application.properties index a0266aecd..39fb43832 100644 --- a/http/grpc/src/main/resources/application.properties +++ b/http/grpc/src/main/resources/application.properties @@ -19,3 +19,21 @@ quarkus.grpc.clients.streaming.port=${quarkus.grpc.clients.plain.port} %ssl.quarkus.http.ssl.certificate.key-files=${grpc.server.key} %ssl.quarkus.grpc.server.ssl.certificate=${grpc.server.cert} %ssl.quarkus.grpc.server.ssl.key=${grpc.server.key} + +%mtls.quarkus.http.insecure-requests=disabled +%mtls.quarkus.grpc.server.plain-text=false +%mtls.quarkus.grpc.clients.plain.tls-configuration-name=mtls-client +%mtls.quarkus.grpc.clients.reflection-service.tls-configuration-name=mtls-client +%mtls.quarkus.grpc.clients.streaming.tls-configuration-name=mtls-client +%mtls.quarkus.grpc.clients.plain.tls.enabled=true +%mtls.quarkus.grpc.clients.reflection-service.tls.enabled=true +%mtls.quarkus.grpc.clients.streaming.tls.enabled=true +%mtls.quarkus.grpc.clients.plain.plain-text=false +%mtls.quarkus.grpc.clients.reflection-service.plain-text=false +%mtls.quarkus.grpc.clients.streaming.plain-text=false +%mtls.quarkus.grpc.clients.reflection-service.use-quarkus-grpc-client=true +%mtls.quarkus.grpc.clients.streaming.use-quarkus-grpc-client=true +%mtls.quarkus.grpc.clients.plain.port=${quarkus.http.ssl-port} +%mtls.quarkus.tls.mtls-client.key-store.pem.0.cert=${grpc.client.crt} +%mtls.quarkus.tls.mtls-client.key-store.pem.0.key=${grpc.client.key} +%mtls.quarkus.tls.mtls-client.trust-store.pem.certs=${grpc.client.ca-crt} diff --git a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/GRPCIT.java b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/GRPCIT.java index fc20ab3ff..029f9020b 100644 --- a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/GRPCIT.java +++ b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/GRPCIT.java @@ -1,33 +1,33 @@ package io.quarkus.ts.http.grpc; -import static org.hamcrest.CoreMatchers.is; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.Iterator; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicInteger; import org.apache.http.HttpStatus; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import io.quarkus.test.bootstrap.CloseableManagedChannel; -import io.quarkus.test.bootstrap.RestService; import io.quarkus.ts.grpc.GreeterGrpc; import io.quarkus.ts.grpc.HelloReply; import io.quarkus.ts.grpc.HelloRequest; import io.quarkus.ts.grpc.StreamingGrpc; +import io.vertx.mutiny.ext.web.client.WebClient; public interface GRPCIT { - RestService app(); - CloseableManagedChannel getChannel(); + WebClient getWebClient(); + @Test default void grpcClient() { - app().given().get("/http/grpc").then() - .statusCode(HttpStatus.SC_OK) - .body(is("Hello grpc")); + var response = getWebClient().get("/http/grpc").sendAndAwait(); + assertEquals(HttpStatus.SC_OK, response.statusCode()); + assertTrue(response.bodyAsString().startsWith("Hello grpc")); } @Test @@ -35,7 +35,7 @@ default void grpcServer() throws ExecutionException, InterruptedException { try (var channel = getChannel()) { HelloRequest request = HelloRequest.newBuilder().setName("server").build(); HelloReply response = GreeterGrpc.newFutureStub(channel).sayHello(request).get(); - Assertions.assertEquals("Hello server", response.getMessage()); + assertEquals("Hello server", response.getMessage()); } } @@ -46,10 +46,10 @@ default void serverStream() { Iterator stream = StreamingGrpc.newBlockingStub(channel).serverStream(request); AtomicInteger counter = new AtomicInteger(0); stream.forEachRemaining((reply) -> { - Assertions.assertEquals("Hello ServerStream", reply.getMessage()); + assertEquals("Hello ServerStream", reply.getMessage()); counter.incrementAndGet(); }); - Assertions.assertEquals(GrpcStreamingService.SERVER_STREAM_MESSAGES_COUNT, counter.get()); + assertEquals(GrpcStreamingService.SERVER_STREAM_MESSAGES_COUNT, counter.get()); } } } diff --git a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/GrpcMutualTlsSeparateServerIT.java b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/GrpcMutualTlsSeparateServerIT.java new file mode 100644 index 000000000..2bf897f49 --- /dev/null +++ b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/GrpcMutualTlsSeparateServerIT.java @@ -0,0 +1,79 @@ +package io.quarkus.ts.http.grpc; + +import static io.quarkus.test.security.certificate.CertificateBuilder.INSTANCE_KEY; +import static io.quarkus.test.services.Certificate.Format.PEM; + +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.condition.OS; + +import io.quarkus.test.bootstrap.CloseableManagedChannel; +import io.quarkus.test.bootstrap.GrpcService; +import io.quarkus.test.scenarios.QuarkusScenario; +import io.quarkus.test.security.certificate.CertificateBuilder; +import io.quarkus.test.security.certificate.PemClientCertificate; +import io.quarkus.test.services.Certificate; +import io.quarkus.test.services.Certificate.ClientCertificate; +import io.quarkus.test.services.QuarkusApplication; +import io.vertx.mutiny.ext.web.client.WebClient; + +@Tag("QUARKUS-4592") +@QuarkusScenario +public class GrpcMutualTlsSeparateServerIT implements GRPCIT, StreamingHttpIT, ReflectionHttpIT { + + private static final String CERT_PREFIX = "grpc-mtls-separate-server"; + private static final String CLIENT_CN_NAME = "mtls-client-name"; + private static WebClient webClient = null; + + @QuarkusApplication(grpc = true, ssl = true, certificates = @Certificate(prefix = CERT_PREFIX, clientCertificates = { + @ClientCertificate(cnAttribute = CLIENT_CN_NAME) + }, format = PEM, configureKeystore = true, configureTruststore = true, tlsConfigName = "mtls-server", configureHttpServer = true)) + static final GrpcService app = (GrpcService) new GrpcService() + .withProperty("quarkus.http.ssl.client-auth", "required") + .withProperty("quarkus.profile", "mtls") + .withProperty("grpc.client.crt", GrpcMutualTlsSeparateServerIT::getClientCert) + .withProperty("grpc.client.ca-crt", GrpcMutualTlsSeparateServerIT::getClientCaCert) + .withProperty("grpc.client.key", GrpcMutualTlsSeparateServerIT::getClientKey); + + public CloseableManagedChannel getChannel() { + return app.securedGrpcChannel(); + } + + @Override + public WebClient getWebClient() { + if (webClient == null) { + // HINT: we don't need to close HTTPS client as FW takes care of it + webClient = app.mutinyHttps(CLIENT_CN_NAME); + } + return webClient; + } + + private static String getClientCert() { + return addEscapes(getClientCertificate().certPath()); + } + + private static String getClientCaCert() { + return addEscapes(getClientCertificate().truststorePath()); + } + + private static String getClientKey() { + return addEscapes(getClientCertificate().keyPath()); + } + + private static CertificateBuilder getCertificateBuilder() { + return app.getPropertyFromContext(CertificateBuilder.INSTANCE_KEY); + } + + private static PemClientCertificate getClientCertificate() { + return (PemClientCertificate) getCertificateBuilder().findCertificateByPrefix(CERT_PREFIX) + .getClientCertificateByCn(CLIENT_CN_NAME); + } + + static String addEscapes(String path) { + if (OS.WINDOWS.isCurrentOs()) { + // TODO: move this to the FW + // back-slashes have special meaning in Cygwin etc. + return path.replace("\\", "\\\\"); + } + return path; + } +} diff --git a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/GrpcTlsSeparateServerIT.java b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/GrpcTlsSeparateServerIT.java index c441be0cd..132237b05 100644 --- a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/GrpcTlsSeparateServerIT.java +++ b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/GrpcTlsSeparateServerIT.java @@ -1,56 +1,68 @@ package io.quarkus.ts.http.grpc; import static io.quarkus.test.services.Certificate.Format.PEM; +import static io.quarkus.ts.http.grpc.GrpcMutualTlsSeparateServerIT.addEscapes; + +import org.junit.jupiter.api.AfterAll; import io.quarkus.test.bootstrap.CloseableManagedChannel; import io.quarkus.test.bootstrap.GrpcService; -import io.quarkus.test.bootstrap.RestService; import io.quarkus.test.scenarios.QuarkusScenario; import io.quarkus.test.security.certificate.Certificate.PemCertificate; import io.quarkus.test.security.certificate.CertificateBuilder; import io.quarkus.test.services.Certificate; import io.quarkus.test.services.QuarkusApplication; -import io.restassured.specification.RequestSpecification; +import io.vertx.mutiny.ext.web.client.WebClient; @QuarkusScenario public class GrpcTlsSeparateServerIT implements GRPCIT, StreamingHttpIT, ReflectionHttpIT { private static final String CERT_PREFIX = "grpc-tls-separate-server"; + private static WebClient webClient = null; @QuarkusApplication(grpc = true, ssl = true, certificates = @Certificate(prefix = CERT_PREFIX, format = PEM, configureKeystore = true, configureTruststore = true)) static final GrpcService app = (GrpcService) new GrpcService() .withProperty("quarkus.profile", "ssl") - .withProperty("grpc.client.ca-cert", CertificateBuilder.INSTANCE_KEY, GrpcTlsSeparateServerIT::getClientCaCert) - .withProperty("grpc.server.cert", CertificateBuilder.INSTANCE_KEY, GrpcTlsSeparateServerIT::getServerCert) - .withProperty("grpc.server.key", CertificateBuilder.INSTANCE_KEY, GrpcTlsSeparateServerIT::getServerKey); + .withProperty("grpc.client.ca-cert", GrpcTlsSeparateServerIT::getClientCaCert) + .withProperty("grpc.server.cert", GrpcTlsSeparateServerIT::getServerCert) + .withProperty("grpc.server.key", GrpcTlsSeparateServerIT::getServerKey); public CloseableManagedChannel getChannel() { return app.securedGrpcChannel(); } @Override - public RestService app() { - return app; + public WebClient getWebClient() { + if (webClient == null) { + webClient = app.mutiny(); + } + return webClient; } - @Override - public RequestSpecification given() { - return app().relaxedHttps().given(); + @AfterAll + static void afterAll() { + if (webClient != null) { + webClient.close(); + } + } + + private static String getClientCaCert() { + return addEscapes(getPemCertificate().truststorePath()); } - private static String getClientCaCert(CertificateBuilder certificateBuilder) { - return getPemCertificate(certificateBuilder).truststorePath(); + private static String getServerCert() { + return addEscapes(getPemCertificate().certPath()); } - private static String getServerCert(CertificateBuilder certificateBuilder) { - return getPemCertificate(certificateBuilder).certPath(); + private static String getServerKey() { + return addEscapes(getPemCertificate().keyPath()); } - private static String getServerKey(CertificateBuilder certificateBuilder) { - return getPemCertificate(certificateBuilder).keyPath(); + private static PemCertificate getPemCertificate() { + return (PemCertificate) getCertificateBuilder().findCertificateByPrefix(CERT_PREFIX); } - private static PemCertificate getPemCertificate(CertificateBuilder certificateBuilder) { - return (PemCertificate) certificateBuilder.findCertificateByPrefix(CERT_PREFIX); + private static CertificateBuilder getCertificateBuilder() { + return app.getPropertyFromContext(CertificateBuilder.INSTANCE_KEY); } } diff --git a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/OpenShiftExtensionGRPCIT.java b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/OpenShiftExtensionGRPCIT.java index ec56a549b..42b29d3a1 100644 --- a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/OpenShiftExtensionGRPCIT.java +++ b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/OpenShiftExtensionGRPCIT.java @@ -4,9 +4,9 @@ import org.junit.jupiter.api.Tag; import io.quarkus.test.bootstrap.CloseableManagedChannel; -import io.quarkus.test.bootstrap.RestService; import io.quarkus.test.scenarios.OpenShiftDeploymentStrategy; import io.quarkus.test.scenarios.OpenShiftScenario; +import io.vertx.mutiny.ext.web.client.WebClient; @Tag("use-quarkus-openshift-extension") @OpenShiftScenario(deployment = OpenShiftDeploymentStrategy.UsingOpenShiftExtension) @@ -14,12 +14,12 @@ public class OpenShiftExtensionGRPCIT implements GRPCIT, StreamingHttpIT, ReflectionHttpIT { @Override - public RestService app() { + public CloseableManagedChannel getChannel() { return null; } @Override - public CloseableManagedChannel getChannel() { + public WebClient getWebClient() { return null; } } diff --git a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/OpenShiftGRPCIT.java b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/OpenShiftGRPCIT.java index b6a436f11..5361f5494 100644 --- a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/OpenShiftGRPCIT.java +++ b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/OpenShiftGRPCIT.java @@ -3,20 +3,20 @@ import org.junit.jupiter.api.Disabled; import io.quarkus.test.bootstrap.CloseableManagedChannel; -import io.quarkus.test.bootstrap.RestService; import io.quarkus.test.scenarios.OpenShiftScenario; +import io.vertx.mutiny.ext.web.client.WebClient; @OpenShiftScenario @Disabled("https://github.com/quarkus-qe/quarkus-test-framework/issues/1052+1053") public class OpenShiftGRPCIT implements GRPCIT, StreamingHttpIT, ReflectionHttpIT { @Override - public RestService app() { + public CloseableManagedChannel getChannel() { return null; } @Override - public CloseableManagedChannel getChannel() { + public WebClient getWebClient() { return null; } } diff --git a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/ReflectionHttpIT.java b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/ReflectionHttpIT.java index fd0d12e66..0a59fb21d 100644 --- a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/ReflectionHttpIT.java +++ b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/ReflectionHttpIT.java @@ -1,14 +1,12 @@ package io.quarkus.ts.http.grpc; import static org.apache.http.HttpStatus.SC_OK; -import static org.hamcrest.CoreMatchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; -import org.hamcrest.Matchers; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -16,20 +14,20 @@ import com.google.protobuf.InvalidProtocolBufferException; import io.grpc.reflection.v1.FileDescriptorResponse; -import io.quarkus.test.bootstrap.RestService; import io.quarkus.ts.grpc.GreeterGrpc; import io.quarkus.ts.grpc.HelloWorldProto; import io.quarkus.ts.grpc.StreamingGrpc; +import io.vertx.mutiny.ext.web.client.WebClient; public interface ReflectionHttpIT { - RestService app(); + WebClient getWebClient(); @Test default void testReflectionServices() { - GrpcReflectionResponse response = app().given().when().get("/http/reflection/service/info") - .then().statusCode(SC_OK).extract().response() - .jsonPath().getObject(".", GrpcReflectionResponse.class); + var httpResponse = getWebClient().get("/http/reflection/service/info").sendAndAwait(); + assertEquals(SC_OK, httpResponse.statusCode()); + GrpcReflectionResponse response = httpResponse.bodyAsJson(GrpcReflectionResponse.class); assertEquals(3, response.getServiceCount()); @@ -43,8 +41,9 @@ default void testReflectionServices() { @Test default void testReflectionMethods() throws InvalidProtocolBufferException { - byte[] responseByteArray = app().given().when().get("/http/reflection/descriptor/greeting") - .then().statusCode(SC_OK).extract().body().asByteArray(); + var httpResponse = getWebClient().get("/http/reflection/descriptor/greeting").sendAndAwait(); + assertEquals(SC_OK, httpResponse.statusCode()); + byte[] responseByteArray = httpResponse.body().getBytes(); String fileDescriptor = FileDescriptorResponse.parseFrom(responseByteArray).toString(); @@ -72,8 +71,9 @@ default void testReflectionMethods() throws InvalidProtocolBufferException { @Test @DisplayName("GRPC reflection test - check service messages types") default void testReflectionMessages() throws InvalidProtocolBufferException { - byte[] responseByteArray = app().given().when().get("/http/reflection/descriptor/greeting") - .then().statusCode(SC_OK).extract().body().asByteArray(); + var httpResponse = getWebClient().get("/http/reflection/descriptor/greeting").sendAndAwait(); + assertEquals(SC_OK, httpResponse.statusCode()); + byte[] responseByteArray = httpResponse.body().getBytes(); String fileDescriptor = FileDescriptorResponse.parseFrom(responseByteArray).toString(); var messageTypes = HelloWorldProto.getDescriptor().getMessageTypes(); @@ -87,8 +87,9 @@ default void testReflectionMessages() throws InvalidProtocolBufferException { @Test @DisplayName("GRPC reflection test - check method SayHello of Greeter service exists and then call it") default void testReflectionCallMethod() throws InvalidProtocolBufferException { - byte[] responseByteArray = app().given().when().get("/http/reflection/descriptor/greeting") - .then().statusCode(SC_OK).extract().body().asByteArray(); + var httpResponse = getWebClient().get("/http/reflection/descriptor/greeting").sendAndAwait(); + assertEquals(SC_OK, httpResponse.statusCode()); + byte[] responseByteArray = httpResponse.body().getBytes(); String fileDescriptor = FileDescriptorResponse.parseFrom(responseByteArray).toString(); @@ -111,6 +112,8 @@ default void testReflectionCallMethod() throws InvalidProtocolBufferException { assertTrue(fileDescriptor.contains("SayHello")); // Call sayHello method and compare context - app().given().when().get("/http/tester").then().statusCode(SC_OK).body(Matchers.is("Hello tester")); + httpResponse = getWebClient().get("/http/tester").sendAndAwait(); + assertEquals(SC_OK, httpResponse.statusCode()); + assertEquals("Hello tester", httpResponse.bodyAsString()); } } diff --git a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/SameServerIT.java b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/SameServerIT.java index 58c431039..5766f7b8a 100644 --- a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/SameServerIT.java +++ b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/SameServerIT.java @@ -1,14 +1,18 @@ package io.quarkus.ts.http.grpc; +import org.junit.jupiter.api.AfterAll; + import io.quarkus.test.bootstrap.CloseableManagedChannel; import io.quarkus.test.bootstrap.GrpcService; -import io.quarkus.test.bootstrap.RestService; import io.quarkus.test.scenarios.QuarkusScenario; import io.quarkus.test.services.QuarkusApplication; +import io.vertx.mutiny.ext.web.client.WebClient; @QuarkusScenario public class SameServerIT implements GRPCIT, ReflectionHttpIT, StreamingHttpIT { + private static WebClient webClient = null; + @QuarkusApplication(grpc = true) static final GrpcService app = new GrpcService(); @@ -18,8 +22,17 @@ public CloseableManagedChannel getChannel() { } @Override - public RestService app() { - return app; + public WebClient getWebClient() { + if (webClient == null) { + webClient = app.mutiny(); + } + return webClient; } + @AfterAll + static void afterAll() { + if (webClient != null) { + webClient.close(); + } + } } diff --git a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/SeparateServerIT.java b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/SeparateServerIT.java index f44275503..e9f679b12 100644 --- a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/SeparateServerIT.java +++ b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/SeparateServerIT.java @@ -1,14 +1,18 @@ package io.quarkus.ts.http.grpc; +import org.junit.jupiter.api.AfterAll; + import io.quarkus.test.bootstrap.CloseableManagedChannel; import io.quarkus.test.bootstrap.GrpcService; -import io.quarkus.test.bootstrap.RestService; import io.quarkus.test.scenarios.QuarkusScenario; import io.quarkus.test.services.QuarkusApplication; +import io.vertx.mutiny.ext.web.client.WebClient; @QuarkusScenario public class SeparateServerIT implements GRPCIT, StreamingHttpIT, ReflectionHttpIT { + private static WebClient webClient = null; + @QuarkusApplication(grpc = true) static final GrpcService app = (GrpcService) new GrpcService() .withProperty("quarkus.grpc.server.use-separate-server", "true") @@ -20,8 +24,17 @@ public CloseableManagedChannel getChannel() { } @Override - public RestService app() { - return app; + public WebClient getWebClient() { + if (webClient == null) { + webClient = app.mutiny(); + } + return webClient; } + @AfterAll + static void afterAll() { + if (webClient != null) { + webClient.close(); + } + } } diff --git a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/StreamingHttpIT.java b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/StreamingHttpIT.java index 7019e5d6f..c0832066e 100644 --- a/http/grpc/src/test/java/io/quarkus/ts/http/grpc/StreamingHttpIT.java +++ b/http/grpc/src/test/java/io/quarkus/ts/http/grpc/StreamingHttpIT.java @@ -5,24 +5,18 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import io.quarkus.test.bootstrap.RestService; -import io.restassured.http.ContentType; -import io.restassured.response.Response; -import io.restassured.specification.RequestSpecification; +import io.vertx.core.http.HttpHeaders; +import io.vertx.mutiny.ext.web.client.WebClient; public interface StreamingHttpIT { - RestService app(); - - default RequestSpecification given() { - return app().given(); - } + WebClient getWebClient(); @Test default void serverStreaming() { - Response response = given().when().get("/http/streaming/server/ServerStreaming"); + var response = getWebClient().get("/http/streaming/server/ServerStreaming").sendAndAwait(); Assertions.assertEquals(200, response.statusCode()); - List responses = response.jsonPath().getList("."); + List responses = response.bodyAsJsonArray().getList(); Assertions.assertEquals(GrpcStreamingService.SERVER_STREAM_MESSAGES_COUNT, responses.size()); responses.forEach(message -> Assertions.assertEquals("Hello ServerStreaming", message)); } @@ -30,23 +24,21 @@ default void serverStreaming() { @Test default void clientStreaming() { List names = List.of("Alice", "Bob", "Charlie"); - Response response = given().when() - .contentType(ContentType.JSON) - .body(names) - .post("/http/streaming/client"); + var response = getWebClient().post("/http/streaming/client") + .putHeader(HttpHeaders.CONTENT_TYPE.toString(), "application/json") + .sendJsonAndAwait(names); Assertions.assertEquals(200, response.statusCode()); - Assertions.assertEquals("Total names submitted: " + names.size(), response.body().asString()); + Assertions.assertEquals("Total names submitted: " + names.size(), response.bodyAsString()); } @Test default void bidirectional() { List names = List.of("Alice", "Bob", "Charlie"); - Response response = given().when() - .contentType(ContentType.JSON) - .body(names) - .post("/http/streaming/bi"); + var response = getWebClient().post("/http/streaming/bi") + .putHeader(HttpHeaders.CONTENT_TYPE.toString(), "application/json") + .sendJsonAndAwait(names); Assertions.assertEquals(200, response.statusCode()); - List messages = response.jsonPath().getList("."); + var messages = response.bodyAsJsonArray().getList(); Assertions.assertEquals(names.size() + 1, messages.size()); Assertions.assertEquals("Hello: Alice;Bob;Charlie;", messages.get(names.size())); }