From 3c955f457e4d0e44c50a7ced81376a27f12df7c8 Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Tue, 12 Nov 2024 13:24:37 +0100 Subject: [PATCH] WebSockets Next: add integration test module - add this module in the native-tests.json config in the HTTP category - fixes #44434 --- .github/native-tests.json | 4 +- integration-tests/pom.xml | 1 + integration-tests/websockets-next/pom.xml | 60 +++++++++++++++++++ .../io/quarkus/websockets/ChatServer.java | 40 +++++++++++++ .../io/quarkus/websockets/ChatClientTest.java | 55 +++++++++++++++++ .../java/io/quarkus/websockets/ChatIT.java | 7 +++ .../java/io/quarkus/websockets/ChatTest.java | 59 ++++++++++++++++++ 7 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 integration-tests/websockets-next/pom.xml create mode 100644 integration-tests/websockets-next/src/main/java/io/quarkus/websockets/ChatServer.java create mode 100644 integration-tests/websockets-next/src/test/java/io/quarkus/websockets/ChatClientTest.java create mode 100644 integration-tests/websockets-next/src/test/java/io/quarkus/websockets/ChatIT.java create mode 100644 integration-tests/websockets-next/src/test/java/io/quarkus/websockets/ChatTest.java diff --git a/.github/native-tests.json b/.github/native-tests.json index f31618bc7b435..87547f9ca469d 100644 --- a/.github/native-tests.json +++ b/.github/native-tests.json @@ -92,8 +92,8 @@ }, { "category": "HTTP", - "timeout": 120, - "test-modules": "elytron-resteasy, resteasy-jackson, elytron-resteasy-reactive, resteasy-mutiny, resteasy-reactive-kotlin/standard, vertx, vertx-http, vertx-web, vertx-http-compressors/all, vertx-http-compressors/some, vertx-web-jackson, vertx-graphql, virtual-http, rest-client, rest-client-reactive, rest-client-reactive-stork, rest-client-reactive-multipart, websockets, management-interface, management-interface-auth, mutiny-native-jctools", + "timeout": 130, + "test-modules": "elytron-resteasy, resteasy-jackson, elytron-resteasy-reactive, resteasy-mutiny, resteasy-reactive-kotlin/standard, vertx, vertx-http, vertx-web, vertx-http-compressors/all, vertx-http-compressors/some, vertx-web-jackson, vertx-graphql, virtual-http, rest-client, rest-client-reactive, rest-client-reactive-stork, rest-client-reactive-multipart, websockets, websockets-next, management-interface, management-interface-auth, mutiny-native-jctools", "os-name": "ubuntu-latest" }, { diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 624ee3141e8db..356cb2336c5c3 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -234,6 +234,7 @@ vertx vertx-kotlin websockets + websockets-next spring-di spring-web spring-data-jpa diff --git a/integration-tests/websockets-next/pom.xml b/integration-tests/websockets-next/pom.xml new file mode 100644 index 0000000000000..ba98a606d088d --- /dev/null +++ b/integration-tests/websockets-next/pom.xml @@ -0,0 +1,60 @@ + + + 4.0.0 + + + quarkus-integration-tests-parent + io.quarkus + 999-SNAPSHOT + + + quarkus-integration-test-websockets-next + Quarkus - Integration Tests - WebSockets Next + + + + io.quarkus + quarkus-websockets-next + + + + io.quarkus + quarkus-junit5 + test + + + + + io.quarkus + quarkus-websockets-next-deployment + ${project.version} + pom + test + + + * + * + + + + + + + + + io.quarkus + quarkus-maven-plugin + + + + build + + + + + + + + diff --git a/integration-tests/websockets-next/src/main/java/io/quarkus/websockets/ChatServer.java b/integration-tests/websockets-next/src/main/java/io/quarkus/websockets/ChatServer.java new file mode 100644 index 0000000000000..8f1422238c081 --- /dev/null +++ b/integration-tests/websockets-next/src/main/java/io/quarkus/websockets/ChatServer.java @@ -0,0 +1,40 @@ +package io.quarkus.websockets; + +import io.quarkus.runtime.annotations.RegisterForReflection; +import io.quarkus.websockets.next.OnClose; +import io.quarkus.websockets.next.OnOpen; +import io.quarkus.websockets.next.OnTextMessage; +import io.quarkus.websockets.next.PathParam; +import io.quarkus.websockets.next.WebSocket; +import io.quarkus.websockets.next.WebSocketConnection; + +@WebSocket(path = "/chat/{username}") +public class ChatServer { + + public enum MessageType { + USER_JOINED, + USER_LEFT, + CHAT_MESSAGE + } + + @RegisterForReflection + public record ChatMessage(MessageType type, String from, String message) { + } + + @OnOpen(broadcast = true) + public ChatMessage onOpen(@PathParam String username) { + return new ChatMessage(MessageType.USER_JOINED, username, "Hello!"); + } + + @OnClose + public void onClose(WebSocketConnection connection) { + connection.broadcast() + .sendTextAndAwait(new ChatMessage(MessageType.USER_LEFT, connection.pathParam("username"), "Bye!")); + } + + @OnTextMessage(broadcast = true) + public ChatMessage onMessage(ChatMessage message) { + return message; + } + +} diff --git a/integration-tests/websockets-next/src/test/java/io/quarkus/websockets/ChatClientTest.java b/integration-tests/websockets-next/src/test/java/io/quarkus/websockets/ChatClientTest.java new file mode 100644 index 0000000000000..25ad7db42401e --- /dev/null +++ b/integration-tests/websockets-next/src/test/java/io/quarkus/websockets/ChatClientTest.java @@ -0,0 +1,55 @@ +package io.quarkus.websockets; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.net.URI; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.TimeUnit; + +import jakarta.inject.Inject; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.websockets.ChatServer.ChatMessage; +import io.quarkus.websockets.ChatServer.MessageType; +import io.quarkus.websockets.next.OnTextMessage; +import io.quarkus.websockets.next.WebSocketClient; +import io.quarkus.websockets.next.WebSocketClientConnection; +import io.quarkus.websockets.next.WebSocketConnector; + +@QuarkusTest +public class ChatClientTest { + + private static final LinkedBlockingDeque MESSAGES = new LinkedBlockingDeque<>(); + + @TestHTTPResource("/") + URI uri; + + @Inject + WebSocketConnector connector; + + @Test + public void testWebsocketChat() throws Exception { + WebSocketClientConnection connection = connector + .baseUri(uri) + .pathParam("username", "Tom") + .connectAndAwait(); + assertEquals(new ChatMessage(MessageType.USER_JOINED, "Tom", "Hello!"), MESSAGES.poll(10, TimeUnit.SECONDS)); + connection.sendTextAndAwait(new ChatMessage(MessageType.CHAT_MESSAGE, "Tom", "Ping")); + assertEquals(new ChatMessage(MessageType.CHAT_MESSAGE, "Tom", "Ping"), MESSAGES.poll(10, TimeUnit.SECONDS)); + connection.closeAndAwait(); + } + + @WebSocketClient(path = "/chat/{username}") + public static class ChatClient { + + @OnTextMessage + void message(ChatMessage message) { + MESSAGES.add(message); + } + + } + +} diff --git a/integration-tests/websockets-next/src/test/java/io/quarkus/websockets/ChatIT.java b/integration-tests/websockets-next/src/test/java/io/quarkus/websockets/ChatIT.java new file mode 100644 index 0000000000000..1f941aae6d66a --- /dev/null +++ b/integration-tests/websockets-next/src/test/java/io/quarkus/websockets/ChatIT.java @@ -0,0 +1,7 @@ +package io.quarkus.websockets; + +import io.quarkus.test.junit.QuarkusIntegrationTest; + +@QuarkusIntegrationTest +public class ChatIT extends ChatTest { +} diff --git a/integration-tests/websockets-next/src/test/java/io/quarkus/websockets/ChatTest.java b/integration-tests/websockets-next/src/test/java/io/quarkus/websockets/ChatTest.java new file mode 100644 index 0000000000000..6b54ad5e705a9 --- /dev/null +++ b/integration-tests/websockets-next/src/test/java/io/quarkus/websockets/ChatTest.java @@ -0,0 +1,59 @@ +package io.quarkus.websockets; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.net.URI; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.common.http.TestHTTPResource; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.websockets.ChatServer.ChatMessage; +import io.quarkus.websockets.ChatServer.MessageType; +import io.vertx.core.Vertx; +import io.vertx.core.http.WebSocketClient; +import io.vertx.core.http.WebSocketConnectOptions; +import io.vertx.core.json.Json; + +@QuarkusTest +public class ChatTest { + + @TestHTTPResource("/chat/Tom") + URI uri; + + @Test + public void testWebsocketChat() throws Exception { + CountDownLatch messageLatch = new CountDownLatch(2); + List messages = new CopyOnWriteArrayList<>(); + Vertx vertx = Vertx.vertx(); + WebSocketClient client = vertx.createWebSocketClient(); + try { + client.connect(new WebSocketConnectOptions() + .setHost(uri.getHost()) + .setPort(uri.getPort()) + .setURI(uri.getPath())) + .onSuccess( + ws -> { + ws.textMessageHandler(m -> { + messages.add(Json.decodeValue(m, ChatMessage.class)); + messageLatch.countDown(); + }); + ws.writeTextMessage(Json.encode(new ChatMessage(MessageType.CHAT_MESSAGE, "Tom", "Ping"))); + }); + assertTrue(messageLatch.await(10, TimeUnit.SECONDS), messageLatch.toString()); + assertEquals(new ChatMessage(MessageType.USER_JOINED, "Tom", "Hello!"), + messages.get(0)); + assertEquals(new ChatMessage(MessageType.CHAT_MESSAGE, "Tom", "Ping"), + messages.get(1)); + } finally { + client.close().toCompletionStage().toCompletableFuture().get(5, TimeUnit.SECONDS); + vertx.close(); + } + } + +}