]> git.basschouten.com Git - openhab-addons.git/blob
75b6b3842c6a8a32150d99de8966ad0b965fcd4d
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.mqtt.generic.mapping;
14
15 import static java.lang.annotation.ElementType.FIELD;
16 import static org.hamcrest.CoreMatchers.is;
17 import static org.hamcrest.MatcherAssert.assertThat;
18 import static org.junit.jupiter.api.Assertions.*;
19 import static org.mockito.ArgumentMatchers.any;
20 import static org.mockito.Mockito.doReturn;
21
22 import java.lang.annotation.Retention;
23 import java.lang.annotation.RetentionPolicy;
24 import java.lang.annotation.Target;
25 import java.lang.reflect.Field;
26 import java.math.BigDecimal;
27 import java.util.concurrent.CompletableFuture;
28 import java.util.concurrent.ExecutionException;
29 import java.util.concurrent.ScheduledExecutorService;
30 import java.util.concurrent.ScheduledThreadPoolExecutor;
31 import java.util.concurrent.TimeUnit;
32 import java.util.concurrent.TimeoutException;
33
34 import org.eclipse.jdt.annotation.NonNull;
35 import org.eclipse.jdt.annotation.Nullable;
36 import org.junit.jupiter.api.BeforeEach;
37 import org.junit.jupiter.api.Test;
38 import org.junit.jupiter.api.extension.ExtendWith;
39 import org.mockito.Mock;
40 import org.mockito.junit.jupiter.MockitoExtension;
41 import org.mockito.junit.jupiter.MockitoSettings;
42 import org.mockito.quality.Strictness;
43 import org.openhab.binding.mqtt.generic.mapping.SubscribeFieldToMQTTtopic.FieldChanged;
44 import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
45
46 /**
47  * Tests cases for {@link org.openhab.binding.mqtt.generic.mapping.SubscribeFieldToMQTTtopic}.
48  *
49  * @author David Graeff - Initial contribution
50  */
51 @ExtendWith(MockitoExtension.class)
52 @MockitoSettings(strictness = Strictness.WARN)
53 public class SubscribeFieldToMQTTtopicTests {
54     @Retention(RetentionPolicy.RUNTIME)
55     @Target({ FIELD })
56     private @interface TestValue {
57         String value() default "";
58     }
59
60     @TopicPrefix
61     public static class Attributes extends AbstractMqttAttributeClass {
62         @SuppressWarnings("unused")
63         public transient String ignoreTransient = "";
64         @SuppressWarnings("unused")
65         public final String ignoreFinal = "";
66
67         public @TestValue("string") String aString;
68         public @TestValue("false") Boolean aBoolean;
69         public @TestValue("10") Long aLong;
70         public @TestValue("10") Integer aInteger;
71         public @TestValue("10") BigDecimal aDecimal;
72
73         public @TestValue("10") @TopicPrefix("a") int Int = 24;
74         public @TestValue("false") boolean aBool = true;
75         public @TestValue("abc,def") @MQTTvalueTransform(splitCharacter = ",") String[] properties;
76
77         public enum ReadyState {
78             unknown,
79             init,
80             ready,
81         }
82
83         public @TestValue("init") ReadyState state = ReadyState.unknown;
84
85         public enum DataTypeEnum {
86             unknown,
87             integer_,
88             float_,
89         }
90
91         public @TestValue("integer") @MQTTvalueTransform(suffix = "_") DataTypeEnum datatype = DataTypeEnum.unknown;
92
93         @Override
94         public @NonNull Object getFieldsOf() {
95             return this;
96         }
97     }
98
99     Attributes attributes = new Attributes();
100
101     @Mock
102     MqttBrokerConnection connection;
103
104     @Mock
105     SubscribeFieldToMQTTtopic fieldSubscriber;
106
107     @Mock
108     FieldChanged fieldChanged;
109
110     @BeforeEach
111     public void setUp() {
112         doReturn(CompletableFuture.completedFuture(true)).when(connection).subscribe(any(), any());
113     }
114
115     @Test
116     public void TimeoutIfNoMessageReceive()
117             throws InterruptedException, NoSuchFieldException, ExecutionException, TimeoutException {
118         final Field field = Attributes.class.getField("Int");
119         ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
120
121         SubscribeFieldToMQTTtopic subscriber = new SubscribeFieldToMQTTtopic(scheduler, field, fieldChanged,
122                 "homie/device123", false);
123         assertThrows(TimeoutException.class,
124                 () -> subscriber.subscribeAndReceive(connection, 1000).get(50, TimeUnit.MILLISECONDS));
125     }
126
127     @Test
128     public void MandatoryMissing()
129             throws InterruptedException, NoSuchFieldException, ExecutionException, TimeoutException {
130         final Field field = Attributes.class.getField("Int");
131         ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
132
133         SubscribeFieldToMQTTtopic subscriber = new SubscribeFieldToMQTTtopic(scheduler, field, fieldChanged,
134                 "homie/device123", true);
135         assertThrows(ExecutionException.class, () -> subscriber.subscribeAndReceive(connection, 50).get());
136     }
137
138     @Test
139     public void MessageReceive()
140             throws InterruptedException, NoSuchFieldException, ExecutionException, TimeoutException {
141         final FieldChanged changed = (field, value) -> {
142             try {
143                 field.set(attributes.getFieldsOf(), value);
144             } catch (IllegalArgumentException | IllegalAccessException e) {
145                 fail(e.getMessage());
146             }
147         };
148         final Field field = Attributes.class.getField("Int");
149         ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
150
151         SubscribeFieldToMQTTtopic subscriber = new SubscribeFieldToMQTTtopic(scheduler, field, changed,
152                 "homie/device123", false);
153         CompletableFuture<@Nullable Void> future = subscriber.subscribeAndReceive(connection, 1000);
154
155         // Simulate a received MQTT message
156         subscriber.processMessage("ignored", "10".getBytes());
157         // No timeout should happen
158         future.get(50, TimeUnit.MILLISECONDS);
159         assertThat(attributes.Int, is(10));
160     }
161 }