Skip to content

Commit a616fa3

Browse files
authored
[homie] Enable and fix tests (#21416)
Signed-off-by: Leo Siepel <leosiepel@gmail.com>
1 parent 933db81 commit a616fa3

1 file changed

Lines changed: 40 additions & 22 deletions

File tree

itests/org.openhab.binding.homie.tests/src/main/java/org/openhab/binding/mqtt/homie/HomieImplementationTest.java

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import static org.mockito.ArgumentMatchers.*;
1919
import static org.mockito.Mockito.*;
2020

21+
import java.nio.charset.StandardCharsets;
2122
import java.util.ArrayList;
2223
import java.util.Collections;
2324
import java.util.List;
@@ -26,11 +27,11 @@
2627
import java.util.concurrent.ScheduledExecutorService;
2728
import java.util.concurrent.ScheduledThreadPoolExecutor;
2829
import java.util.concurrent.TimeUnit;
30+
import java.util.concurrent.TimeoutException;
2931

3032
import org.eclipse.jdt.annotation.NonNullByDefault;
3133
import org.junit.jupiter.api.AfterEach;
3234
import org.junit.jupiter.api.BeforeEach;
33-
import org.junit.jupiter.api.Disabled;
3435
import org.junit.jupiter.api.Test;
3536
import org.junit.jupiter.api.extension.ExtendWith;
3637
import org.mockito.Mock;
@@ -51,10 +52,10 @@
5152
import org.openhab.binding.homie.internal.homie300.PropertyHelper;
5253
import org.openhab.binding.mqtt.generic.ChannelState;
5354
import org.openhab.binding.mqtt.generic.tools.ChildMap;
54-
import org.openhab.binding.mqtt.generic.tools.WaitForTopicValue;
5555
import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
5656
import org.openhab.core.io.transport.mqtt.MqttConnectionObserver;
5757
import org.openhab.core.io.transport.mqtt.MqttConnectionState;
58+
import org.openhab.core.io.transport.mqtt.MqttMessageSubscriber;
5859
import org.openhab.core.library.types.OnOffType;
5960
import org.openhab.core.library.types.QuantityType;
6061
import org.openhab.core.library.unit.SIUnits;
@@ -64,6 +65,7 @@
6465
* A full implementation test, that starts the embedded MQTT broker and publishes a homie device tree.
6566
*
6667
* @author David Graeff - Initial contribution
68+
* @author Leo Siepel - Test stabilization refactoring
6769
*/
6870
@ExtendWith(MockitoExtension.class)
6971
@MockitoSettings(strictness = Strictness.LENIENT)
@@ -72,6 +74,7 @@ public class HomieImplementationTest extends MqttOSGiTest {
7274
private static final String BASE_TOPIC = "homie";
7375
private static final String DEVICE_ID = ThingChannelConstants.TEST_HOMIE_THING.getId();
7476
private static final String DEVICE_TOPIC = BASE_TOPIC + "/" + DEVICE_ID;
77+
private static final int MQTT_TIMEOUT = 10000;
7578

7679
private @NonNullByDefault({}) MqttBrokerConnection homieConnection;
7780
private int registeredTopics = 100;
@@ -165,15 +168,21 @@ public void retrieveAllTopics() throws Exception {
165168
"Connection " + homieConnection.getClientId() + " not retrieving all topics ");
166169
}
167170

168-
@Disabled("https://github.com/openhab/openhab-addons/issues/12667")
169171
@Test
170172
public void retrieveOneAttribute() throws Exception {
171-
WaitForTopicValue watcher = new WaitForTopicValue(homieConnection, DEVICE_TOPIC + "/$homie");
172-
assertThat(watcher.waitForTopicValue(1000), is("3.0"));
173+
String topic = DEVICE_TOPIC + "/$homie";
174+
CompletableFuture<String> receivedValue = new CompletableFuture<>();
175+
MqttMessageSubscriber subscriber = (receivedTopic, payload) -> receivedValue
176+
.complete(new String(payload, StandardCharsets.UTF_8));
177+
try {
178+
assertTrue(homieConnection.subscribe(topic, subscriber).get(5, TimeUnit.SECONDS));
179+
assertThat(receivedValue.get(MQTT_TIMEOUT, TimeUnit.MILLISECONDS), is("3.0"));
180+
} finally {
181+
homieConnection.unsubscribe(topic, subscriber).get(5, TimeUnit.SECONDS);
182+
}
173183
}
174184

175185
@SuppressWarnings("null")
176-
@Disabled("Temporarily disabled: unstable")
177186
@Test
178187
public void retrieveAttributes() throws Exception {
179188
assertThat(homieConnection.hasSubscribers(), is(false));
@@ -183,9 +192,6 @@ public void retrieveAttributes() throws Exception {
183192
Property property = spy(
184193
new Property(DEVICE_TOPIC + "/testnode", node, "temperature", callback, new PropertyAttributes()));
185194

186-
// Create a scheduler
187-
ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(4);
188-
189195
property.subscribe(homieConnection, scheduler, 500).get();
190196

191197
assertThat(property.attributes.settable, is(true));
@@ -202,8 +208,8 @@ public void retrieveAttributes() throws Exception {
202208

203209
property.startChannel(homieConnection, scheduler, 500).get();
204210
verify(channelState).start(any(), any(), anyInt());
205-
verify(channelState, timeout(500)).processMessage(any(), any());
206-
verify(callback).updateChannelState(any(), any());
211+
verify(callback, timeout(MQTT_TIMEOUT)).updateChannelState(any(), any());
212+
verify(channelState).processMessage(any(), any());
207213

208214
assertThat(property.getChannelState().getCache().getChannelState(),
209215
is(new QuantityType<>(10, SIUnits.CELSIUS)));
@@ -231,7 +237,6 @@ public Node createSpyNode(InvocationOnMock invocation) {
231237
}
232238

233239
@SuppressWarnings("null")
234-
@Disabled("Temporarily disabled: unstable")
235240
@Test
236241
public void parseHomieTree() throws Exception {
237242
// Create a Homie Device object. Because spied Nodes are required for call verification,
@@ -297,21 +302,34 @@ public void parseHomieTree() throws Exception {
297302
device.startChannels(homieConnection, scheduler, 50, handler).get();
298303
assertThat(propertyBell.getChannelState().isStateful(), is(false));
299304
assertThat(propertyBell.getChannelState().getCache().getChannelState(), is(UnDefType.UNDEF));
300-
assertThat(property.getChannelState().getCache().getChannelState(),
301-
is(new QuantityType<>(10, SIUnits.CELSIUS)));
305+
Property temperatureProperty = property;
306+
waitForAssert(() -> assertThat(temperatureProperty.getChannelState().getCache().getChannelState(),
307+
is(new QuantityType<>(10, SIUnits.CELSIUS))));
302308

303309
property = node.properties.get("testRetain");
304-
WaitForTopicValue watcher = new WaitForTopicValue(brokerConnection, propertyTestTopic + "/set");
305-
// Watch the topic. Publish a retain=false value to MQTT
306-
property.getChannelState().publishValue(OnOffType.OFF).get();
307-
assertThat(watcher.waitForTopicValue(10000), is("false"));
310+
String commandTopic = propertyTestTopic + "/set";
311+
CompletableFuture<String> receivedValue = new CompletableFuture<>();
312+
MqttMessageSubscriber subscriber = (topic, payload) -> receivedValue
313+
.complete(new String(payload, StandardCharsets.UTF_8));
314+
try {
315+
assertTrue(brokerConnection.subscribe(commandTopic, subscriber).get(5, TimeUnit.SECONDS));
316+
property.getChannelState().publishValue(OnOffType.OFF).get();
317+
assertThat(receivedValue.get(MQTT_TIMEOUT, TimeUnit.MILLISECONDS), is("false"));
318+
} finally {
319+
brokerConnection.unsubscribe(commandTopic, subscriber).get(5, TimeUnit.SECONDS);
320+
}
308321

309322
// Publish a retain=false value to MQTT.
310323
property.getChannelState().publishValue(OnOffType.ON).get();
311324
// No value is expected to be retained on this MQTT topic
312-
waitForAssert(() -> {
313-
WaitForTopicValue w = new WaitForTopicValue(brokerConnection, propertyTestTopic + "/set");
314-
assertNull(w.waitForTopicValue(50));
315-
}, 500, 100);
325+
CompletableFuture<String> retainedValue = new CompletableFuture<>();
326+
MqttMessageSubscriber retainedSubscriber = (topic, payload) -> retainedValue
327+
.complete(new String(payload, StandardCharsets.UTF_8));
328+
try {
329+
assertTrue(brokerConnection.subscribe(commandTopic, retainedSubscriber).get(5, TimeUnit.SECONDS));
330+
assertThrows(TimeoutException.class, () -> retainedValue.get(1, TimeUnit.SECONDS));
331+
} finally {
332+
brokerConnection.unsubscribe(commandTopic, retainedSubscriber).get(5, TimeUnit.SECONDS);
333+
}
316334
}
317335
}

0 commit comments

Comments
 (0)