From 9d9befebe197fd170f73518483ce213bef661653 Mon Sep 17 00:00:00 2001 From: Divine Threepwood Date: Thu, 15 Jan 2026 21:33:10 +0100 Subject: [PATCH 01/10] fix test container config by injecting the config instead of exchanging it via the os --- .../communication/mqtt/test/MqttIntegrationTest.kt | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt index 5da6a25e8..637ec4e22 100644 --- a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt +++ b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt @@ -10,13 +10,12 @@ import org.openbase.jps.exception.JPServiceException import org.openbase.jul.communication.jp.JPComHost import org.openbase.jul.communication.jp.JPComPort import org.openbase.jul.communication.mqtt.SharedMqttClient.waitForShutdown -import org.testcontainers.containers.BindMode import org.testcontainers.containers.GenericContainer import org.testcontainers.utility.DockerImageName +import org.testcontainers.utility.MountableFile import java.nio.file.Files import java.nio.file.Path import java.time.Duration -import java.util.* /*- * #%L @@ -46,7 +45,7 @@ open class MqttIntegrationTest { companion object { const val port = 1884 - var mosquittoConfig: Path? = null + lateinit var mosquittoConfig: Path var broker: GenericContainer<*>? = null val configLock = Any() } @@ -64,10 +63,9 @@ open class MqttIntegrationTest { ) GenericContainer(DockerImageName.parse("eclipse-mosquitto")) .withExposedPorts(port) - .withFileSystemBind( - mosquittoConfig.toString(), - "/mosquitto/config/mosquitto.conf", - BindMode.READ_ONLY + .withCopyFileToContainer( + MountableFile.forHostPath(mosquittoConfig.toString()), + "/mosquitto/config/mosquitto.conf" ) .apply { withStartupTimeout(Duration.ofSeconds(30)).start() } .also { From 743b0ca2a10593112a707ea30c80a12106b5cf6e Mon Sep 17 00:00:00 2001 From: Divine Threepwood Date: Wed, 18 Mar 2026 21:05:41 +0100 Subject: [PATCH 02/10] fix test container framework integration, made sure mqtt docker container is not restarted after each test, share mqtt docker test container between all tests. --- .../AbstractControllerServerTest.java | 2 +- .../mqtt/AbstractIntegrationTest.kt | 101 ++-- .../jul/communication/mqtt/IntegrationTest.kt | 2 +- .../mqtt/SharedMqttClientTest.kt | 5 +- .../mqtt/test/MqttIntegrationTest.kt | 68 +-- versions.properties | 430 +++++++++++++++++- 6 files changed, 520 insertions(+), 88 deletions(-) diff --git a/module/communication/controller/src/test/java/org/openbase/jul/communication/controller/AbstractControllerServerTest.java b/module/communication/controller/src/test/java/org/openbase/jul/communication/controller/AbstractControllerServerTest.java index 54fd894dc..fad789635 100644 --- a/module/communication/controller/src/test/java/org/openbase/jul/communication/controller/AbstractControllerServerTest.java +++ b/module/communication/controller/src/test/java/org/openbase/jul/communication/controller/AbstractControllerServerTest.java @@ -405,7 +405,7 @@ public void testReinit() throws Exception { * * @throws Exception if any error occurs */ - @Timeout(5) + @Timeout(20) @Test public void testParallelMethodCall() throws Exception { final String scope = "/test/parallel"; diff --git a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt index cb09a3116..7cf37e31f 100644 --- a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt +++ b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt @@ -4,77 +4,82 @@ import com.hivemq.client.mqtt.mqtt5.datatypes.Mqtt5UserProperties import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.Timeout -import org.testcontainers.containers.BindMode +import org.junit.jupiter.api.extension.ExtendWith import org.testcontainers.containers.GenericContainer import org.testcontainers.junit.jupiter.Testcontainers import org.testcontainers.utility.DockerImageName +import org.testcontainers.utility.MountableFile +import java.nio.file.Files +import java.nio.file.Path import java.time.Duration -import kotlin.io.path.absolute import kotlin.io.path.deleteIfExists -import kotlin.io.path.writeLines +import kotlin.jvm.java -@Testcontainers -abstract class AbstractIntegrationTest { +//@Testcontainers +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +open class AbstractIntegrationTest { - // the companion object makes sure that the container is started once before all tests instead of restarting for every test companion object { + const val port = 1883 + var broker: GenericContainer<*>? = null + val lock = Any() + } - private const val port: Int = 1883 - - private val mosquittoConfig = kotlin.io.path.createTempFile(prefix = "mosquitto_", suffix = ".conf") - private lateinit var broker: MqttBrokerContainer + private var usageCounter = 0 - private var usageCounter = 0 - private val lock = Any() + @BeforeAll + @Timeout(30) + fun setupMqtt() { + synchronized(lock) { + if (usageCounter == 0) { + val mosquittoConfig: Path = Files.createTempFile("${this::class.java.simpleName}_mosquitto_", ".conf") + Files.write( + mosquittoConfig, listOf( + "allow_anonymous true", + "listener $port" + ) + ) - @JvmStatic - @BeforeAll - @Timeout(30) - fun setup() { - synchronized(lock) { - if (usageCounter == 0) { - mosquittoConfig.writeLines( - listOf( - "allow_anonymous true", - "listener 1883" - ) + broker = MqttBrokerContainer() + .withExposedPorts(port) + .withCopyFileToContainer( + MountableFile.forHostPath(mosquittoConfig.toString()), + "/mosquitto/config/mosquitto.conf" ) + .apply { withStartupTimeout(Duration.ofSeconds(30)).start() } + .also { + if (broker?.takeIf { it.containerId != null } != null) + error("broker was already initialized!") + } + .also { broker = it } - broker = MqttBrokerContainer() - .withExposedPorts(port) - .withFileSystemBind( - mosquittoConfig.absolute().toString(), - "/mosquitto/config/mosquitto.conf", - BindMode.READ_ONLY - ) - broker.withStartupTimeout(Duration.ofSeconds(30)).start() - } - usageCounter++ + mosquittoConfig.deleteIfExists() } + usageCounter++ } + } - @JvmStatic - @AfterAll - @Timeout(30) - fun cleanup() { - synchronized(lock) { - usageCounter-- - if (usageCounter == 0) { - SharedMqttClient.waitForShutdown() - broker.stop() - mosquittoConfig.deleteIfExists() - } + @AfterAll + @Timeout(30) + fun cleanup() { + synchronized(lock) { + SharedMqttClient.waitForShutdown() + usageCounter-- + if (usageCounter == 0) { + SharedMqttClient.waitForShutdown() + broker?.stop() } } } - protected val brokerHost: String get() = broker.host + class MqttBrokerContainer : GenericContainer(DockerImageName.parse("eclipse-mosquitto")) - protected val brokerPort: Int get() = broker.firstMappedPort -} + protected val brokerHost: String? get() = broker?.host -class MqttBrokerContainer : GenericContainer(DockerImageName.parse("eclipse-mosquitto")) + protected val brokerPort: Int? get() = broker?.firstMappedPort +} fun Mqtt5Publish.clearTimestamp() = let { this.extend().userProperties(Mqtt5UserProperties.of()).build() diff --git a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/IntegrationTest.kt b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/IntegrationTest.kt index ddd1a205c..857f4bcf0 100644 --- a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/IntegrationTest.kt +++ b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/IntegrationTest.kt @@ -22,7 +22,7 @@ import kotlin.concurrent.withLock class IntegrationTest : AbstractIntegrationTest() { private val scope = ScopeProcessor.generateScope("/test/integration") - private val config = CommunicatorConfig(brokerHost, brokerPort) + private val config get() = CommunicatorConfig(brokerHost!!, brokerPort!!) internal class MethodMock { val lock = ReentrantLock() diff --git a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/SharedMqttClientTest.kt b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/SharedMqttClientTest.kt index ec17b95d5..5a4dbc53b 100644 --- a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/SharedMqttClientTest.kt +++ b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/SharedMqttClientTest.kt @@ -12,10 +12,12 @@ import org.openbase.jul.communication.config.CommunicatorConfig internal class SharedMqttClientTest : AbstractIntegrationTest() { + private val config get() = CommunicatorConfig(brokerHost!!, brokerPort!!) + + @Test @Timeout(value = 30) fun `shutdown should be work as expected`() { - val config = CommunicatorConfig(brokerHost, brokerPort) val client = SharedMqttClient client.get(config).apply { disconnect() @@ -27,7 +29,6 @@ internal class SharedMqttClientTest : AbstractIntegrationTest() { @Test @Timeout(value = 30) fun `subscription should be work as expected`() { - val config = CommunicatorConfig(brokerHost, brokerPort) val topic = "/a/b/c" val client = SharedMqttClient diff --git a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt index 637ec4e22..1622d1220 100644 --- a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt +++ b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt @@ -9,13 +9,15 @@ import org.openbase.jps.core.JPService import org.openbase.jps.exception.JPServiceException import org.openbase.jul.communication.jp.JPComHost import org.openbase.jul.communication.jp.JPComPort -import org.openbase.jul.communication.mqtt.SharedMqttClient.waitForShutdown +import org.openbase.jul.communication.mqtt.SharedMqttClient import org.testcontainers.containers.GenericContainer +import org.testcontainers.junit.jupiter.Testcontainers import org.testcontainers.utility.DockerImageName import org.testcontainers.utility.MountableFile import java.nio.file.Files import java.nio.file.Path import java.time.Duration +import kotlin.io.path.deleteIfExists /*- * #%L @@ -41,50 +43,58 @@ import java.time.Duration * */ @TestInstance(TestInstance.Lifecycle.PER_CLASS) @ExtendWith(OpenbaseDeadlockChecker::class) +@Testcontainers open class MqttIntegrationTest { companion object { const val port = 1884 - lateinit var mosquittoConfig: Path var broker: GenericContainer<*>? = null - val configLock = Any() + val lock = Any() } + private var usageCounter = 0 + @BeforeAll @Timeout(30) fun setupMqtt() { - synchronized(configLock) { - mosquittoConfig = Files.createTempFile("mosquitto_", ".conf") - Files.write( - mosquittoConfig, listOf( - "allow_anonymous true", - "listener " + port - ) - ) - GenericContainer(DockerImageName.parse("eclipse-mosquitto")) - .withExposedPorts(port) - .withCopyFileToContainer( - MountableFile.forHostPath(mosquittoConfig.toString()), - "/mosquitto/config/mosquitto.conf" + synchronized(lock) { + if (usageCounter == 0) { + val mosquittoConfig: Path = Files.createTempFile("${this::class.java.simpleName}_mosquitto_", ".conf") + Files.write( + mosquittoConfig, listOf( + "allow_anonymous true", + "listener $port" + ) ) - .apply { withStartupTimeout(Duration.ofSeconds(30)).start() } - .also { - if (broker?.takeIf { it.containerId != null } != null) - error("broker was already initialized!") - } - .also { broker = it } - .also { setupProperties() } + MqttBrokerContainer() + .withExposedPorts(port) + .withCopyFileToContainer( + MountableFile.forHostPath(mosquittoConfig.toString()), + "/mosquitto/config/mosquitto.conf" + ) + .apply { withStartupTimeout(Duration.ofSeconds(30)).start() } + .also { + if (broker?.takeIf { it.containerId != null } != null) + error("broker was already initialized!") + } + .also { broker = it } + .also { setupProperties() } + mosquittoConfig.deleteIfExists() + } + usageCounter++ } } @AfterAll @Timeout(30) fun tearDownMQTT() { - synchronized(configLock) { - waitForShutdown() - broker?.stop() - Files.delete(mosquittoConfig) - } + synchronized(lock) { + SharedMqttClient.waitForShutdown() + usageCounter-- + if (usageCounter == 0) { + //waitForShutdown() + broker?.stop() + }} } @Throws(JPServiceException::class) @@ -96,5 +106,7 @@ open class MqttIntegrationTest { JPService.setupJUnitTestMode() } + class MqttBrokerContainer : GenericContainer(DockerImageName.parse("eclipse-mosquitto")) + open fun setupCustomProperties() {} } diff --git a/versions.properties b/versions.properties index 59b33ebcb..3ff339559 100644 --- a/versions.properties +++ b/versions.properties @@ -6,66 +6,480 @@ #### #### suppress inspection "SpellCheckingInspection" for whole file #### suppress inspection "UnusedProperty" for whole file + version.com.adarshr..gradle-test-logger-plugin=4.0.0 + version.junit.jupiter=5.10.1 +## # available=5.10.2 +## # available=5.10.3 +## # available=5.10.4 +## # available=5.10.5 +## # available=5.11.0-M1 +## # available=5.11.0-M2 +## # available=5.11.0-RC1 +## # available=5.11.0 +## # available=5.11.1 +## # available=5.11.2 +## # available=5.11.3 +## # available=5.11.4 +## # available=5.12.0-M1 +## # available=5.12.0-RC1 +## # available=5.12.0-RC2 +## # available=5.12.0 +## # available=5.12.1 +## # available=5.12.2 +## # available=5.13.0-M1 +## # available=5.13.0-M2 +## # available=5.13.0-M3 +## # available=5.13.0-RC1 +## # available=5.13.0 +## # available=5.13.1 +## # available=5.13.2 +## # available=5.13.3 +## # available=5.13.4 +## # available=5.14.0-RC1 +## # available=5.14.0 +## # available=5.14.1 +## # available=5.14.2 +## # available=5.14.3 +## # available=6.0.0-M1 +## # available=6.0.0-M2 +## # available=6.0.0-RC1 +## # available=6.0.0-RC2 +## # available=6.0.0-RC3 +## # available=6.0.0 +## # available=6.0.1 +## # available=6.0.2 +## # available=6.0.3 +## # available=6.1.0-M1 + version.java3d..j3d-core=1.3.1 + plugin.io.github.gradle-nexus.publish-plugin=2.0.0 -## # available=2.0.0-rc-1 + version.kotlinx.coroutines=1.8.1 +## # available=1.9.0-RC +## # available=1.9.0-RC.2 +## # available=1.9.0 +## # available=1.10.0 +## # available=1.10.1 +## # available=1.10.2 + ## unused version.org.apache.commons..commons-collections4=4.4 + ## unused version.rxjava2.rxjava=2.2.21 + version.uk.com.robust-it..cloning=1.9.12 -version.org.testcontainers..junit-jupiter=1.18.3 -## # available=1.19.0 -## # available=1.19.1 -## # available=1.19.2 + +version.org.testcontainers..junit-jupiter=1.21.4 + version.org.projectlombok..lombok=1.18.30 +## # available=1.18.32 +## # available=1.18.34 +## # available=1.18.36 +## # available=1.18.38 +## # available=1.18.40 +## # available=1.18.42 +## # available=1.18.44 + version.org.openbase..type=[1.4,1.5-alpha) ## # available=1.0.0 ## # available=1.1.2 ## # available=1.1.3 ## # available=1.2.1 ## # available=1.3.0 -## # available=1.4-SNAPSHOT ## # available=1.4.0 -## # available=1.4.1-SNAPSHOT ## # available=1.4.1 -## # available=1.4.2-SNAPSHOT + version.org.openbase..jps=3.7.0 + version.org.netbeans.external..AbsoluteLayout=RELEASE190 +## # available=RELEASE200 +## # available=RELEASE210 +## # available=RELEASE220 +## # available=RELEASE230 +## # available=RELEASE240 +## # available=RELEASE250 +## # available=RELEASE260 +## # available=RELEASE270 +## # available=RELEASE280 +## # available=RELEASE290 + ## unused version.org.eclipse.jgit..org.eclipse.jgit=[5.1.7,5.1.8-alpha) + version.org.controlsfx..controlsfx=11.2.0 +## # available=11.2.1 +## # available=11.2.2 +## # available=11.2.3 + ## unused version.org.codehaus.woodstox..woodstox-core-asl=[4.1,4.2-alpha) + version.org.apache.commons..commons-lang3=3.13.0 +## # available=3.14.0 +## # available=3.15.0 +## # available=3.16.0 +## # available=3.17.0 +## # available=3.18.0 +## # available=3.19.0 +## # available=3.20.0 + version.mockk=1.13.8 +### available=1.13.9 +### available=1.13.10 +### available=1.13.11 +### available=1.13.12 +### available=1.13.13 +### available=1.13.14 +### available=1.13.16 +### available=1.13.17 +### available=1.14.0 +### available=1.14.2 +### available=1.14.3 +### available=1.14.4 +### available=1.14.5 +### available=1.14.6 +### available=1.14.7 +### available=1.14.9 + version.kotlin=2.0.0 +## # available=2.0.10-RC +## # available=2.0.10-RC2 +## # available=2.0.10 +## # available=2.0.20-Beta1 +## # available=2.0.20-Beta2 +## # available=2.0.20-RC +## # available=2.0.20-RC2 +## # available=2.0.20 +## # available=2.0.21-RC +## # available=2.0.21 +## # available=2.1.0-Beta1 +## # available=2.1.0-Beta2 +## # available=2.1.0-RC +## # available=2.1.0-RC2 +## # available=2.1.0 +## # available=2.1.10-RC +## # available=2.1.10-RC2 +## # available=2.1.10 +## # available=2.1.20-Beta1 +## # available=2.1.20-Beta2 +## # available=2.1.20-RC +## # available=2.1.20-RC2 +## # available=2.1.20-RC3 +## # available=2.1.20 +## # available=2.1.21-RC +## # available=2.1.21-RC2 +## # available=2.1.21 +## # available=2.2.0-Beta1 +## # available=2.2.0-Beta2 +## # available=2.2.0-RC +## # available=2.2.0-RC2 +## # available=2.2.0-RC3 +## # available=2.2.0 +## # available=2.2.10-RC +## # available=2.2.10-RC2 +## # available=2.2.10 +## # available=2.2.20-Beta1 +## # available=2.2.20-Beta2 +## # available=2.2.20-RC +## # available=2.2.20-RC2 +## # available=2.2.20 +## # available=2.2.21-RC +## # available=2.2.21-RC2 +## # available=2.2.21 +## # available=2.3.0-Beta1 +## # available=2.3.0-Beta2 +## # available=2.3.0-RC +## # available=2.3.0-RC2 +## # available=2.3.0-RC3 +## # available=2.3.0 +## # available=2.3.10-RC +## # available=2.3.10-RC2 +## # available=2.3.10 +## # available=2.3.20-Beta1 +## # available=2.3.20-Beta2 +## # available=2.3.20-RC +## # available=2.3.20-RC2 +## # available=2.3.20-RC3 +## # available=2.3.20 + version.kotest=5.6.2 ## # available=5.7.0 ## # available=5.7.1 ## # available=5.7.2 ## # available=5.8.0 +## # available=5.8.1 +## # available=5.9.0 +## # available=5.9.1 +## # available=6.0.0.M1 +## # available=6.0.0.M2 +## # available=6.0.0.M3 +## # available=6.0.0.M4 +## # available=6.0.0.M5 +## # available=6.0.0.M6 +## # available=6.0.0.M7 +## # available=6.0.0.M8 +## # available=6.0.0.M9 +## # available=6.0.0.M10 +## # available=6.0.0.M11 +## # available=6.0.0.M12 +## # available=6.0.0.M13 +## # available=6.0.0.M14 +## # available=6.0.0.M15 +## # available=6.0.0.M16 +## # available=6.0.0.M17 +## # available=6.0.0 +## # available=6.0.1 +## # available=6.0.2 +## # available=6.0.3 +## # available=6.0.4 +## # available=6.0.5 +## # available=6.0.6 +## # available=6.0.7 +## # available=6.1.0-RC1 +## # available=6.1.0-RC2 +## # available=6.1.0-RC3 +## # available=6.1.0-RC4 +## # available=6.1.0 +## # available=6.1.1 +## # available=6.1.2 +## # available=6.1.3 +## # available=6.1.4 +## # available=6.1.5 +## # available=6.1.6 +## # available=6.1.7 + version.java3d..vecmath=1.3.1 + version.de.jensd..fontawesomefx=8.9 + version.commons-lang..commons-lang=2.6 + version.commons-io..commons-io=2.13.0 ## # available=2.14.0 ## # available=2.15.0 +## # available=2.15.1 +## # available=2.16.0 +## # available=2.16.1 +## # available=2.17.0 +## # available=2.18.0 +## # available=2.19.0 +## # available=2.20.0 +## # available=2.21.0 + version.com.jfoenix..jfoenix=9.0.10 + version.com.io7m.xom..xom=1.2.10 + version.com.hivemq..hivemq-mqtt-client=1.3.3 +## # available=1.3.4 +## # available=1.3.5 +## # available=1.3.6 +## # available=1.3.7 +## # available=1.3.8 +## # available=1.3.9 +## # available=1.3.10 +## # available=1.3.11 +## # available=1.3.12 + version.com.googlecode.protobuf-java-format..protobuf-java-format=1.4 + version.com.google.code.gson..gson=2.10.1 +## # available=2.11.0 +## # available=2.12.0 +## # available=2.12.1 +## # available=2.13.0 +## # available=2.13.1 +## # available=2.13.2-rc1 +## # available=2.13.2 + ## unused version.com.fasterxml.jackson.dataformat..jackson-dataformat-xml=[2.11,2.12-alpha) + ## unused version.com.fasterxml.jackson.core..jackson-databind=[2.11,2.12-alpha) + ## unused version.com.fasterxml.jackson.core..jackson-core=[2.11,2.12-alpha) + ## unused version.com.fasterxml.jackson.core..jackson-annotations=[2.11,2.12-alpha) + version.io.quarkus..quarkus-junit4-mock=3.5.2 +## # available=3.5.3 +## # available=3.6.0 ## # available=3.6.0.CR1 +## # available=3.6.1 +## # available=3.6.2 +## # available=3.6.3 +## # available=3.6.4 +## # available=3.6.5 +## # available=3.6.6 +## # available=3.6.7 +## # available=3.6.8 +## # available=3.6.9 +## # available=3.7.0 +## # available=3.7.0.CR1 +## # available=3.7.1 +## # available=3.7.2 +## # available=3.7.3 +## # available=3.7.4 +## # available=3.8.0 +## # available=3.8.0.CR1 +## # available=3.8.1 +## # available=3.8.2 +## # available=3.8.3 +## # available=3.8.4 +## # available=3.8.5 +## # available=3.8.6 +## # available=3.8.6.1 +## # available=3.9.0 +## # available=3.9.0.CR1 +## # available=3.9.0.CR2 +## # available=3.9.1 +## # available=3.9.2 +## # available=3.9.3 +## # available=3.9.4 +## # available=3.9.5 +## # available=3.10.0 +## # available=3.10.0.CR1 +## # available=3.10.1 +## # available=3.10.2 +## # available=3.11.0 +## # available=3.11.0.CR1 +## # available=3.11.1 +## # available=3.11.2 +## # available=3.11.3 +## # available=3.12.0 +## # available=3.12.0.CR1 +## # available=3.12.1 +## # available=3.12.2 +## # available=3.12.3 +## # available=3.13.0 +## # available=3.13.0.CR1 +## # available=3.13.1 +## # available=3.13.2 +## # available=3.13.3 +## # available=3.14.0 +## # available=3.14.0.CR1 +## # available=3.14.1 +## # available=3.14.2 +## # available=3.14.3 +## # available=3.14.4 +## # available=3.15.0 +## # available=3.15.0.CR1 +## # available=3.15.1 +## # available=3.15.2 +## # available=3.15.3 +## # available=3.15.3.1 +## # available=3.15.4 +## # available=3.15.5 +## # available=3.15.6 +## # available=3.15.6.1 +## # available=3.15.6.2 +## # available=3.15.7 +## # available=3.16.0 +## # available=3.16.0.CR1 +## # available=3.16.1 +## # available=3.16.2 +## # available=3.16.3 +## # available=3.16.4 +## # available=3.17.0 +## # available=3.17.0.CR1 +## # available=3.17.1 +## # available=3.17.2 +## # available=3.17.3 +## # available=3.17.4 +## # available=3.17.5 +## # available=3.17.6 +## # available=3.17.7 +## # available=3.17.8 +## # available=3.18.0 +## # available=3.18.0.CR1 +## # available=3.18.1 +## # available=3.18.2 +## # available=3.18.3 +## # available=3.18.4 +## # available=3.19.0 +## # available=3.19.0.CR1 +## # available=3.19.1 +## # available=3.19.2 +## # available=3.19.3 +## # available=3.19.4 +## # available=3.20.0 +## # available=3.20.0.CR1 +## # available=3.20.1 +## # available=3.20.2 +## # available=3.20.2.1 +## # available=3.20.2.2 +## # available=3.20.3 +## # available=3.20.4 +## # available=3.20.5 +## # available=3.20.6 +## # available=3.21.0 +## # available=3.21.0.CR1 +## # available=3.21.1 +## # available=3.21.2 +## # available=3.21.3 +## # available=3.21.4 +## # available=3.22.0 +## # available=3.22.0.CR1 +## # available=3.22.1 +## # available=3.22.2 +## # available=3.22.3 +## # available=3.23.0 +## # available=3.23.0.CR1 +## # available=3.23.1 +## # available=3.23.2 +## # available=3.23.3 +## # available=3.23.4 +## # available=3.24.0 +## # available=3.24.0.CR1 +## # available=3.24.1 +## # available=3.24.2 +## # available=3.24.3 +## # available=3.24.4 +## # available=3.24.5 +## # available=3.25.0 +## # available=3.25.0.CR1 +## # available=3.25.1 +## # available=3.25.2 +## # available=3.25.3 +## # available=3.25.4 +## # available=3.26.0 +## # available=3.26.0.CR1 +## # available=3.26.1 +## # available=3.26.2 +## # available=3.26.3 +## # available=3.26.4 +## # available=3.27.0 +## # available=3.27.0.CR1 +## # available=3.27.1 +## # available=3.27.2 +## # available=3.27.3 +## # available=3.28.0 +## # available=3.28.0.CR1 +## # available=3.28.1 +## # available=3.28.2 +## # available=3.28.3 +## # available=3.28.4 +## # available=3.28.5 +## # available=3.29.0 +## # available=3.29.0.CR1 +## # available=3.29.1 +## # available=3.29.2 +## # available=3.29.3 +## # available=3.29.4 +## # available=3.30.0 +## # available=3.30.0.CR1 +## # available=3.30.1 +## # available=3.30.2 +## # available=3.30.3 +## # available=3.30.4 +## # available=3.30.5 +## # available=3.30.6 +## # available=3.30.7 +## # available=3.30.8 From 66adfc9142ba9b3ee45e8022770c0304529f0792 Mon Sep 17 00:00:00 2001 From: Divine Threepwood Date: Wed, 18 Mar 2026 22:32:38 +0100 Subject: [PATCH 03/10] bump version to 3.7.3 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7519f2864..4d78e15a0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,3 +1,3 @@ -version=3.7.2 +version=3.7.3 org.gradle.caching=true org.gradle.parallel=true From d1ab6eabf86a8d5777a95244d826ddcf6b8c3fcf Mon Sep 17 00:00:00 2001 From: Divine Threepwood Date: Thu, 19 Mar 2026 00:27:01 +0100 Subject: [PATCH 04/10] introduce broker manager and shutdown hook for test container --- module/communication/mqtt/build.gradle.kts | 1 + .../mqtt/AbstractIntegrationTest.kt | 61 ++-------------- .../mqtt/test/MqttBrokerManager.kt | 69 +++++++++++++++++++ .../mqtt/test/MqttIntegrationTest.kt | 67 +----------------- 4 files changed, 78 insertions(+), 120 deletions(-) create mode 100644 module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttBrokerManager.kt diff --git a/module/communication/mqtt/build.gradle.kts b/module/communication/mqtt/build.gradle.kts index 8593455f6..dbd9d22f8 100644 --- a/module/communication/mqtt/build.gradle.kts +++ b/module/communication/mqtt/build.gradle.kts @@ -8,6 +8,7 @@ dependencies { api(project(":jul.extension.type.processing")) api("com.hivemq:hivemq-mqtt-client:_") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:_") + testImplementation(project(":jul.communication.mqtt.test")) testImplementation("org.testcontainers:junit-jupiter:_") { exclude(group = "junit", module = "junit") } diff --git a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt index 7cf37e31f..0c21d2623 100644 --- a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt +++ b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt @@ -6,79 +6,28 @@ import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.Timeout -import org.junit.jupiter.api.extension.ExtendWith -import org.testcontainers.containers.GenericContainer +import org.openbase.jul.communication.mqtt.test.MqttBrokerManager import org.testcontainers.junit.jupiter.Testcontainers -import org.testcontainers.utility.DockerImageName -import org.testcontainers.utility.MountableFile -import java.nio.file.Files -import java.nio.file.Path -import java.time.Duration -import kotlin.io.path.deleteIfExists -import kotlin.jvm.java //@Testcontainers @TestInstance(TestInstance.Lifecycle.PER_CLASS) open class AbstractIntegrationTest { - companion object { - const val port = 1883 - var broker: GenericContainer<*>? = null - val lock = Any() - } - - private var usageCounter = 0 - @BeforeAll @Timeout(30) fun setupMqtt() { - synchronized(lock) { - if (usageCounter == 0) { - val mosquittoConfig: Path = Files.createTempFile("${this::class.java.simpleName}_mosquitto_", ".conf") - Files.write( - mosquittoConfig, listOf( - "allow_anonymous true", - "listener $port" - ) - ) - - broker = MqttBrokerContainer() - .withExposedPorts(port) - .withCopyFileToContainer( - MountableFile.forHostPath(mosquittoConfig.toString()), - "/mosquitto/config/mosquitto.conf" - ) - .apply { withStartupTimeout(Duration.ofSeconds(30)).start() } - .also { - if (broker?.takeIf { it.containerId != null } != null) - error("broker was already initialized!") - } - .also { broker = it } - - mosquittoConfig.deleteIfExists() - } - usageCounter++ - } + MqttBrokerManager.setupMqtt(this::class.java.simpleName) } @AfterAll @Timeout(30) fun cleanup() { - synchronized(lock) { - SharedMqttClient.waitForShutdown() - usageCounter-- - if (usageCounter == 0) { - SharedMqttClient.waitForShutdown() - broker?.stop() - } - } + MqttBrokerManager.tearDownMQTT() } - class MqttBrokerContainer : GenericContainer(DockerImageName.parse("eclipse-mosquitto")) - - protected val brokerHost: String? get() = broker?.host + protected val brokerHost: String? get() = MqttBrokerManager.broker?.host - protected val brokerPort: Int? get() = broker?.firstMappedPort + protected val brokerPort: Int? get() = MqttBrokerManager.broker?.firstMappedPort } fun Mqtt5Publish.clearTimestamp() = let { diff --git a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttBrokerManager.kt b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttBrokerManager.kt new file mode 100644 index 000000000..7d9ea9eb8 --- /dev/null +++ b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttBrokerManager.kt @@ -0,0 +1,69 @@ +package org.openbase.jul.communication.mqtt.test + +import org.openbase.jps.core.JPService +import org.openbase.jps.exception.JPServiceException +import org.openbase.jul.communication.jp.JPComHost +import org.openbase.jul.communication.jp.JPComPort +import org.openbase.jul.communication.mqtt.SharedMqttClient +import org.testcontainers.containers.GenericContainer +import org.testcontainers.utility.DockerImageName +import org.testcontainers.utility.MountableFile +import java.nio.file.Files +import java.nio.file.Path +import java.time.Duration +import kotlin.concurrent.Volatile +import kotlin.io.path.deleteIfExists + +object MqttBrokerManager { + var broker: GenericContainer<*>? = null + val lock = Any() + + fun setupMqtt(testClassName: String, port: Int = 1883) { + synchronized(lock) { + if (broker == null) { + val mosquittoConfig: Path = Files.createTempFile("${testClassName}_mosquitto_", ".conf") + Files.write( + mosquittoConfig, listOf( + "allow_anonymous true", + "listener $port" + ) + ) + MqttBrokerContainer() + .withExposedPorts(port) + .withCopyFileToContainer( + MountableFile.forHostPath(mosquittoConfig.toString()), + "/mosquitto/config/mosquitto.conf" + ) + .apply { withStartupTimeout(Duration.ofSeconds(30)).start() } + .also { broker = it } + .also { setupProperties() } + .also { + // Add shutdown hook to stop broker at JVM exit + Runtime.getRuntime().addShutdownHook(Thread { + synchronized(lock) { + broker?.stop() + } + }) + } + mosquittoConfig.deleteIfExists() + } + } + } + + fun tearDownMQTT() { + synchronized(lock) { + SharedMqttClient.waitForShutdown() + // Broker is stopped by shutdown hook + } + } + + @Throws(JPServiceException::class) + private fun setupProperties() { + JPService.reset() + JPService.registerProperty(JPComPort::class.java, broker!!.firstMappedPort) + JPService.registerProperty(JPComHost::class.java, broker!!.host) + JPService.setupJUnitTestMode() + } + + class MqttBrokerContainer : GenericContainer(DockerImageName.parse("eclipse-mosquitto")) +} diff --git a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt index 1622d1220..4fbebc9a2 100644 --- a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt +++ b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt @@ -5,19 +5,7 @@ import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.Timeout import org.junit.jupiter.api.extension.ExtendWith -import org.openbase.jps.core.JPService -import org.openbase.jps.exception.JPServiceException -import org.openbase.jul.communication.jp.JPComHost -import org.openbase.jul.communication.jp.JPComPort -import org.openbase.jul.communication.mqtt.SharedMqttClient -import org.testcontainers.containers.GenericContainer import org.testcontainers.junit.jupiter.Testcontainers -import org.testcontainers.utility.DockerImageName -import org.testcontainers.utility.MountableFile -import java.nio.file.Files -import java.nio.file.Path -import java.time.Duration -import kotlin.io.path.deleteIfExists /*- * #%L @@ -46,67 +34,18 @@ import kotlin.io.path.deleteIfExists @Testcontainers open class MqttIntegrationTest { - companion object { - const val port = 1884 - var broker: GenericContainer<*>? = null - val lock = Any() - } - - private var usageCounter = 0 - @BeforeAll @Timeout(30) fun setupMqtt() { - synchronized(lock) { - if (usageCounter == 0) { - val mosquittoConfig: Path = Files.createTempFile("${this::class.java.simpleName}_mosquitto_", ".conf") - Files.write( - mosquittoConfig, listOf( - "allow_anonymous true", - "listener $port" - ) - ) - MqttBrokerContainer() - .withExposedPorts(port) - .withCopyFileToContainer( - MountableFile.forHostPath(mosquittoConfig.toString()), - "/mosquitto/config/mosquitto.conf" - ) - .apply { withStartupTimeout(Duration.ofSeconds(30)).start() } - .also { - if (broker?.takeIf { it.containerId != null } != null) - error("broker was already initialized!") - } - .also { broker = it } - .also { setupProperties() } - mosquittoConfig.deleteIfExists() - } - usageCounter++ - } + MqttBrokerManager.setupMqtt(this::class.java.simpleName, 1884) + setupCustomProperties() } @AfterAll @Timeout(30) fun tearDownMQTT() { - synchronized(lock) { - SharedMqttClient.waitForShutdown() - usageCounter-- - if (usageCounter == 0) { - //waitForShutdown() - broker?.stop() - }} + MqttBrokerManager.tearDownMQTT() } - @Throws(JPServiceException::class) - private fun setupProperties() { - JPService.reset() - JPService.registerProperty(JPComPort::class.java, broker!!.firstMappedPort) - JPService.registerProperty(JPComHost::class.java, broker!!.host) - setupCustomProperties() - JPService.setupJUnitTestMode() - } - - class MqttBrokerContainer : GenericContainer(DockerImageName.parse("eclipse-mosquitto")) - open fun setupCustomProperties() {} } From b5b7d12b09b3d38dec3a33a539a7b2ba75b366d0 Mon Sep 17 00:00:00 2001 From: Divine Threepwood Date: Thu, 19 Mar 2026 00:31:24 +0100 Subject: [PATCH 05/10] cleanup code --- .../jul/communication/mqtt/AbstractIntegrationTest.kt | 6 ------ .../jul/communication/mqtt/test/MqttBrokerManager.kt | 7 ------- .../jul/communication/mqtt/test/MqttIntegrationTest.kt | 6 ------ 3 files changed, 19 deletions(-) diff --git a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt index 0c21d2623..297a4d8e8 100644 --- a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt +++ b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt @@ -19,12 +19,6 @@ open class AbstractIntegrationTest { MqttBrokerManager.setupMqtt(this::class.java.simpleName) } - @AfterAll - @Timeout(30) - fun cleanup() { - MqttBrokerManager.tearDownMQTT() - } - protected val brokerHost: String? get() = MqttBrokerManager.broker?.host protected val brokerPort: Int? get() = MqttBrokerManager.broker?.firstMappedPort diff --git a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttBrokerManager.kt b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttBrokerManager.kt index 7d9ea9eb8..516ea2a09 100644 --- a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttBrokerManager.kt +++ b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttBrokerManager.kt @@ -50,13 +50,6 @@ object MqttBrokerManager { } } - fun tearDownMQTT() { - synchronized(lock) { - SharedMqttClient.waitForShutdown() - // Broker is stopped by shutdown hook - } - } - @Throws(JPServiceException::class) private fun setupProperties() { JPService.reset() diff --git a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt index 4fbebc9a2..efb2174c1 100644 --- a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt +++ b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttIntegrationTest.kt @@ -41,11 +41,5 @@ open class MqttIntegrationTest { setupCustomProperties() } - @AfterAll - @Timeout(30) - fun tearDownMQTT() { - MqttBrokerManager.tearDownMQTT() - } - open fun setupCustomProperties() {} } From cb61f55de3d4466b8eef02cfe2707c0be3db5f9f Mon Sep 17 00:00:00 2001 From: Divine Threepwood Date: Sun, 29 Mar 2026 21:29:42 +0200 Subject: [PATCH 06/10] handle strange client behaviour that throws an not connected exception on disconnect while returing a connected state. --- .../openbase/jul/communication/mqtt/SharedMqttClient.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/module/communication/mqtt/src/main/java/org/openbase/jul/communication/mqtt/SharedMqttClient.kt b/module/communication/mqtt/src/main/java/org/openbase/jul/communication/mqtt/SharedMqttClient.kt index 827cbb0ba..20b5ded06 100644 --- a/module/communication/mqtt/src/main/java/org/openbase/jul/communication/mqtt/SharedMqttClient.kt +++ b/module/communication/mqtt/src/main/java/org/openbase/jul/communication/mqtt/SharedMqttClient.kt @@ -14,6 +14,7 @@ import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubscribeBuilder import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck import org.openbase.jul.communication.config.CommunicatorConfig +import org.openbase.jul.exception.tryOrNull import org.openbase.jul.iface.Shutdownable import java.util.* import java.util.concurrent.CompletableFuture @@ -52,7 +53,13 @@ object SharedMqttClient : Shutdownable { sharedClients.values .filter { (it as Mqtt5ClientWrapper).isConnected() } .map { it.disconnect() } - .map { it.get() } + .map { + runCatching { it.get() } + .getOrElse { t -> check(t.message == "com.hivemq.client.mqtt.exceptions.MqttClientStateException: MQTT client is not connected.") { + "Could not disconnect client connection: ${t.message}" } + null + } + } .run { sharedClients.clear() } @Synchronized From 5331478366a4809a4e3c09522db03f29d756c06f Mon Sep 17 00:00:00 2001 From: Divine Threepwood Date: Mon, 30 Mar 2026 11:53:34 +0200 Subject: [PATCH 07/10] fix FileSynchronizer null handling in java class. --- .../storage/registry/FileSynchronizedRegistryImpl.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/module/storage/src/main/java/org/openbase/jul/storage/registry/FileSynchronizedRegistryImpl.java b/module/storage/src/main/java/org/openbase/jul/storage/registry/FileSynchronizedRegistryImpl.java index 32eccfe7e..b2218e02a 100644 --- a/module/storage/src/main/java/org/openbase/jul/storage/registry/FileSynchronizedRegistryImpl.java +++ b/module/storage/src/main/java/org/openbase/jul/storage/registry/FileSynchronizedRegistryImpl.java @@ -213,10 +213,12 @@ public ENTRY remove(final ENTRY entry) throws CouldNotPerformException { fileSynchronizerMapLock.writeLock().unlock(); } - filePluginPool.beforeRemove(entry, fileSynchronizer); - fileSynchronizer.delete(); + if (fileSynchronizer != null) { + filePluginPool.beforeRemove(entry, fileSynchronizer); + fileSynchronizer.delete(); + filePluginPool.afterRemove(entry, fileSynchronizer); + } fileSynchronizerMap.remove(entry.getId()); - filePluginPool.afterRemove(entry, fileSynchronizer); return removedValue; } catch (InterruptedException ex) { Thread.currentThread().interrupt(); From fae838b7a818d5d4461b47e83c268b270c79b2a2 Mon Sep 17 00:00:00 2001 From: Divine Threepwood Date: Tue, 7 Apr 2026 00:11:15 +0200 Subject: [PATCH 08/10] Code improvements as requested. --- .../openbase/jul/communication/mqtt/SharedMqttClient.kt | 1 - .../jul/communication/mqtt/AbstractIntegrationTest.kt | 8 +++++++- .../openbase/jul/communication/mqtt/IntegrationTest.kt | 1 - .../jul/communication/mqtt/SharedMqttClientTest.kt | 5 ----- .../jul/communication/mqtt/test/MqttBrokerManager.kt | 5 ++++- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/module/communication/mqtt/src/main/java/org/openbase/jul/communication/mqtt/SharedMqttClient.kt b/module/communication/mqtt/src/main/java/org/openbase/jul/communication/mqtt/SharedMqttClient.kt index 20b5ded06..65fc5a9f0 100644 --- a/module/communication/mqtt/src/main/java/org/openbase/jul/communication/mqtt/SharedMqttClient.kt +++ b/module/communication/mqtt/src/main/java/org/openbase/jul/communication/mqtt/SharedMqttClient.kt @@ -14,7 +14,6 @@ import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5UnsubscribeBuilder import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.unsuback.Mqtt5UnsubAck import org.openbase.jul.communication.config.CommunicatorConfig -import org.openbase.jul.exception.tryOrNull import org.openbase.jul.iface.Shutdownable import java.util.* import java.util.concurrent.CompletableFuture diff --git a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt index 297a4d8e8..211e74a77 100644 --- a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt +++ b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/AbstractIntegrationTest.kt @@ -6,10 +6,10 @@ import org.junit.jupiter.api.AfterAll import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.TestInstance import org.junit.jupiter.api.Timeout +import org.openbase.jul.communication.config.CommunicatorConfig import org.openbase.jul.communication.mqtt.test.MqttBrokerManager import org.testcontainers.junit.jupiter.Testcontainers -//@Testcontainers @TestInstance(TestInstance.Lifecycle.PER_CLASS) open class AbstractIntegrationTest { @@ -22,6 +22,12 @@ open class AbstractIntegrationTest { protected val brokerHost: String? get() = MqttBrokerManager.broker?.host protected val brokerPort: Int? get() = MqttBrokerManager.broker?.firstMappedPort + + protected val config + get() = CommunicatorConfig( + hostname = brokerHost ?: error("Host not defined!"), + port = brokerPort ?: error("Port not defined!"), + ) } fun Mqtt5Publish.clearTimestamp() = let { diff --git a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/IntegrationTest.kt b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/IntegrationTest.kt index 857f4bcf0..aeb08a944 100644 --- a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/IntegrationTest.kt +++ b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/IntegrationTest.kt @@ -22,7 +22,6 @@ import kotlin.concurrent.withLock class IntegrationTest : AbstractIntegrationTest() { private val scope = ScopeProcessor.generateScope("/test/integration") - private val config get() = CommunicatorConfig(brokerHost!!, brokerPort!!) internal class MethodMock { val lock = ReentrantLock() diff --git a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/SharedMqttClientTest.kt b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/SharedMqttClientTest.kt index 5a4dbc53b..42233e979 100644 --- a/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/SharedMqttClientTest.kt +++ b/module/communication/mqtt/src/test/java/org/openbase/jul/communication/mqtt/SharedMqttClientTest.kt @@ -1,8 +1,6 @@ package org.openbase.jul.communication.mqtt -import com.hivemq.client.internal.mqtt.util.MqttChecks.unsubscribe import com.hivemq.client.mqtt.datatypes.MqttQos -import com.hivemq.client.mqtt.mqtt5.message.publish.Mqtt5Publish import com.hivemq.client.mqtt.mqtt5.message.subscribe.Mqtt5Subscribe import com.hivemq.client.mqtt.mqtt5.message.unsubscribe.Mqtt5Unsubscribe import org.junit.jupiter.api.Test @@ -12,9 +10,6 @@ import org.openbase.jul.communication.config.CommunicatorConfig internal class SharedMqttClientTest : AbstractIntegrationTest() { - private val config get() = CommunicatorConfig(brokerHost!!, brokerPort!!) - - @Test @Timeout(value = 30) fun `shutdown should be work as expected`() { diff --git a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttBrokerManager.kt b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttBrokerManager.kt index 516ea2a09..fde89eafe 100644 --- a/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttBrokerManager.kt +++ b/module/communication/mqtttest/src/main/kotlin/org/openbase/jul/communication/mqtt/test/MqttBrokerManager.kt @@ -15,6 +15,9 @@ import kotlin.concurrent.Volatile import kotlin.io.path.deleteIfExists object MqttBrokerManager { + + val STARTUP_TIMEOUT: Duration = Duration.ofSeconds(30) + var broker: GenericContainer<*>? = null val lock = Any() @@ -34,7 +37,7 @@ object MqttBrokerManager { MountableFile.forHostPath(mosquittoConfig.toString()), "/mosquitto/config/mosquitto.conf" ) - .apply { withStartupTimeout(Duration.ofSeconds(30)).start() } + .apply { withStartupTimeout(STARTUP_TIMEOUT).start() } .also { broker = it } .also { setupProperties() } .also { From 3e8136f8fde784591a4cbae094ba90dd7ed72028 Mon Sep 17 00:00:00 2001 From: LukBelter Date: Thu, 9 Apr 2026 20:49:02 +0200 Subject: [PATCH 09/10] Update outdated actions in workflows to latest versions --- .github/workflows/build-and-test.yml | 14 +++++++------- .github/workflows/inspect-code.yml | 6 +++--- .github/workflows/publish-jars.yml | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 3f81fcee6..8eeda6b75 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -22,16 +22,16 @@ jobs: steps: - name: "Checkout Branch" - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: "Setup Java" - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '21' - name: Setup Gradle cache - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.gradle key: ${{ runner.os }}-gradle-${{ hashFiles('build.gradle') }} @@ -59,16 +59,16 @@ jobs: steps: - name: "Checkout Branch" - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: "Setup Java" - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '21' - name: Setup Gradle cache - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: ~/.gradle key: ${{ runner.os }}-gradle-${{ hashFiles('build.gradle') }} @@ -81,7 +81,7 @@ jobs: RUN_LONG_INTEGRATION_TESTS: false - name: Upload Gradle reports - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 if: ${{ failure() }} with: name: Test Backend Reports diff --git a/.github/workflows/inspect-code.yml b/.github/workflows/inspect-code.yml index aabd2a236..eef2c64ef 100644 --- a/.github/workflows/inspect-code.yml +++ b/.github/workflows/inspect-code.yml @@ -27,7 +27,7 @@ on: env: # Release tag associated with version of Detekt to be installed # SARIF support (required for this workflow) was introduced in Detekt v1.15.0 - DETEKT_RELEASE_TAG: v1.15.0 + DETEKT_RELEASE_TAG: v1.23.8 # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -40,7 +40,7 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - uses: actions/checkout@v2 + - uses: actions/checkout@v6 # Gets the download URL associated with the $DETEKT_RELEASE_TAG - name: Get Detekt download URL @@ -96,7 +96,7 @@ jobs: )" > ${{ github.workspace }}/detekt.sarif.json # Uploads results to GitHub repository using the upload-sarif action - - uses: github/codeql-action/upload-sarif@v1 + - uses: github/codeql-action/upload-sarif@v4 with: # Path to SARIF file relative to the root of the repository sarif_file: ${{ github.workspace }}/detekt.sarif.json diff --git a/.github/workflows/publish-jars.yml b/.github/workflows/publish-jars.yml index dd2e95d27..fa20bcb87 100644 --- a/.github/workflows/publish-jars.yml +++ b/.github/workflows/publish-jars.yml @@ -14,19 +14,19 @@ jobs: packages: write steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set up Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: '21' distribution: 'adopt' - name: Validate Gradle wrapper - uses: gradle/actions/wrapper-validation@v3.5.0 + uses: gradle/actions/wrapper-validation@v6 - name: Publish Packages - uses: gradle/actions/setup-gradle@v3.5.0 + uses: gradle/actions/setup-gradle@v6 with: arguments: publishToSonatype closeAndReleaseSonatypeStagingRepository env: From 6e3840a4eb94b44de086e19ad3fbdba665bd5b3f Mon Sep 17 00:00:00 2001 From: LukBelter Date: Thu, 9 Apr 2026 21:15:01 +0200 Subject: [PATCH 10/10] switch detekt version back to v1.15.0 --- .github/workflows/inspect-code.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/inspect-code.yml b/.github/workflows/inspect-code.yml index eef2c64ef..ca075ffd1 100644 --- a/.github/workflows/inspect-code.yml +++ b/.github/workflows/inspect-code.yml @@ -27,7 +27,7 @@ on: env: # Release tag associated with version of Detekt to be installed # SARIF support (required for this workflow) was introduced in Detekt v1.15.0 - DETEKT_RELEASE_TAG: v1.23.8 + DETEKT_RELEASE_TAG: v1.15.0 # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -62,7 +62,8 @@ jobs: } ' | \ jq --raw-output '.data.repository.release.releaseAssets.nodes[0].downloadUrl' ) - echo "::set-output name=download_url::$DETEKT_DOWNLOAD_URL" + echo "download_url=$DETEKT_DOWNLOAD_URL" >> $GITHUB_OUTPUT + echo "Detekt download URL: $DETEKT_DOWNLOAD_URL" # Sets up the detekt cli - name: Setup Detekt