You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2026/10/04 16:19:38 UTC

(karaf) branch main updated: Fix flaky GraphQLExampleTest (#2976)

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

jbonofre pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/karaf.git


The following commit(s) were added to refs/heads/main by this push:
     new 383adcba3a Fix flaky GraphQLExampleTest (#2976)
383adcba3a is described below

commit 383adcba3a1c4ed1eb5bb4bd15e9682c5ce320e0
Author: JB Onofré <jb...@apache.org>
AuthorDate: Sun Oct 4 18:19:31 2026 +0200

    Fix flaky GraphQLExampleTest (#2976)
---
 .../karaf/itests/examples/GraphQLExampleTest.java  | 42 +++++++++++++++-------
 .../org/apache/karaf/itests/util/SimpleSocket.java | 11 ++++--
 2 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/itests/test/src/test/java/org/apache/karaf/itests/examples/GraphQLExampleTest.java b/itests/test/src/test/java/org/apache/karaf/itests/examples/GraphQLExampleTest.java
index e6c66c5996..69c5eefb60 100644
--- a/itests/test/src/test/java/org/apache/karaf/itests/examples/GraphQLExampleTest.java
+++ b/itests/test/src/test/java/org/apache/karaf/itests/examples/GraphQLExampleTest.java
@@ -17,6 +17,7 @@ import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.apache.karaf.itests.BaseTest;
 import org.apache.karaf.itests.util.SimpleSocket;
+import org.awaitility.Awaitility;
 import org.eclipse.jetty.websocket.client.WebSocketClient;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -46,9 +47,19 @@ public class GraphQLExampleTest extends BaseTest {
         installAndAssertFeature("karaf-graphql-example");
     }
 
+    // the HTTP service starts and registers the servlets asynchronously
+    private void awaitServlet(String path) {
+        Awaitility.await("servlet " + path).atMost(30, TimeUnit.SECONDS).ignoreExceptions().until(() -> {
+            URL url = new URL("http://localhost:" + getHttpPort() + path);
+            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+            return connection.getResponseCode() != HttpURLConnection.HTTP_NOT_FOUND;
+        });
+    }
+
     @Test
     public void testServlet() throws Exception {
         setUp();
+        awaitServlet("/graphql");
 
         String getBooksQuery = "{ books { name id } }";
         String booksRequestResult = sendGetRequest(getBooksQuery);
@@ -80,22 +91,29 @@ public class GraphQLExampleTest extends BaseTest {
     @Test
     public void testWebSocket() throws Exception {
         setUp();
+        awaitServlet("/graphql");
 
         WebSocketClient client = new WebSocketClient();
         SimpleSocket socket = new SimpleSocket();
         client.start();
-        URI uri = new URI("ws://localhost:" + getHttpPort() + "/graphql-websocket");
-        client.connect(socket, uri).get(10, TimeUnit.SECONDS);
-
-        sendPostRequest("mutation { addBook(name:\"Lord of the Rings\" pageCount:100) { id name } }");
-
-        Thread.sleep(3000);
-
-        assertTrue(socket.messages.size() > 0);
-
-        assertContains("Lord of the Rings", socket.messages.get(0));
-
-        client.stop();
+        try {
+            URI uri = new URI("ws://localhost:" + getHttpPort() + "/graphql-websocket");
+            client.connect(socket, uri).get(10, TimeUnit.SECONDS);
+
+            // the server subscribes to the book feed once the websocket is opened, and a book added
+            // before that is not published to this client, so add books until one is received
+            boolean received = false;
+            for (int i = 0; !received && i < 30; i++) {
+                sendPostRequest("mutation { addBook(name:\"Lord of the Rings\" pageCount:100) { id name } }");
+                received = socket.awaitMessage(1, TimeUnit.SECONDS);
+            }
+
+            assertTrue(received);
+
+            assertContains("Lord of the Rings", socket.messages.get(0));
+        } finally {
+            client.stop();
+        }
     }
 
     private String sendGetRequest(String query) throws Exception {
diff --git a/itests/test/src/test/java/org/apache/karaf/itests/util/SimpleSocket.java b/itests/test/src/test/java/org/apache/karaf/itests/util/SimpleSocket.java
index 11c6e589ea..35273f41d4 100644
--- a/itests/test/src/test/java/org/apache/karaf/itests/util/SimpleSocket.java
+++ b/itests/test/src/test/java/org/apache/karaf/itests/util/SimpleSocket.java
@@ -24,8 +24,8 @@ import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen;
 import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
 import org.eclipse.jetty.websocket.api.annotations.WebSocket;
 
-import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -34,17 +34,23 @@ public class SimpleSocket {
 
     public final List<String> messages;
     private final CountDownLatch closeLatch;
+    private final CountDownLatch messageLatch;
     private Session session;
 
     public SimpleSocket() {
-        this.messages = new ArrayList<>();
+        this.messages = new CopyOnWriteArrayList<>();
         this.closeLatch = new CountDownLatch(1);
+        this.messageLatch = new CountDownLatch(1);
     }
 
     public boolean awaitClose(int duration, TimeUnit unit) throws InterruptedException {
         return this.closeLatch.await(duration, unit);
     }
 
+    public boolean awaitMessage(int duration, TimeUnit unit) throws InterruptedException {
+        return this.messageLatch.await(duration, unit);
+    }
+
     @OnWebSocketClose
     public void onClose(int statusCode, String reason) {
         System.out.println("Closing websocket client");
@@ -63,5 +69,6 @@ public class SimpleSocket {
     public void onMessage(String msg) {
         System.out.println("Received websocket message: " + msg);
         messages.add(msg);
+        this.messageLatch.countDown();
     }
 }