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 3a76807c1f Added azure-servicebus local testing
3a76807c1f is described below

commit 3a76807c1f706b9d94a6d6f607861cbd49c8c053
Author: Jiri Ondrusek <[email protected]>
AuthorDate: Tue Mar 4 09:38:46 2025 +0100

    Added azure-servicebus local testing
---
 .../azure/azure-servicebus/pom.xml                 |   5 +
 .../src/main/resources/application.properties      |   3 +
 .../azure/servicebus/it/AzureServiceBusIT.java     |   3 -
 .../azure/servicebus/it/AzureServiceBusTest.java   |  26 +++--
 .../support/azure/AzureServiceBusTestResource.java | 120 +++++++++++++++++++++
 .../src/main/resources/servicebus-config.json      |  90 ++++++++++++++++
 .../main/resources/servicebus-docker-compose.yaml  |  46 ++++++++
 pom.xml                                            |   2 +
 8 files changed, 286 insertions(+), 9 deletions(-)

diff --git a/integration-test-groups/azure/azure-servicebus/pom.xml 
b/integration-test-groups/azure/azure-servicebus/pom.xml
index e589fa42bd..71258e692d 100644
--- a/integration-test-groups/azure/azure-servicebus/pom.xml
+++ b/integration-test-groups/azure/azure-servicebus/pom.xml
@@ -72,6 +72,11 @@
             <artifactId>awaitility</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.quarkus</groupId>
+            
<artifactId>camel-quarkus-integration-tests-support-azure</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <profiles>
diff --git 
a/integration-test-groups/azure/azure-servicebus/src/main/resources/application.properties
 
