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

jamesnetherton 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 bbe10ba1e7 Add Qdrant exception and auth tests
bbe10ba1e7 is described below

commit bbe10ba1e78203bd6c7e0cac7bcb06efcfabf34c
Author: Lukas Lowinger <[email protected]>
AuthorDate: Tue Mar 3 08:05:37 2026 +0100

    Add Qdrant exception and auth tests
---
 .../component/qdrant/it/QdrantResource.java        | 121 +++++++++++++++++++++
 ...source.java => AbstractQdrantTestResource.java} |  24 +++-
 .../quarkus/component/qdrant/it/QdrantAuthIT.java  |  24 ++++
 .../component/qdrant/it/QdrantAuthTest.java        |  48 ++++++++
 .../component/qdrant/it/QdrantAuthTestProfile.java |  29 +++++
 .../qdrant/it/QdrantAuthTestResource.java          |  26 +++++
 .../quarkus/component/qdrant/it/QdrantTest.java    |  31 ++++++
 .../component/qdrant/it/QdrantTestResource.java    |  50 +--------
 8 files changed, 303 insertions(+), 50 deletions(-)

diff --git 
a/integration-tests/qdrant/src/main/java/org/apache/camel/quarkus/component/qdrant/it/QdrantResource.java
 
b/integration-tests/qdrant/src/main/java/org/apache/camel/quarkus/component/qdrant/it/QdrantResource.java
index ad8f1f9a29..e7199878a9 100644
--- 
a/integration-tests/qdrant/src/main/java/org/apache/camel/quarkus/component/qdrant/it/QdrantResource.java
+++ 
b/integration-tests/qdrant/src/main/java/org/apache/camel/quarkus/component/qdrant/it/QdrantResource.java
@@ -185,4 +185,125 @@ public class QdrantResource {
 
         return Response.ok(operationId + "/" + opeartionStatus + "/" + 
operationValue).build();
     }
