2 * Copyright (c) 2010-2020 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.mqtt.generic.mapping;
15 import static java.lang.annotation.ElementType.FIELD;
16 import static org.hamcrest.CoreMatchers.is;
17 import static org.junit.Assert.*;
18 import static org.mockito.ArgumentMatchers.any;
19 import static org.mockito.Mockito.doReturn;
21 import java.lang.annotation.Retention;
22 import java.lang.annotation.RetentionPolicy;
23 import java.lang.annotation.Target;
24 import java.lang.reflect.Field;
25 import java.math.BigDecimal;
26 import java.util.concurrent.CompletableFuture;
27 import java.util.concurrent.ExecutionException;
28 import java.util.concurrent.ScheduledExecutorService;
29 import java.util.concurrent.ScheduledThreadPoolExecutor;
30 import java.util.concurrent.TimeUnit;
31 import java.util.concurrent.TimeoutException;
33 import org.eclipse.jdt.annotation.NonNull;
34 import org.eclipse.jdt.annotation.Nullable;
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.mockito.Mock;
38 import org.mockito.MockitoAnnotations;
39 import org.openhab.binding.mqtt.generic.mapping.SubscribeFieldToMQTTtopic.FieldChanged;
40 import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
43 * Tests cases for {@link org.openhab.binding.mqtt.generic.mapping.SubscribeFieldToMQTTtopic}.
45 * @author David Graeff - Initial contribution
47 public class SubscribeFieldToMQTTtopicTests {
48 @Retention(RetentionPolicy.RUNTIME)
50 private @interface TestValue {
51 String value() default "";
55 public static class Attributes extends AbstractMqttAttributeClass {
56 @SuppressWarnings("unused")
57 public transient String ignoreTransient = "";
58 @SuppressWarnings("unused")
59 public final String ignoreFinal = "";
61 public @TestValue("string") String aString;
62 public @TestValue("false") Boolean aBoolean;
63 public @TestValue("10") Long aLong;
64 public @TestValue("10") Integer aInteger;
65 public @TestValue("10") BigDecimal aDecimal;
67 public @TestValue("10") @TopicPrefix("a") int Int = 24;
68 public @TestValue("false") boolean aBool = true;
69 public @TestValue("abc,def") @MQTTvalueTransform(splitCharacter = ",") String[] properties;
71 public enum ReadyState {
77 public @TestValue("init") ReadyState state = ReadyState.unknown;
79 public enum DataTypeEnum {
85 public @TestValue("integer") @MQTTvalueTransform(suffix = "_") DataTypeEnum datatype = DataTypeEnum.unknown;
88 public @NonNull Object getFieldsOf() {
93 Attributes attributes = new Attributes();
96 MqttBrokerConnection connection;
99 SubscribeFieldToMQTTtopic fieldSubscriber;
102 FieldChanged fieldChanged;
105 public void setUp() {
106 MockitoAnnotations.initMocks(this);
107 doReturn(CompletableFuture.completedFuture(true)).when(connection).subscribe(any(), any());
110 @Test(expected = TimeoutException.class)
111 public void TimeoutIfNoMessageReceive()
112 throws InterruptedException, NoSuchFieldException, ExecutionException, TimeoutException {
113 final Field field = Attributes.class.getField("Int");
114 ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
116 SubscribeFieldToMQTTtopic subscriber = new SubscribeFieldToMQTTtopic(scheduler, field, fieldChanged,
117 "homie/device123", false);
118 subscriber.subscribeAndReceive(connection, 1000).get(50, TimeUnit.MILLISECONDS);
121 @Test(expected = ExecutionException.class)
122 public void MandatoryMissing()
123 throws InterruptedException, NoSuchFieldException, ExecutionException, TimeoutException {
124 final Field field = Attributes.class.getField("Int");
125 ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
127 SubscribeFieldToMQTTtopic subscriber = new SubscribeFieldToMQTTtopic(scheduler, field, fieldChanged,
128 "homie/device123", true);
129 subscriber.subscribeAndReceive(connection, 50).get();
133 public void MessageReceive()
134 throws InterruptedException, NoSuchFieldException, ExecutionException, TimeoutException {
135 final FieldChanged changed = (field, value) -> {
137 field.set(attributes.getFieldsOf(), value);
138 } catch (IllegalArgumentException | IllegalAccessException e) {
139 fail(e.getMessage());
142 final Field field = Attributes.class.getField("Int");
143 ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
145 SubscribeFieldToMQTTtopic subscriber = new SubscribeFieldToMQTTtopic(scheduler, field, changed,
146 "homie/device123", false);
147 CompletableFuture<@Nullable Void> future = subscriber.subscribeAndReceive(connection, 1000);
149 // Simulate a received MQTT message
150 subscriber.processMessage("ignored", "10".getBytes());
151 // No timeout should happen
152 future.get(50, TimeUnit.MILLISECONDS);
153 assertThat(attributes.Int, is(10));