b/integration-test-groups/azure/azure-servicebus/src/main/resources/application.properties
index 03acdfc389..76053671f1 100644
--- 
a/integration-test-groups/azure/azure-servicebus/src/main/resources/application.properties
+++ 
b/integration-test-groups/azure/azure-servicebus/src/main/resources/application.properties
@@ -21,3 +21,6 @@ 
azure.servicebus.topic.subscription.name=${AZURE_SERVICEBUS_TOPIC_SUBSCRIPTION_N
 
 # Avoid autowiring custom ServiceBus clients. They are set explicitly via 
endpoint options
 camel.component.azure-servicebus.autowired-enabled=false
+
+# Uncomment to reduce log noise from com.azure internals
+# quarkus.log.category."com.azure".level = OFF
\ No newline at end of file
diff --git 
a/integration-test-groups/azure/azure-servicebus/src/test/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusIT.java
 
b/integration-test-groups/azure/azure-servicebus/src/test/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusIT.java
index 2bc9aaa435..fc907b1a12 100644
--- 
a/integration-test-groups/azure/azure-servicebus/src/test/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusIT.java
+++ 
b/integration-test-groups/azure/azure-servicebus/src/test/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusIT.java
@@ -17,10 +17,7 @@
 package org.apache.camel.quarkus.component.azure.servicebus.it;
 
 import io.quarkus.test.junit.QuarkusIntegrationTest;
-import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
 
-@EnabledIfEnvironmentVariable(named = "AZURE_SERVICEBUS_CONNECTION_STRING", 
matches = ".+")
-@EnabledIfEnvironmentVariable(named = "AZURE_SERVICEBUS_QUEUE_NAME", matches = 
".+")
 @QuarkusIntegrationTest
 class AzureServiceBusIT extends AzureServiceBusTest {
 }
diff --git 
a/integration-test-groups/azure/azure-servicebus/src/test/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusTest.java
 
b/integration-test-groups/azure/azure-servicebus/src/test/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusTest.java
index 8592476e0f..1634c3deb3 100644
--- 
a/integration-test-groups/azure/azure-servicebus/src/test/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusTest.java
+++ 
b/integration-test-groups/azure/azure-servicebus/src/test/java/org/apache/camel/quarkus/component/azure/servicebus/it/AzureServiceBusTest.java
@@ -29,15 +29,18 @@ import com.azure.core.amqp.AmqpTransportType;
 import com.azure.core.util.BinaryData;
 import com.azure.messaging.servicebus.ServiceBusClientBuilder;
 import com.azure.messaging.servicebus.ServiceBusProcessorClient;
+import io.quarkus.test.common.QuarkusTestResource;
 import io.quarkus.test.junit.QuarkusTest;
 import io.restassured.RestAssured;
 import io.restassured.http.ContentType;
+import org.apache.camel.quarkus.test.EnabledIf;
+import org.apache.camel.quarkus.test.mock.backend.MockBackendDisabled;
+import org.apache.camel.quarkus.test.support.azure.AzureServiceBusTestResource;
 import org.awaitility.Awaitility;
 import org.jboss.logging.Logger;
 import org.junit.jupiter.api.Assumptions;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
@@ -45,9 +48,8 @@ import org.junit.jupiter.params.provider.MethodSource;
 import static org.hamcrest.Matchers.greaterThanOrEqualTo;
 import static org.hamcrest.Matchers.is;
 
-@EnabledIfEnvironmentVariable(named = "AZURE_SERVICEBUS_CONNECTION_STRING", 
matches = ".+")
-@EnabledIfEnvironmentVariable(named = "AZURE_SERVICEBUS_QUEUE_NAME", matches = 
".+")
 @QuarkusTest
+@QuarkusTestResource(AzureServiceBusTestResource.class)
 class AzureServiceBusTest {
     // NOTE: Consumer endpoints are started / stopped manually to prevent them 
from inferring with each other
 
@@ -55,6 +57,11 @@ class AzureServiceBusTest {
 
     @BeforeAll
     public static void beforeAll() {
+        //this is not necessary for mocked testing
+        if (AzureServiceBusHelper.isMockBackEnd()) {
+            return;
+        }
+
         // Drain the test queue in case there are messages lingering from 
previous failed runs
         ServiceBusProcessorClient client = new ServiceBusClientBuilder()
                 .connectionString(AzureServiceBusHelper.getConnectionString())
@@ -135,9 +142,8 @@ class AzureServiceBusTest {
         final List<String> messages = new ArrayList<>();
 
         for (int i = 0; i < 3; i++) {
-            messages.add(UUID.randomUUID().toString());
+            messages.add("cq-azure-servicebus-test-" + 
UUID.randomUUID().toString());
         }
-
         try {
             RestAssured.given()
                     .post("/azure-servicebus/route/" + consumerRouteId + 
"/start")
@@ -213,6 +219,7 @@ class AzureServiceBusTest {
     }
 
     @Test
+    @EnabledIf({ MockBackendDisabled.class }) //only connection string is 
enabled on emulator, see 
https://github.com/Azure/azure-service-bus-emulator-installer/issues/30#issuecomment-2500163047
     void tokenCredentialAuthentication() {
         final String messageBody = UUID.randomUUID().toString();
         try {
@@ -306,6 +313,7 @@ class AzureServiceBusTest {
         }
     }
 
+    @EnabledIf({ MockBackendDisabled.class }) //only connection string is 
enabled on emulator, see 
https://github.com/Azure/azure-service-bus-emulator-installer/issues/30#issuecomment-2500163047
     @Test
     void azureIdentityCredentials() {
         
Assumptions.assumeTrue(AzureServiceBusHelper.isAzureIdentityCredentialsAvailable());
@@ -357,7 +365,13 @@ class AzureServiceBusTest {
 
         String[] payloadTypes = { String.class.getSimpleName(), 
byte[].class.getSimpleName(),
                 BinaryData.class.getSimpleName() };
-        AmqpTransportType[] transportTypes = AmqpTransportType.values();
+        //in mocked backend, the  AMQP_WEB_SOCKET is not supported, see 
https://github.com/Azure/azure-service-bus-emulator-installer/issues/51
+        AmqpTransportType[] transportTypes;
+        if (AzureServiceBusHelper.isMockBackEnd()) {
+            transportTypes = new AmqpTransportType[] { AmqpTransportType.AMQP 
};
+        } else {
+            transportTypes = AmqpTransportType.values();
+        }
         return Stream.of(destinationTypes.split(","))
                 .flatMap(s1 -> Stream.of(transportTypes)
                         .flatMap(s2 -> Stream.of(payloadTypes)
diff --git 
a/integration-tests-support/azure/src/main/java/org/apache/camel/quarkus/test/support/azure/AzureServiceBusTestResource.java
 
b/integration-tests-support/azure/src/main/java/org/apache/camel/quarkus/test/support/azure/AzureServiceBusTestResource.java
new file mode 100644
index 0000000000..68577d6e02
--- /dev/null
+++ 
b/integration-tests-support/azure/src/main/java/org/apache/camel/quarkus/test/support/azure/AzureServiceBusTestResource.java
@@ -0,0 +1,120 @@
+/*
+ * 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.test.support.azure;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import io.quarkus.runtime.LaunchMode;
+import io.quarkus.runtime.configuration.ConfigUtils;
+import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
+import io.smallrye.config.SmallRyeConfig;
+import org.apache.camel.quarkus.test.mock.backend.MockBackendUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testcontainers.containers.ComposeContainer;
+import org.testcontainers.containers.output.Slf4jLogConsumer;
+import org.testcontainers.containers.wait.strategy.Wait;
+
+public class AzureServiceBusTestResource implements 
QuarkusTestResourceLifecycleManager {
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(AzureServiceBusTestResource.class);
+    private static final int SERVICEBUS_INNER_PORT = 5672;
+    private Map<String, String> initArgs = new LinkedHashMap<>();
+    private ComposeContainer container;
+
+    @Override
+    public void init(Map<String, String> initArgs) {
+        this.initArgs = initArgs;
+    }
+
+    @Override
+    public Map<String, String> start() {
+        final SmallRyeConfig config = ConfigUtils.configBuilder(true, 
LaunchMode.NORMAL).build();
+
+        final boolean realCredentialsProvided = 
System.getenv("AZURE_SERVICEBUS_CONNECTION_STRING") != null
+                && System.getenv("AZURE_SERVICEBUS_QUEUE_NAME") != null;
+
+        final boolean startMockBackend = 
MockBackendUtils.startMockBackend(false);
+        final Map<String, String> result = new LinkedHashMap<>();
+        if (startMockBackend && !realCredentialsProvided) {
+            MockBackendUtils.logMockBackendUsed();
+
+            try {
+                //copy docker-compose to tmp location
+                File dockerComposeFile, configFile;
+                try (InputStream inYaml = 
getClass().getClassLoader().getResourceAsStream("servicebus-docker-compose.yaml");
+                        InputStream inJson = 
getClass().getClassLoader().getResourceAsStream("servicebus-config.json")) {
+                    dockerComposeFile = 
File.createTempFile("servicebus-docker-compose-", ".yaml");
+                    configFile = File.createTempFile("servicebus-config-", 
".json");
+                    Files.copy(inYaml, dockerComposeFile.toPath(), 
StandardCopyOption.REPLACE_EXISTING);
+                    Files.copy(inJson, configFile.toPath(), 
StandardCopyOption.REPLACE_EXISTING);
+                }
+
+                container = new ComposeContainer(dockerComposeFile)
+                        .withEnv("ACCEPT_EULA", "Y")
+                        .withEnv("SERVICEBUS_EMULATOR_IMAGE",
+                                
config.getValue("servicebus-emulator.container.image", String.class))
+                        .withEnv("SQL_EDGE_IMAGE", 
config.getValue("azure-sql-edge.container.image", String.class))
+                        .withEnv("CONFIG_FILE", configFile.getAbsolutePath())
+                        .withEnv("MSSQL_SA_PASSWORD", "12345678923456y!43")
+                        .withExposedService("emulator", SERVICEBUS_INNER_PORT)
+                        .withLocalCompose(true)
+                        .withLogConsumer("emulator", new 
Slf4jLogConsumer(LOGGER))
+                        .waitingFor("emulator", Wait.forLogMessage(".*Emulator 
Service is Successfully Up!.*", 1));
+
+                container.start();
+
+                String connectionString = 
"Endpoint=sb://%s:%d;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=SAS_KEY_VALUE;UseDevelopmentEmulator=true;"
+                        .formatted(container.getServiceHost("emulator", 
SERVICEBUS_INNER_PORT),
+                                container.getServicePort("emulator", 
SERVICEBUS_INNER_PORT));
+                result.put("azure.servicebus.connection.string", 
connectionString);
+                result.put("azure.servicebus.queue.name", "queue.1");
+                result.put("azure.servicebus.topic.name", "topic.1");
+                result.put("azure.servicebus.topic.subscription.name", 
"subscription.1");
+
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        } else {
+            if (!startMockBackend && !realCredentialsProvided) {
+                throw new IllegalStateException(
+                        "Set AZURE_SERVICEBUS_CONNECTION_STRING and 
AZURE_SERVICEBUS_QUEUE_NAME env vars if you set 
CAMEL_QUARKUS_START_MOCK_BACKEND=false");
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public void stop() {
+        try {
+
+            if (container != null) {
+                container.stop();
+            }
+
+        } catch (Exception e) {
+            // ignored
+        }
+    }
+
+}
diff --git 
a/integration-tests-support/azure/src/main/resources/servicebus-config.json 
b/integration-tests-support/azure/src/main/resources/servicebus-config.json
new file mode 100644
index 0000000000..bdc25570d0
--- /dev/null
+++ b/integration-tests-support/azure/src/main/resources/servicebus-config.json
@@ -0,0 +1,90 @@
+{
+  "UserConfig": {
+    "Namespaces": [
+      {
+        "Name": "sbemulatorns",
+        "Queues": [
+          {
+            "Name": "queue.1",
+            "Properties": {
+              "DeadLetteringOnMessageExpiration": false,
+              "DefaultMessageTimeToLive": "PT1H",
+              "DuplicateDetectionHistoryTimeWindow": "PT20S",
+              "ForwardDeadLetteredMessagesTo": "",
+              "ForwardTo": "",
+              "LockDuration": "PT1M",
+              "MaxDeliveryCount": 10,
+              "RequiresDuplicateDetection": false,
+              "RequiresSession": false
+            }
+          }
+        ],
+
+        "Topics": [
+          {
+            "Name": "topic.1",
+            "Properties": {
+              "DefaultMessageTimeToLive": "PT1H",
+              "DuplicateDetectionHistoryTimeWindow": "PT20S",
+              "RequiresDuplicateDetection": false
+            },
+            "Subscriptions": [
+              {
+                "Name": "subscription.1",
+                "Properties": {
+                  "DeadLetteringOnMessageExpiration": false,
+                  "DefaultMessageTimeToLive": "PT1H",
+                  "LockDuration": "PT1M",
+                  "MaxDeliveryCount": 10,
+                  "ForwardDeadLetteredMessagesTo": "",
+                  "ForwardTo": "",
+                  "RequiresSession": false
+                }
+              },
+              {
+                "Name": "subscription.2",
+                "Properties": {
+                  "DeadLetteringOnMessageExpiration": false,
+                  "DefaultMessageTimeToLive": "PT1H",
+                  "LockDuration": "PT1M",
+                  "MaxDeliveryCount": 10,
+                  "ForwardDeadLetteredMessagesTo": "",
+                  "ForwardTo": "",
+                  "RequiresSession": false
+                },
+                "Rules": [
+                  {
+                    "Name": "user-prop-filter-1",
+                    "Properties": {
+                      "FilterType": "Correlation",
+                      "CorrelationFilter": {
+                        "Properties": {
+                          "prop3": "value3"
+                        }
+                      }
+                    }
+                  }
+                ]
+              },
+              {
+                "Name": "subscription.3",
+                "Properties": {
+                  "DeadLetteringOnMessageExpiration": false,
+                  "DefaultMessageTimeToLive": "PT1H",
+                  "LockDuration": "PT1M",
+                  "MaxDeliveryCount": 10,
+                  "ForwardDeadLetteredMessagesTo": "",
+                  "ForwardTo": "",
+                  "RequiresSession": false
+                }
+              }
+            ]
+          }
+        ]
+      }
+    ],
+    "Logging": {
+      "Type": "File"
+    }
+  }
+}
\ No newline at end of file
diff --git 
a/integration-tests-support/azure/src/main/resources/servicebus-docker-compose.yaml
 
b/integration-tests-support/azure/src/main/resources/servicebus-docker-compose.yaml
new file mode 100644
index 0000000000..4df541a4f7
--- /dev/null
+++ 
b/integration-tests-support/azure/src/main/resources/servicebus-docker-compose.yaml
@@ -0,0 +1,46 @@
+#
+# 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.
+#
+
+name: microsoft-azure-servicebus-emulator
+services:
+  emulator:
+    image: "${SERVICEBUS_EMULATOR_IMAGE}"
+    volumes:
+      - "${CONFIG_FILE}:/ServiceBus_Emulator/ConfigFiles/Config.json"
+    ports:
+      - 0:5672
+    environment:
+      SQL_SERVER: sqledge
+      MSSQL_SA_PASSWORD: ${MSSQL_SA_PASSWORD}
+      ACCEPT_EULA: ${ACCEPT_EULA}
+    depends_on:
+      - sqledge
+    networks:
+      sb-emulator:
+        aliases:
+          - "sb-emulator"
+  sqledge:
+    image: "${SQL_EDGE_IMAGE}"
+    networks:
+      sb-emulator:
+        aliases:
+          - "sqledge"
+    environment:
+      ACCEPT_EULA: ${ACCEPT_EULA}
+      MSSQL_SA_PASSWORD: ${MSSQL_SA_PASSWORD}
+networks:
+  sb-emulator:
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 913ac69878..d97274793a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -221,6 +221,7 @@
         <!-- Test container image properties -->
         
<activemq.container.image>mirror.gcr.io/rmohr/activemq:5.15.9-alpine</activemq.container.image>
         
<arangodb.container.image>mirror.gcr.io/arangodb:3.12.0</arangodb.container.image>
+        
<azure-sql-edge.container.image>mcr.microsoft.com/azure-sql-edge:latest</azure-sql-edge.container.image>
         
<azurite.container.image>mcr.microsoft.com/azure-storage/azurite:3.33.0</azurite.container.image>
         
<calculator-ws.container.image>quay.io/l2x6/calculator-ws:1.2</calculator-ws.container.image>
         
<cassandra.container.image>mirror.gcr.io/cassandra:5.0.2</cassandra.container.image>
@@ -254,6 +255,7 @@
         
<qdrant.container.image>mirror.gcr.io/qdrant/qdrant:v1.9.7-unprivileged</qdrant.container.image>
         
<rabbitmq.container.image>mirror.gcr.io/rabbitmq:3.13.7-management-alpine</rabbitmq.container.image>
         
<redis.container.image>mirror.gcr.io/redis:6.2.14-alpine</redis.container.image>
+        
<servicebus-emulator.container.image>mcr.microsoft.com/azure-messaging/servicebus-emulator:latest</servicebus-emulator.container.image>
         
<smb.container.image>quay.io/jamesnetherton/camel-smb-test-server:1.0.0</smb.container.image>
         
<solr.container.image>mirror.gcr.io/solr:9.8.0-slim</solr.container.image>
         
<splunk.container.image>mirror.gcr.io/splunk/splunk:9.3.1</splunk.container.image>

Reply via email to