+
+    @Path("/exception/nonExistentCollection")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response retrieveFromNonExistentCollection() {
+        // Try to retrieve from a collection that doesn't exist
+        // This should trigger QdrantException
+        Exchange exchange = producer.to("qdrant:nonExistentCollection")
+                .withHeader(QdrantHeaders.ACTION, QdrantAction.RETRIEVE)
+                .withBody(PointIdFactory.id(1))
+                .request(Exchange.class);
+
+        if (exchange.isFailed() && exchange.getException() != null) {
+            Exception exception = exchange.getException();
+            return Response.status(500)
+                    .entity("QdrantException: " + exception.getMessage())
+                    .build();
+        }
+        return Response.ok("Should not reach here").build();
+    }
+
+    @Path("/exception/invalidOperation")
+    @PUT
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response invalidCollectionOperation() {
+        // Try to create collection with invalid parameters
+        // This should trigger QdrantException
+        Exchange exchange = producer.to("qdrant:testCollection")
+                .withHeader(QdrantHeaders.ACTION, 
QdrantAction.CREATE_COLLECTION)
+                .withBody(
+                        Collections.VectorParams.newBuilder()
+                                .setSize(0) // Invalid size
+                                
.setDistance(Collections.Distance.Cosine).build())
+                .request(Exchange.class);
+
+        if (exchange.isFailed() && exchange.getException() != null) {
+            Exception exception = exchange.getException();
+            return Response.status(500)
+                    .entity("QdrantException: " + exception.getMessage())
+                    .build();
+        }
+        return Response.ok("Should not reach here").build();
+    }
+
+    @Path("/exception/withMessage")
+    @GET
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response exceptionWithMessage() {
+        // Verify that exception messages are properly preserved
+        Exchange exchange = producer.to("qdrant:nonExistentTestCollection")
+                .withHeader(QdrantHeaders.ACTION, QdrantAction.DELETE)
+                .withBody(Common.Filter.newBuilder()
+                        .addMust(matchKeyword("test", "value"))
+                        .build())
+                .request(Exchange.class);
+
+        if (exchange.isFailed() && exchange.getException() != null) {
+            Exception exception = exchange.getException();
+            return Response.status(500)
+                    .entity("QdrantException: Test exception message - " + 
exception.getMessage())
+                    .build();
+        }
+        return Response.ok("Should not reach here").build();
+    }
+
+    @Path("/apiKey/valid")
+    @PUT
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response testWithValidApiKey() {
+        // The component is already configured with correct API key in 
QdrantAuthTestResource
+        producer.to("qdrant:authTestCollection")
+                .withHeader(QdrantHeaders.ACTION, 
QdrantAction.CREATE_COLLECTION)
+                .withBody(
+                        Collections.VectorParams.newBuilder()
+                                .setSize(2)
+                                
.setDistance(Collections.Distance.Cosine).build())
+                .request();
+
+        return Response.ok("ApiKeyCredentials reflection works: authentication 
successful").build();
+    }
+
+    @Path("/apiKey/invalid")
+    @PUT
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response testWithInvalidApiKey() {
+        // Test that wrong API key is rejected
+        // Use endpoint URI with explicit wrong API key to override component 
configuration
+        try {
+            producer.to("qdrant:authTestCollection2?apiKey=wrong-api-key")
+                    .withHeader(QdrantHeaders.ACTION, 
QdrantAction.CREATE_COLLECTION)
+                    .withBody(
+                            Collections.VectorParams.newBuilder()
+                                    .setSize(2)
+                                    
.setDistance(Collections.Distance.Cosine).build())
+                    .request();
+
+            return Response.status(500)
+                    .entity("Authentication should have failed but succeeded!")
+                    .build();
+        } catch (Exception e) {
+            // Expected to fail on authentication
+            if (exceptionChainContains(e, "UNAUTHENTICATED") || 
exceptionChainContains(e, "PERMISSION_DENIED")) {
+                return Response.status(403).entity("Authentication correctly 
failed").build();
+            }
+            return Response.status(500)
+                    .entity("Unexpected error: " + e.getMessage())
+                    .build();
+        }
+    }
+
+    private boolean exceptionChainContains(Throwable e, String searchTerm) {
+        Throwable current = e;
+        while (current != null) {
+            String message = current.getMessage();
+            if (message != null && 
message.toLowerCase().contains(searchTerm.toLowerCase())) {
+                return true;
+            }
+            current = current.getCause();
+        }
+        return false;
+    }
 }
diff --git 
a/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantTestResource.java
 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/AbstractQdrantTestResource.java
similarity index 74%
copy from 
integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantTestResource.java
copy to 
integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/AbstractQdrantTestResource.java
index a01d8115bd..24e4e0e916 100644
--- 
a/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantTestResource.java
+++ 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/AbstractQdrantTestResource.java
@@ -28,21 +28,34 @@ import 
org.testcontainers.containers.output.Slf4jLogConsumer;
 import org.testcontainers.qdrant.QdrantContainer;
 import org.testcontainers.utility.DockerImageName;
 
-public class QdrantTestResource implements QuarkusTestResourceLifecycleManager 
{
+abstract class AbstractQdrantTestResource implements 
QuarkusTestResourceLifecycleManager {
 
-    private static final Logger LOG = 
LoggerFactory.getLogger(QdrantTestResource.class);
+    private static final Logger LOG = 
LoggerFactory.getLogger(AbstractQdrantTestResource.class);
     private static final String QDRANT_IMAGE = 
ConfigProvider.getConfig().getValue("qdrant.container.image", String.class);
     private static final int QDRANT_GRPC_PORT = 6334;
+    protected static final String QDRANT_API_KEY = "test-secret-api-key";
 
     private GenericContainer<?> qdrantContainer;
 
+    /**
+     * Override this method to enable API key authentication
+     */
+    protected abstract boolean isAuthEnabled();
+
     @Override
     public Map<String, String> start() {
         Map<String, String> properties = new HashMap<>();
 
         DockerImageName qdrantImageName = 
DockerImageName.parse(QDRANT_IMAGE).asCompatibleSubstituteFor("qdrant/qdrant");
-        qdrantContainer = new QdrantContainer(qdrantImageName)
+        QdrantContainer container = new QdrantContainer(qdrantImageName)
                 .withLogConsumer(new Slf4jLogConsumer(LOG));
+
+        // Configure authentication if enabled
+        if (isAuthEnabled()) {
+            container.withEnv("QDRANT__SERVICE__API_KEY", QDRANT_API_KEY);
+        }
+
+        qdrantContainer = container;
         qdrantContainer.start();
 
         String grpcHost = qdrantContainer.getHost();
@@ -51,6 +64,11 @@ public class QdrantTestResource implements 
QuarkusTestResourceLifecycleManager {
         properties.put("camel.component.qdrant.host", grpcHost);
         properties.put("camel.component.qdrant.port", grpcPort.toString());
 
+        // Add API key property if authentication is enabled
+        if (isAuthEnabled()) {
+            properties.put("camel.component.qdrant.api-key", QDRANT_API_KEY);
+        }
+
         LOG.info("Properties: {}", properties);
 
         return properties;
diff --git 
a/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantAuthIT.java
 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantAuthIT.java
new file mode 100644
index 0000000000..e9898b659e
--- /dev/null
+++ 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantAuthIT.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.qdrant.it;
+
+import io.quarkus.test.junit.QuarkusIntegrationTest;
+
+@QuarkusIntegrationTest
+class QdrantAuthIT extends QdrantAuthTest {
+
+}
diff --git 
a/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantAuthTest.java
 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantAuthTest.java
new file mode 100644
index 0000000000..389c12013d
--- /dev/null
+++ 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantAuthTest.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.qdrant.it;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.quarkus.test.junit.TestProfile;
+import io.restassured.RestAssured;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.Matchers.containsString;
+
+@QuarkusTest
+@TestProfile(QdrantAuthTestProfile.class)
+class QdrantAuthTest {
+
+    @Test
+    void apiKeyAuthenticationShouldWork() {
+        // This test runs with QdrantAuthTestProfile which configures the 
component with API key
+        RestAssured.put("/qdrant/apiKey/valid")
+                .then()
+                .statusCode(200)
+                .body(containsString("ApiKeyCredentials reflection works"));
+    }
+
+    @Test
+    void invalidApiKeyShouldBeRejected() {
+        // Verify that authentication is actually enforced with wrong API key
+        RestAssured.put("/qdrant/apiKey/invalid")
+                .then()
+                .statusCode(403)
+                .body(containsString("Authentication correctly failed"));
+    }
+
+}
diff --git 
a/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantAuthTestProfile.java
 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantAuthTestProfile.java
new file mode 100644
index 0000000000..8c1cf4dd15
--- /dev/null
+++ 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantAuthTestProfile.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.qdrant.it;
+
+import java.util.List;
+
+import io.quarkus.test.junit.QuarkusTestProfile;
+
+public class QdrantAuthTestProfile implements QuarkusTestProfile {
+
+    @Override
+    public List<TestResourceEntry> testResources() {
+        return List.of(new TestResourceEntry(QdrantAuthTestResource.class));
+    }
+}
diff --git 
a/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantAuthTestResource.java
 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantAuthTestResource.java
new file mode 100644
index 0000000000..d1199df8cd
--- /dev/null
+++ 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantAuthTestResource.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.qdrant.it;
+
+public class QdrantAuthTestResource extends AbstractQdrantTestResource {
+
+    @Override
+    protected boolean isAuthEnabled() {
+        return true;
+    }
+
+}
diff --git 
a/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantTest.java
 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantTest.java
index 6862bf28e4..6c106293d4 100644
--- 
a/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantTest.java
+++ 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantTest.java
@@ -21,6 +21,7 @@ import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
 import org.junit.jupiter.api.Test;
 
+import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.is;
 
 @QuarkusTestResource(QdrantTestResource.class)
@@ -63,4 +64,34 @@ class QdrantTest {
                 .body(is("0/"));
     }
 
+    @Test
+    void operationOnNonExistentCollectionShouldThrowException() {
+        // Try to retrieve from a collection that doesn't exist
+        // This should trigger QdrantException from the qdrant client
+        RestAssured.get("/qdrant/exception/nonExistentCollection")
+                .then()
+                .statusCode(500)
+                .body(containsString("QdrantException"));
+    }
+
+    @Test
+    void invalidCollectionOperationShouldThrowException() {
+        // Try to perform an invalid operation
+        // This should trigger QdrantException with a descriptive message
+        RestAssured.put("/qdrant/exception/invalidOperation")
+                .then()
+                .statusCode(500)
+                .body(containsString("QdrantException"));
+    }
+
+    @Test
+    void exceptionMessageShouldBePreserved() {
+        // Verify that exception messages are properly preserved
+        // This is important for native reflection support
+        RestAssured.get("/qdrant/exception/withMessage")
+                .then()
+                .statusCode(500)
+                .body(containsString("Test exception message"));
+    }
+
 }
diff --git 
a/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantTestResource.java
 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantTestResource.java
index a01d8115bd..fb7e6a0407 100644
--- 
a/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantTestResource.java
+++ 
b/integration-tests/qdrant/src/test/java/org/apache/camel/quarkus/component/qdrant/it/QdrantTestResource.java
@@ -16,55 +16,11 @@
  */
 package org.apache.camel.quarkus.component.qdrant.it;
 
-import java.util.HashMap;
-import java.util.Map;
-
-import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
-import org.eclipse.microprofile.config.ConfigProvider;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.testcontainers.containers.GenericContainer;
-import org.testcontainers.containers.output.Slf4jLogConsumer;
-import org.testcontainers.qdrant.QdrantContainer;
-import org.testcontainers.utility.DockerImageName;
-
-public class QdrantTestResource implements QuarkusTestResourceLifecycleManager 
{
-
-    private static final Logger LOG = 
LoggerFactory.getLogger(QdrantTestResource.class);
-    private static final String QDRANT_IMAGE = 
ConfigProvider.getConfig().getValue("qdrant.container.image", String.class);
-    private static final int QDRANT_GRPC_PORT = 6334;
-
-    private GenericContainer<?> qdrantContainer;
-
-    @Override
-    public Map<String, String> start() {
-        Map<String, String> properties = new HashMap<>();
-
-        DockerImageName qdrantImageName = 
DockerImageName.parse(QDRANT_IMAGE).asCompatibleSubstituteFor("qdrant/qdrant");
-        qdrantContainer = new QdrantContainer(qdrantImageName)
-                .withLogConsumer(new Slf4jLogConsumer(LOG));
-        qdrantContainer.start();
-
-        String grpcHost = qdrantContainer.getHost();
-        Integer grpcPort = qdrantContainer.getMappedPort(QDRANT_GRPC_PORT);
-
-        properties.put("camel.component.qdrant.host", grpcHost);
-        properties.put("camel.component.qdrant.port", grpcPort.toString());
-
-        LOG.info("Properties: {}", properties);
-
-        return properties;
-    }
+public class QdrantTestResource extends AbstractQdrantTestResource {
 
     @Override
-    public void stop() {
-        try {
-            if (qdrantContainer != null) {
-                qdrantContainer.stop();
-            }
-        } catch (Exception ex) {
-            LOG.error("An issue occurred while stopping Qdrant container", ex);
-        }
+    protected boolean isAuthEnabled() {
+        return false;
     }
 
 }

Reply via email to