| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 71a073b commit bfb8cec
43 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -57,6 +57,11 @@ updates: | |||
| 57 | 57 | schedule: | |
| 58 | 58 | interval: "monthly" | |
| 59 | 59 | open-pull-requests-limit: 10 | |
| 60 | + - package-ecosystem: "gradle" | ||
| 61 | + directory: "/modules/hivemq" | ||
| 62 | + schedule: | ||
| 63 | + interval: "monthly" | ||
| 64 | + open-pull-requests-limit: 10 | ||
| 60 | 65 | - package-ecosystem: "gradle" | |
| 61 | 66 | directory: "/modules/influxdb" | |
| 62 | 67 | schedule: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,59 @@ | |||
| 1 | + package org.testcontainers.containers.wait.strategy; | ||
| 2 | + | ||
| 3 | + import org.testcontainers.DockerClientFactory; | ||
| 4 | + import org.testcontainers.containers.ContainerLaunchException; | ||
| 5 | + import org.testcontainers.containers.output.OutputFrame; | ||
| 6 | + import org.testcontainers.containers.output.WaitingConsumer; | ||
| 7 | + import org.testcontainers.utility.LogUtils; | ||
| 8 | + | ||
| 9 | + import java.util.Map; | ||
| 10 | + import java.util.concurrent.ConcurrentHashMap; | ||
| 11 | + import java.util.concurrent.TimeUnit; | ||
| 12 | + import java.util.concurrent.TimeoutException; | ||
| 13 | + import java.util.function.Predicate; | ||
| 14 | + | ||
| 15 | + /** | ||
| 16 | + * This is a wait strategy to wait for multiple log patterns. | ||
| 17 | + * The wait strategy will continue when every log pattern is matched at least once. | ||
| 18 | + */ | ||
| 19 | + public class MultiLogMessageWaitStrategy extends AbstractWaitStrategy { | ||
| 20 | + | ||
| 21 | + private final ConcurrentHashMap<String, Boolean> regexes = new ConcurrentHashMap<>(); | ||
| 22 | + | ||
| 23 | + @Override | ||
| 24 | + protected void waitUntilReady() { | ||
| 25 | + WaitingConsumer waitingConsumer = new WaitingConsumer(); | ||
| 26 | + LogUtils.followOutput(DockerClientFactory.instance().client(), waitStrategyTarget.getContainerId(), waitingConsumer); | ||
| 27 | + | ||
| 28 | + Predicate<OutputFrame> waitPredicate = outputFrame -> { | ||
| 29 | + if (regexes.isEmpty()) { | ||
| 30 | + return true; | ||
| 31 | + } | ||
| 32 | + regexes.entrySet().forEach(regexHasMatched -> { | ||
| 33 | + final boolean matched = outputFrame.getUtf8String().matches("(?s)" + regexHasMatched.getKey()); | ||
| 34 | + if (matched) { | ||
| 35 | + regexHasMatched.setValue(true); | ||
| 36 | + } | ||
| 37 | + }); | ||
| 38 | + return regexes.values().stream().reduce(Boolean::logicalAnd).orElse(true); | ||
| 39 | + }; | ||
| 40 | + | ||
| 41 | + try { | ||
| 42 | + waitingConsumer.waitUntil(waitPredicate, startupTimeout.getSeconds(), TimeUnit.SECONDS, 1); | ||
| 43 | + } catch (TimeoutException e) { | ||
| 44 | + throw new ContainerLaunchException("Timed out waiting for log output matching '" + regexes + "'"); | ||
| 45 | + } | ||
| 46 | + } | ||
| 47 | + | ||
| 48 | + public MultiLogMessageWaitStrategy withRegEx(final String regEx) { | ||
| 49 | + regexes.put(regEx, false); | ||
| 50 | + return this; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + public MultiLogMessageWaitStrategy reset() { | ||
| 54 | + for (final Map.Entry<String, Boolean> stringBooleanEntry : regexes.entrySet()) { | ||
| 55 | + stringBooleanEntry.setValue(false); | ||
| 56 | + } | ||
| 57 | + return this; | ||
| 58 | + } | ||
| 59 | + } | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,235 @@ | |||
| 1 | + # HiveMQ Module | ||
| 2 | + | ||
| 3 | + <img src="../modules_logos/hivemq-module.png" alt="drawing" width="800"/> | ||
| 4 | + | ||
| 5 | + Automatic starting HiveMQ docker containers for JUnit4 and JUnit5 tests. | ||
| 6 | + This enables testing MQTT client applications and integration testing of custom HiveMQ extensions. | ||
| 7 | + | ||
| 8 | + - Community forum: https://community.hivemq.com/ | ||
| 9 | + - HiveMQ website: https://www.hivemq.com/ | ||
| 10 | + - MQTT resources: | ||
| 11 | + - [MQTT Essentials](https://www.hivemq.com/mqtt-essentials/) | ||
| 12 | + - [MQTT 5 Essentials](https://www.hivemq.com/mqtt-5/) | ||
| 13 | + | ||
| 14 | + Please make sure to check out the hivemq-docs for the [Community Edition](https://github.com/hivemq/hivemq-community-edition/wiki/) | ||
| 15 | + and the [Enterprise Edition](https://www.hivemq.com/docs/hivemq/4.7/user-guide/). | ||
| 16 | + | ||
| 17 | + ## Using HiveMQ CE/EE | ||
| 18 | + | ||
| 19 | + HiveMQ provides different editions of on [Docker Hub](https://hub.docker.com/u/hivemq): | ||
| 20 | + | ||
| 21 | + - the open source [Community Edition](https://github.com/hivemq/hivemq-community-edition) which | ||
| 22 | + is published as *hivemq/hivemq-ce*. | ||
| 23 | + - the [Enterprise Edition](https://www.hivemq.com/docs/hivemq/4.7/user-guide/) which is published as *hivemq/hivemq4*. | ||
| 24 | + | ||
| 25 | + Both editions can be used directly: | ||
| 26 | + | ||
| 27 | + Using the Community Edition: | ||
| 28 | + <!--codeinclude--> | ||
| 29 | + [Community Edition HiveMQ image](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java) inside_block:ceVersion | ||
| 30 | + <!--/codeinclude--> | ||
| 31 | + | ||
| 32 | + Using the Enterprise Edition: | ||
| 33 | + <!--codeinclude--> | ||
| 34 | + [Enterprise Edition HiveMQ image](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java) inside_block:eeVersion | ||
| 35 | + <!--/codeinclude--> | ||
| 36 | + | ||
| 37 | + Using a specifc version is possible by using the tag: | ||
| 38 | + <!--codeinclude--> | ||
| 39 | + [Specific HiveMQ Version](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java) inside_block:specificVersion | ||
| 40 | + <!--/codeinclude--> | ||
| 41 | + | ||
| 42 | + ## Test your MQTT 3 and MQTT 5 client application | ||
| 43 | + | ||
| 44 | + Using an Mqtt-client (e.g. the [HiveMQ-Mqtt-Client](https://github.com/hivemq/hivemq-mqtt-client)) you can start | ||
| 45 | + testing directly. | ||
| 46 | + | ||
| 47 | + <!--codeinclude--> | ||
| 48 | + [MQTT5 Client](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java) inside_block:mqtt5client | ||
| 49 | + <!--/codeinclude--> | ||
| 50 | + | ||
| 51 | + ## Settings | ||
| 52 | + | ||
| 53 | + There are several things that can be adjusted before container setup. | ||
| 54 | + The following example shows how to enable the Control Center (this is an enterprise feature), set the log level to DEBUG | ||
| 55 | + and load a HiveMQ-config-file from the classpath. | ||
| 56 | + | ||
| 57 | + <!--codeinclude--> | ||
| 58 | + [Config Examples](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java) inside_block:eeVersionWithControlCenter | ||
| 59 | + <!--/codeinclude--> | ||
| 60 | + | ||
| 61 | + --- | ||
| 62 | + **Note:** | ||
| 63 | + The Control Center of HiveMQ can be accessed via the URL presented in the output of the starting container: | ||
| 64 | + | ||
| 65 | + ``` | ||
| 66 | + 2021-09-10 10:35:53,511 INFO - The HiveMQ Control Center is reachable under: http://localhost:55032 | ||
| 67 | + ``` | ||
| 68 | + | ||
| 69 | + Please be aware that the Control Center is a feature of the enterprise edition of HiveMQ and thus only available with | ||
| 70 | + the enterprise image. | ||
| 71 | + | ||
| 72 | + --- | ||
| 73 | + | ||
| 74 | + ## Testing HiveMQ extensions | ||
| 75 | + | ||
| 76 | + Using the [Extension SDK](https://github.com/hivemq/hivemq-extension-sdk) the functionality of all editions of HiveMQ | ||
| 77 | + can be extended. | ||
| 78 | + The HiveMQ module also supports testing your own custom extensions. | ||
| 79 | + | ||
| 80 | + ### Wait Strategy | ||
| 81 | + | ||
| 82 | + The raw HiveMQ module is built to wait for certain startup log messages to signal readiness. | ||
| 83 | + Since extensions are loaded dynamically they can be available a short while after the main container has started. | ||
| 84 | + We therefore provide custom wait conditions for HiveMQ Extensions: | ||
| 85 | + | ||
| 86 | + The following will specify an extension to be loaded from **src/test/resources/modifier-extension** into the container and | ||
| 87 | + wait for an extension named **'My Extension Name'** to be started: | ||
| 88 | + | ||
| 89 | + <!--codeinclude--> | ||
| 90 | + [Custom Wait Strategy](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoExtensionTestsIT.java) inside_block:waitStrategy | ||
| 91 | + <!--/codeinclude--> | ||
| 92 | + | ||
| 93 | + Next up we have an example for using an extension directly from the classpath and waiting directly on the extension: | ||
| 94 | + | ||
| 95 | + <!--codeinclude--> | ||
| 96 | + [Extension from Classpath](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoExtensionTestsIT.java) inside_block:extensionClasspath | ||
| 97 | + <!--/codeinclude--> | ||
| 98 | + | ||
| 99 | + --- | ||
| 100 | + **Note** Debugging extensions | ||
| 101 | + | ||
| 102 | + Both examples contain ```.withDebugging()``` which enables remote debugging on the container. | ||
| 103 | + With debugging enabled you can start putting breakpoints right into your extensions. | ||
| 104 | + | ||
| 105 | + --- | ||
| 106 | + | ||
| 107 | + ### Testing extensions using Gradle | ||
| 108 | + | ||
| 109 | + In a Gradle based HiveMQ Extension project, testing is supported using the dedicated [HiveMQ Extension Gradle Plugin](https://github.com/hivemq/hivemq-extension-gradle-plugin/README.md). | ||
| 110 | + | ||
| 111 | + The plugin adds an `integrationTest` task which executes tests from the `integrationTest` source set. | ||
| 112 | + - Integration test source files are defined in `src/integrationTest`. | ||
| 113 | + - Integration test dependencies are defined via the `integrationTestImplementation`, `integrationTestRuntimeOnly`, etc. configurations. | ||
| 114 | + | ||
| 115 | + The `integrationTest` task builds the extension and unzips it to the `build/hivemq-extension-test` directory. | ||
| 116 | + The tests can then load the built extension into the HiveMQ Testcontainer. | ||
| 117 | + | ||
| 118 | + <!--codeinclude--> | ||
| 119 | + [Extension from filesystem](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:startFromFilesystem | ||
| 120 | + <!--/codeinclude--> | ||
| 121 | + | ||
| 122 | + ### Enable/Disable an extension | ||
| 123 | + | ||
| 124 | + It is possible to enable and disable HiveMQ extensions during runtime. Extensions can also be disabled on startup. | ||
| 125 | + | ||
| 126 | + --- | ||
| 127 | + **Note**: that disabling or enabling of extension during runtime is only supported in HiveMQ 4 Enterprise Edition Containers. | ||
| 128 | + | ||
| 129 | + --- | ||
| 130 | + | ||
| 131 | + The following example shows how to start a HiveMQ container with the extension called **my-extension** being disabled. | ||
| 132 | + | ||
| 133 | + | ||
| 134 | + <!--codeinclude--> | ||
| 135 | + [Disable Extension at startup](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:startDisabled | ||
| 136 | + <!--/codeinclude--> | ||
| 137 | + | ||
| 138 | + The following test then proceeds to enable and then disable the extension: | ||
| 139 | + | ||
| 140 | + <!--codeinclude--> | ||
| 141 | + [Enable/Disable extension at runtime](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:runtimeEnable | ||
| 142 | + <!--/codeinclude--> | ||
| 143 | + | ||
| 144 | + ## Enable/Disable an extension loaded from a folder | ||
| 145 | + | ||
| 146 | + Extensions loaded from an extension folder during runtime can also be enabled/disabled on the fly. | ||
| 147 | + If the extension folder contains a DISABLED file, the extension will be disabled during startup. | ||
| 148 | + | ||
| 149 | + --- | ||
| 150 | + **Note**: that disabling or enabling of extension during runtime is only supported in HiveMQ 4 Enterprise Edition Containers. | ||
| 151 | + | ||
| 152 | + --- | ||
| 153 | + | ||
| 154 | + We first load the extension from the filesytem: | ||
| 155 | + <!--codeinclude--> | ||
| 156 | + [Extension from filesystem](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:startFromFilesystem | ||
| 157 | + <!--/codeinclude--> | ||
| 158 | + | ||
| 159 | + Now we can enable/disable the extension using its name: | ||
| 160 | + | ||
| 161 | + <!--codeinclude--> | ||
| 162 | + [Enable/Disable extension at runtime](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:runtimeEnableFilesystem | ||
| 163 | + <!--/codeinclude--> | ||
| 164 | + | ||
| 165 | + ### Remove prepackaged HiveMQ Extensions | ||
| 166 | + | ||
| 167 | + Since HiveMQ's 4.4 release, HiveMQ Docker images come with the HiveMQ Extension for Kafka, the HiveMQ Enterprise Bridge Extension | ||
| 168 | + and the HiveMQ Enterprise Security Extension. | ||
| 169 | + These Extensions are disabled by default, but sometimes you my need to remove them before the container starts. | ||
| 170 | + | ||
| 171 | + Removing all extension is as simple as: | ||
| 172 | + | ||
| 173 | + <!--codeinclude--> | ||
| 174 | + [Remove all extensions](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:noExtensions | ||
| 175 | + <!--/codeinclude--> | ||
| 176 | + | ||
| 177 | + A single extension (e.g. Kafka) can be removed as easily: | ||
| 178 | + <!--codeinclude--> | ||
| 179 | + [Remove a specific extension](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:noKafkaExtension | ||
| 180 | + <!--/codeinclude--> | ||
| 181 | + | ||
| 182 | + ## Put files into the container | ||
| 183 | + | ||
| 184 | + ### Put a file into HiveMQ home | ||
| 185 | + | ||
| 186 | + <!--codeinclude--> | ||
| 187 | + [Put file into HiveMQ home](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoFilesIT.java) inside_block:hivemqHome | ||
| 188 | + <!--/codeinclude--> | ||
| 189 | + | ||
| 190 | + ### Put files into extension home | ||
| 191 | + | ||
| 192 | + <!--codeinclude--> | ||
| 193 | + [Put file into HiveMQ-Extension home](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoFilesIT.java) inside_block:extensionHome | ||
| 194 | + <!--/codeinclude--> | ||
| 195 | + | ||
| 196 | + ### Put license files into the container | ||
| 197 | + | ||
| 198 | + <!--codeinclude--> | ||
| 199 | + [Put license file into the HiveMQ container](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoFilesIT.java) inside_block:withLicenses | ||
| 200 | + <!--/codeinclude--> | ||
| 201 | + | ||
| 202 | + | ||
| 203 | + ### Customize the Container further | ||
| 204 | + | ||
| 205 | + Since the `HiveMQContainer` extends from [Testcontainer's](https://github.com/testcontainers) `GenericContainer` the container | ||
| 206 | + can be customized as desired. | ||
| 207 | + | ||
| 208 | + ## Add to your project | ||
| 209 | + | ||
| 210 | + ### Gradle | ||
| 211 | + | ||
| 212 | + Add to `build.gradle`: | ||
| 213 | + | ||
| 214 | + ````groovy | ||
| 215 | + testImplementation 'org.testcontainers:hivemq:{{latest_version}}' | ||
| 216 | + ```` | ||
| 217 | + | ||
| 218 | + Add to `build.gradle.kts`: | ||
| 219 | + | ||
| 220 | + ````kotlin | ||
| 221 | + testImplementation("org.testcontainers:hivemq:{{latest_version}}") | ||
| 222 | + ```` | ||
| 223 | + | ||
| 224 | + ### Maven | ||
| 225 | + | ||
| 226 | + Add to `pom.xml`: | ||
| 227 | + | ||
| 228 | + ```xml | ||
| 229 | + <dependency> | ||
| 230 | + <groupId>org.testcontainers</groupId> | ||
| 231 | + <artifactId>hivemq</artifactId> | ||
| 232 | + <version>{{latest_version}}</version> | ||
| 233 | + <scope>test</scope> | ||
| 234 | + </dependency> | ||
| 235 | + ``` | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -67,6 +67,7 @@ nav: | |||
| 67 | 67 | - modules/docker_compose.md | |
| 68 | 68 | - modules/elasticsearch.md | |
| 69 | 69 | - modules/gcloud.md | |
| 70 | + - modules/hivemq.md | ||
| 70 | 71 | - modules/k3s.md | |
| 71 | 72 | - modules/kafka.md | |
| 72 | 73 | - modules/localstack.md | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,37 @@ | |||
| 1 | + description = "TestContainers :: HiveMQ" | ||
| 2 | + | ||
| 3 | + dependencies { | ||
| 4 | + api(project(":testcontainers")) | ||
| 5 | + api("org.jetbrains:annotations:23.0.0") | ||
| 6 | + | ||
| 7 | + shaded("org.apache.commons:commons-lang3:3.12.0") | ||
| 8 | + shaded("commons-io:commons-io:2.11.0") | ||
| 9 | + shaded("org.javassist:javassist:3.28.0-GA") | ||
| 10 | + shaded("org.jboss.shrinkwrap:shrinkwrap-api:1.2.6") | ||
| 11 | + shaded("org.jboss.shrinkwrap:shrinkwrap-impl-base:1.2.6") | ||
| 12 | + shaded("net.lingala.zip4j:zip4j:2.9.1") | ||
| 13 | + | ||
| 14 | + testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2") | ||
| 15 | + testImplementation(project(":junit-jupiter")) | ||
| 16 | + testImplementation("com.hivemq:hivemq-extension-sdk:4.7.3") | ||
| 17 | + testImplementation("com.hivemq:hivemq-mqtt-client:1.3.0") | ||
| 18 | + testImplementation("org.apache.httpcomponents:httpclient:4.5.13") | ||
| 19 | + testImplementation("ch.qos.logback:logback-classic:1.2.10") | ||
| 20 | + testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2") | ||
| 21 | + } | ||
| 22 | + | ||
| 23 | + test { | ||
| 24 | + useJUnitPlatform() | ||
| 25 | + testLogging { | ||
| 26 | + events "passed", "skipped", "failed" | ||
| 27 | + } | ||
| 28 | + javaLauncher = javaToolchains.launcherFor { | ||
| 29 | + languageVersion = JavaLanguageVersion.of(11) | ||
| 30 | + } | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + compileTestJava { | ||
| 34 | + javaCompiler = javaToolchains.compilerFor { | ||
| 35 | + languageVersion = JavaLanguageVersion.of(11) | ||
| 36 | + } | ||
| 37 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments