Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HiveMQ docs tests on CI #5055

Closed
wants to merge 62 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
75118cb
moved hivemq testcontainer to testcontainers-java
YannickWeber Nov 23, 2021
b688e40
updated licensing
YannickWeber Nov 29, 2021
1bd680b
added license exclusions to build.gradle.kts
YannickWeber Nov 29, 2021
2302264
fixed build.gradle.kts
YannickWeber Nov 29, 2021
414591b
removed unnecessary schema declarations
YannickWeber Nov 29, 2021
6fa8d77
added constants for default images and added them to test
YannickWeber Nov 29, 2021
805bdae
improved constants
YannickWeber Nov 29, 2021
e32f48e
using in memory persistence for ITs
YannickWeber Nov 29, 2021
fb8cdfd
updated license header
YannickWeber Nov 29, 2021
72fbd88
First iteration of public docs
codepitbull Dec 15, 2021
b1cf349
Fix groupId
codepitbull Dec 15, 2021
8c1af50
Apply suggestions from code review
codepitbull Dec 15, 2021
829cadb
Removed leftover license info
codepitbull Dec 15, 2021
39e5f18
Update docs/modules/hviemq.md
codepitbull Dec 15, 2021
240fb69
Working recommendations in
codepitbull Dec 15, 2021
cd3c328
renamed hviemq to hivemq
YannickWeber Dec 21, 2021
322337a
removed hivemq-extension-sdk compile-dependency
YannickWeber Dec 22, 2021
54c14a9
removed license headers
YannickWeber Dec 22, 2021
16eabb0
removed link in javadoc because ExtensionMain is not on the classpath…
YannickWeber Dec 23, 2021
cc3fb94
removed guava dependency
YannickWeber Dec 23, 2021
b795bb9
improved gradle.properties
YannickWeber Dec 23, 2021
d450ea1
implementation -> shaded
YannickWeber Dec 23, 2021
a7cc93e
moved versions to build.gradle.kts
YannickWeber Jan 5, 2022
a73f5f0
removed unnecessary header
YannickWeber Jan 5, 2022
61375b7
added new buildscript
YannickWeber Jan 10, 2022
3d1627e
removed settings.gradle
YannickWeber Jan 11, 2022
eb7b82b
added logging events configuration to build.gradle
YannickWeber Jan 11, 2022
88dc53e
removed GradleHiveMQExtensionSupplier.java
YannickWeber Jan 11, 2022
672929c
configure tests to use JDK 11
YannickWeber Jan 11, 2022
3732c1e
removed @author javadoc
YannickWeber Jan 13, 2022
e1947c2
removed maven-embedded dependencies
YannickWeber Jan 13, 2022
03282da
removed suppression
YannickWeber Jan 13, 2022
0d85c83
inlined file mode
YannickWeber Jan 13, 2022
1806fd3
removed Nullability annotations from constants
YannickWeber Jan 13, 2022
1656a71
removed default constructor
YannickWeber Jan 13, 2022
73c33d7
removed default constructor from tests
YannickWeber Jan 13, 2022
52edca1
localhost -> getHost()
YannickWeber Jan 13, 2022
6f2fa80
unified variable name for the HiveMQ Container in the tests
YannickWeber Jan 13, 2022
52bb0e3
wrapped with try with resources block
YannickWeber Jan 13, 2022
5629c8d
added hivemq to dependabot.yml
YannickWeber Jan 13, 2022
abc4581
removed .gitignore
YannickWeber Jan 13, 2022
4f4dbef
constants to upper case
YannickWeber Jan 14, 2022
f9c8564
moved extension creation logic from HiveMQContainer to HiveMQExtension
YannickWeber Jan 14, 2022
c15ff22
replaced getters with lombok in HiveMQExtension
YannickWeber Jan 14, 2022
e998dc5
moved MultiLogMessageWaitStrategy to core
YannickWeber Jan 14, 2022
bed4add
Moved code-samples from docs into java-files. Cleaned up docs while d…
codepitbull Jan 19, 2022
1940a8e
Fixed review comments
codepitbull Jan 28, 2022
89de228
Merge pull request #3 from hivemq/externalised-codesamples
YannickWeber Jan 31, 2022
2e356b5
removed silent() method and the log-comsumer
YannickWeber Jan 31, 2022
ecc7088
adapted logback-test.xml
YannickWeber Jan 31, 2022
e835015
added hivemq-testcontainer.png
YannickWeber Jan 31, 2022
a51d854
Fixed a missing file and broken label-rendering
codepitbull Feb 1, 2022
9c18121
Merge pull request #4 from hivemq/fix-rendering
YannickWeber Feb 2, 2022
0b3a919
addressed documentation PR change requests
YannickWeber Feb 4, 2022
1db83e5
removed nullability annotations from MultiLogMessageWaitStrategy
YannickWeber Feb 4, 2022
daa9408
changed hivemq logo
YannickWeber Feb 4, 2022
537c29d
hivemq/hivemq-ee -> hivemq/hivemq4
YannickWeber Feb 4, 2022
f717b73
refactored log consumers
YannickWeber Feb 7, 2022
955e52b
addressed PR change request
YannickWeber Feb 8, 2022
a9b331d
removed Tags from default docker image names to make the compatibilit…
YannickWeber Feb 9, 2022
4784f34
removed docker image creation for removal of prepackaged extensions
YannickWeber Feb 15, 2022
a3b25f0
Enable all doc code snippet tests for HiveMQ module
kiview Feb 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ updates:
schedule:
interval: "monthly"
open-pull-requests-limit: 10
- package-ecosystem: "gradle"
directory: "/modules/hivemq"
schedule:
interval: "monthly"
open-pull-requests-limit: 10
- package-ecosystem: "gradle"
directory: "/modules/influxdb"
schedule:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.testcontainers.containers.wait.strategy;

import org.testcontainers.DockerClientFactory;
import org.testcontainers.containers.ContainerLaunchException;
import org.testcontainers.containers.output.OutputFrame;
import org.testcontainers.containers.output.WaitingConsumer;
import org.testcontainers.utility.LogUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Predicate;

/**
* This is a wait strategy to wait for multiple log patterns.
* The wait strategy will continue when every log pattern is matched at least once.
*/
public class MultiLogMessageWaitStrategy extends AbstractWaitStrategy {

private final ConcurrentHashMap<String, Boolean> regexes = new ConcurrentHashMap<>();

@Override
protected void waitUntilReady() {
WaitingConsumer waitingConsumer = new WaitingConsumer();
LogUtils.followOutput(DockerClientFactory.instance().client(), waitStrategyTarget.getContainerId(), waitingConsumer);

Predicate<OutputFrame> waitPredicate = outputFrame -> {
if (regexes.isEmpty()) {
return true;
}
regexes.entrySet().forEach(regexHasMatched -> {
final boolean matched = outputFrame.getUtf8String().matches("(?s)" + regexHasMatched.getKey());
if (matched) {
regexHasMatched.setValue(true);
}
});
return regexes.values().stream().reduce(Boolean::logicalAnd).orElse(true);
};

try {
waitingConsumer.waitUntil(waitPredicate, startupTimeout.getSeconds(), TimeUnit.SECONDS, 1);
} catch (TimeoutException e) {
throw new ContainerLaunchException("Timed out waiting for log output matching '" + regexes + "'");
}
}

public MultiLogMessageWaitStrategy withRegEx(final String regEx) {
regexes.put(regEx, false);
return this;
}

public MultiLogMessageWaitStrategy reset() {
for (final Map.Entry<String, Boolean> stringBooleanEntry : regexes.entrySet()) {
stringBooleanEntry.setValue(false);
}
return this;
}
}
237 changes: 237 additions & 0 deletions docs/modules/hivemq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
# HiveMQ Module

<img src="../modules_logos/hivemq-module.png" alt="drawing" width="800"/>

Automatic starting HiveMQ docker containers for JUnit4 and JUnit5 tests.
This enables testing MQTT client applications and integration testing of custom HiveMQ extensions.

- Community forum: https://community.hivemq.com/
- HiveMQ website: https://www.hivemq.com/
- MQTT resources:
- [MQTT Essentials](https://www.hivemq.com/mqtt-essentials/)
- [MQTT 5 Essentials](https://www.hivemq.com/mqtt-5/)

Please make sure to check out the hivemq-docs for the [Community Edition](https://github.com/hivemq/hivemq-community-edition/wiki/)
and the [Enterprise Edition](https://www.hivemq.com/docs/hivemq/4.7/user-guide/).

## Using HiveMQ CE/EE

HiveMQ provides different editions of on [Docker Hub](https://hub.docker.com/u/hivemq):

- the open source [Community Edition](https://github.com/hivemq/hivemq-community-edition) which
is published as *hivemq/hivemq-ce*.
- the [Enterprise Edition](https://www.hivemq.com/docs/hivemq/4.7/user-guide/) which is published as *hivemq/hivemq4*.

Both editions can be used directly:

Using the Community Edition:
<!--codeinclude-->
[Community Edition HiveMQ image](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java) inside_block:ceVersion
<!--/codeinclude-->

Using the Enterprise Edition:
<!--codeinclude-->
[Enterprise Edition HiveMQ image](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java) inside_block:eeVersion
<!--/codeinclude-->

Using a specifc version is possible by using the tag:
<!--codeinclude-->
[Specific HiveMQ Version](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java) inside_block:specificVersion
<!--/codeinclude-->

## Test your MQTT 3 and MQTT 5 client application

Using an Mqtt-client (e.g. the [HiveMQ-Mqtt-Client](https://github.com/hivemq/hivemq-mqtt-client)) you can start
testing directly.

<!--codeinclude-->
[MQTT5 Client](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java) inside_block:mqtt5client
<!--/codeinclude-->

## Settings

There are several things that can be adjusted before container setup.
The following example shows how to enable the Control Center (this is an enterprise feature), set the log level to DEBUG
and load a HiveMQ-config-file from the classpath.

<!--codeinclude-->
[Config Examples](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoHiveMQContainerIT.java) inside_block:eeVersionWithControlCenter
<!--/codeinclude-->

---
**Note:**
The Control Center of HiveMQ can be accessed via the URL presented in the output of the starting container:

```
2021-09-10 10:35:53,511 INFO - The HiveMQ Control Center is reachable under: http://localhost:55032
```

Please be aware that the Control Center is a feature of the enterprise edition of HiveMQ and thus only available with
the enterprise image.

---

## Testing HiveMQ extensions

Using the [Extension SDK](https://github.com/hivemq/hivemq-extension-sdk) the functionality of all editions of HiveMQ
can be extended.
The HiveMQ module also supports testing your own custom extensions.

### Wait Strategy

The raw HiveMQ module is built to wait for certain startup log messages to signal readiness.
Since extensions are loaded dynamically they can be available a short while after the main container has started.
We therefore provide custom wait conditions for HiveMQ Extensions:

The following will specify an extension to be loaded from **src/test/resources/modifier-extension** into the container and
wait for an extension named **'My Extension Name'** to be started:

<!--codeinclude-->
[Custom Wait Strategy](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoExtensionTestsIT.java) inside_block:waitStrategy
<!--/codeinclude-->

Next up we have an example for using an extension directly from the classpath and waiting directly on the extension:

<!--codeinclude-->
[Extension from Classpath](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoExtensionTestsIT.java) inside_block:extensionClasspath
<!--/codeinclude-->

---
**Note** Debugging extensions

Both examples contain ```.withDebugging()``` which enables remote debugging on the container.
With debugging enabled you can start putting breakpoints right into your extensions.

---

### Testing extensions using Gradle

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).

The plugin adds an `integrationTest` task which executes tests from the `integrationTest` source set.
- Integration test source files are defined in `src/integrationTest`.
- Integration test dependencies are defined via the `integrationTestImplementation`, `integrationTestRuntimeOnly`, etc. configurations.

The `integrationTest` task builds the extension and unzips it to the `build/hivemq-extension-test` directory.
The tests can then load the built extension into the HiveMQ Testcontainer.

```java
@Container
final HiveMQContainer hivemq = new HiveMQContainer(HiveMQContainer.DEFAULT_HIVEMQ_CE_IMAGE_NAME)
.withExtension(new File("build/hivemq-extension-test/<extension-id>"));
```

### Enable/Disable an extension

It is possible to enable and disable HiveMQ extensions during runtime. Extensions can also be disabled on startup.

---
**Note**: that disabling or enabling of extension during runtime is only supported in HiveMQ 4 Enterprise Edition Containers.

---

The following example shows how to start a HiveMQ container with the extension called **my-extension** being disabled.


<!--codeinclude-->
[Disable Extension at startup](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:startDisabled
<!--/codeinclude-->

The following test then proceeds to enable and then disable the extension:

<!--codeinclude-->
[Enable/Disable extension at runtime](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:runtimeEnable
<!--/codeinclude-->

## Enable/Disable an extension loaded from a folder

Extensions loaded from an extension folder during runtime can also be enabled/disabled on the fly.
If the extension folder contains a DISABLED file, the extension will be disabled during startup.

---
**Note**: that disabling or enabling of extension during runtime is only supported in HiveMQ 4 Enterprise Edition Containers.

---

We first load the extension from the filesytem:
<!--codeinclude-->
[Extension from filesystem](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:startFromFilesystem
<!--/codeinclude-->

Now we can enable/disable the extension using its name:

<!--codeinclude-->
[Enable/Disable extension at runtime](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:runtimeEnableFilesystem
<!--/codeinclude-->

### Remove prepackaged HiveMQ Extensions

Since HiveMQ's 4.4 release, HiveMQ Docker images come with the HiveMQ Extension for Kafka, the HiveMQ Enterprise Bridge Extension
and the HiveMQ Enterprise Security Extension.
These Extensions are disabled by default, but sometimes you my need to remove them before the container starts.

Removing all extension is as simple as:

<!--codeinclude-->
[Remove all extensions](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:noExtensions
<!--/codeinclude-->

A single extension (e.g. Kafka) can be removed as easily:
<!--codeinclude-->
[Remove a specific extension](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoDisableExtensionsIT.java) inside_block:noKafkaExtension
<!--/codeinclude-->

## Put files into the container

### Put a file into HiveMQ home

<!--codeinclude-->
[Put file into HiveMQ home](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoFilesIT.java) inside_block:hivemqHome
<!--/codeinclude-->

### Put files into extension home

<!--codeinclude-->
[Put file into HiveMQ-Extension home](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoFilesIT.java) inside_block:extensionHome
<!--/codeinclude-->

### Put license files into the container

<!--codeinclude-->
[Put license file into the HiveMQ container](../../modules/hivemq/src/test/java/org/testcontainers/hivemq/docs/DemoFilesIT.java) inside_block:withLicenses
<!--/codeinclude-->


### Customize the Container further

Since the `HiveMQContainer` extends from [Testcontainer's](https://github.com/testcontainers) `GenericContainer` the container
can be customized as desired.

## Add to your project

### Gradle

Add to `build.gradle`:

````groovy
testImplementation 'org.testcontainers:hivemq:{{latest_version}}'
````

Add to `build.gradle.kts`:

````kotlin
testImplementation("org.testcontainers:hivemq:{{latest_version}}")
````

### Maven

Add to `pom.xml`:

```xml
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>hivemq</artifactId>
<version>{{latest_version}}</version>
<scope>test</scope>
</dependency>
```
Binary file added docs/modules_logos/hivemq-module.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ nav:
- modules/docker_compose.md
- modules/elasticsearch.md
- modules/gcloud.md
- modules/hivemq.md
- modules/k3s.md
- modules/kafka.md
- modules/localstack.md
Expand Down
37 changes: 37 additions & 0 deletions modules/hivemq/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
description = "TestContainers :: HiveMQ"

dependencies {
api(project(":testcontainers"))
api("org.jetbrains:annotations:23.0.0")

shaded("org.apache.commons:commons-lang3:3.12.0")
shaded("commons-io:commons-io:2.11.0")
shaded("org.javassist:javassist:3.28.0-GA")
shaded("org.jboss.shrinkwrap:shrinkwrap-api:1.2.6")
shaded("org.jboss.shrinkwrap:shrinkwrap-impl-base:1.2.6")
shaded("net.lingala.zip4j:zip4j:2.9.1")

testImplementation("org.junit.jupiter:junit-jupiter-api:5.8.2")
testImplementation(project(":junit-jupiter"))
testImplementation("com.hivemq:hivemq-extension-sdk:4.7.3")
testImplementation("com.hivemq:hivemq-mqtt-client:1.3.0")
testImplementation("org.apache.httpcomponents:httpclient:4.5.13")
testImplementation("ch.qos.logback:logback-classic:1.2.10")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.8.2")
}

test {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed"
}
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(11)
}
}

compileTestJava {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(11)
}
}