]> git.basschouten.com Git - openhab-addons.git/blob
989bc1e3ed99de55a4fb1765c8331ed5272fb607
[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.homeassistant.internal;
14
15 import static org.mockito.Mockito.any;
16 import static org.mockito.Mockito.anyBoolean;
17 import static org.mockito.Mockito.anyInt;
18 import static org.mockito.Mockito.doAnswer;
19 import static org.mockito.Mockito.doReturn;
20 import static org.mockito.Mockito.spy;
21 import static org.mockito.Mockito.when;
22
23 import java.io.IOException;
24 import java.net.URISyntaxException;
25 import java.nio.file.Files;
26 import java.nio.file.Path;
27 import java.nio.file.Paths;
28 import java.util.Set;
29 import java.util.UUID;
30 import java.util.concurrent.CompletableFuture;
31 import java.util.concurrent.ConcurrentHashMap;
32 import java.util.concurrent.ConcurrentMap;
33
34 import org.eclipse.jdt.annotation.NonNullByDefault;
35 import org.junit.jupiter.api.Assertions;
36 import org.junit.jupiter.api.BeforeEach;
37 import org.junit.jupiter.api.extension.ExtendWith;
38 import org.mockito.Mock;
39 import org.mockito.junit.jupiter.MockitoExtension;
40 import org.mockito.junit.jupiter.MockitoSettings;
41 import org.mockito.quality.Strictness;
42 import org.openhab.binding.mqtt.generic.MqttChannelTypeProvider;
43 import org.openhab.binding.mqtt.generic.TransformationServiceProvider;
44 import org.openhab.binding.mqtt.handler.BrokerHandler;
45 import org.openhab.core.io.transport.mqtt.MqttBrokerConnection;
46 import org.openhab.core.io.transport.mqtt.MqttMessageSubscriber;
47 import org.openhab.core.test.java.JavaTest;
48 import org.openhab.core.thing.Bridge;
49 import org.openhab.core.thing.Thing;
50 import org.openhab.core.thing.ThingStatus;
51 import org.openhab.core.thing.ThingStatusDetail;
52 import org.openhab.core.thing.ThingStatusInfo;
53 import org.openhab.core.thing.ThingTypeUID;
54 import org.openhab.core.thing.ThingUID;
55 import org.openhab.core.thing.binding.builder.BridgeBuilder;
56 import org.openhab.core.thing.binding.builder.ThingBuilder;
57 import org.openhab.core.thing.type.ThingTypeBuilder;
58 import org.openhab.core.thing.type.ThingTypeRegistry;
59 import org.openhab.transform.jinja.internal.JinjaTransformationService;
60 import org.openhab.transform.jinja.internal.profiles.JinjaTransformationProfile;
61
62 /**
63  * Abstract class for HomeAssistant unit tests.
64  *
65  * @author Anton Kharuzhy - Initial contribution
66  */
67 @SuppressWarnings({ "ConstantConditions" })
68 @ExtendWith(MockitoExtension.class)
69 @MockitoSettings(strictness = Strictness.WARN)
70 @NonNullByDefault
71 public abstract class AbstractHomeAssistantTests extends JavaTest {
72     public static final String BINDING_ID = "mqtt";
73
74     public static final String BRIDGE_TYPE_ID = "broker";
75     public static final String BRIDGE_TYPE_LABEL = "MQTT Broker";
76     public static final ThingTypeUID BRIDGE_TYPE_UID = new ThingTypeUID(BINDING_ID, BRIDGE_TYPE_ID);
77     public static final String BRIDGE_ID = UUID.randomUUID().toString();
78     public static final ThingUID BRIDGE_UID = new ThingUID(BRIDGE_TYPE_UID, BRIDGE_ID);
79
80     public static final String HA_TYPE_ID = "homeassistant";
81     public static final String HA_TYPE_LABEL = "Homeassistant";
82     public static final ThingTypeUID HA_TYPE_UID = new ThingTypeUID(BINDING_ID, HA_TYPE_ID);
83     public static final String HA_ID = UUID.randomUUID().toString();
84     public static final ThingUID HA_UID = new ThingUID(HA_TYPE_UID, HA_ID);
85
86     protected @Mock @NonNullByDefault({}) MqttBrokerConnection bridgeConnection;
87     protected @Mock @NonNullByDefault({}) ThingTypeRegistry thingTypeRegistry;
88     protected @Mock @NonNullByDefault({}) TransformationServiceProvider transformationServiceProvider;
89
90     @SuppressWarnings("NotNullFieldNotInitialized")
91     protected @NonNullByDefault({}) MqttChannelTypeProvider channelTypeProvider;
92
93     protected final Bridge bridgeThing = BridgeBuilder.create(BRIDGE_TYPE_UID, BRIDGE_UID).build();
94     protected final BrokerHandler bridgeHandler = spy(new BrokerHandler(bridgeThing));
95     protected final Thing haThing = ThingBuilder.create(HA_TYPE_UID, HA_UID).withBridge(BRIDGE_UID).build();
96     protected final ConcurrentMap<String, Set<MqttMessageSubscriber>> subscriptions = new ConcurrentHashMap<>();
97
98     private final JinjaTransformationService jinjaTransformationService = new JinjaTransformationService();
99
100     @BeforeEach
101     public void beforeEachAbstractHomeAssistantTests() {
102         when(thingTypeRegistry.getThingType(BRIDGE_TYPE_UID))
103                 .thenReturn(ThingTypeBuilder.instance(BRIDGE_TYPE_UID, BRIDGE_TYPE_LABEL).build());
104         when(thingTypeRegistry.getThingType(HA_TYPE_UID))
105                 .thenReturn(ThingTypeBuilder.instance(HA_TYPE_UID, HA_TYPE_LABEL).build());
106         when(transformationServiceProvider
107                 .getTransformationService(JinjaTransformationProfile.PROFILE_TYPE_UID.getId()))
108                         .thenReturn(jinjaTransformationService);
109
110         channelTypeProvider = spy(new MqttChannelTypeProvider(thingTypeRegistry));
111
112         setupConnection();
113
114         // Return the mocked connection object if the bridge handler is asked for it
115         when(bridgeHandler.getConnectionAsync()).thenReturn(CompletableFuture.completedFuture(bridgeConnection));
116
117         bridgeThing.setStatusInfo(new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.ONLINE.NONE, ""));
118         bridgeThing.setHandler(bridgeHandler);
119
120         haThing.setStatusInfo(new ThingStatusInfo(ThingStatus.ONLINE, ThingStatusDetail.ONLINE.NONE, ""));
121     }
122
123     protected void setupConnection() {
124         doAnswer(invocation -> {
125             final var topic = (String) invocation.getArgument(0);
126             final var subscriber = (MqttMessageSubscriber) invocation.getArgument(1);
127
128             subscriptions.putIfAbsent(topic, ConcurrentHashMap.newKeySet());
129             subscriptions.get(topic).add(subscriber);
130             return CompletableFuture.completedFuture(true);
131         }).when(bridgeConnection).subscribe(any(), any());
132
133         doAnswer(invocation -> {
134             final var topic = (String) invocation.getArgument(0);
135             final var subscriber = (MqttMessageSubscriber) invocation.getArgument(1);
136             final var topicSubscriptions = subscriptions.get(topic);
137
138             if (topicSubscriptions != null) {
139                 topicSubscriptions.remove(subscriber);
140             }
141             return CompletableFuture.completedFuture(true);
142         }).when(bridgeConnection).unsubscribe(any(), any());
143
144         doAnswer(invocation -> {
145             subscriptions.clear();
146             return CompletableFuture.completedFuture(true);
147         }).when(bridgeConnection).unsubscribeAll();
148
149         doReturn(CompletableFuture.completedFuture(true)).when(bridgeConnection).publish(any(), any(), anyInt(),
150                 anyBoolean());
151     }
152
153     /**
154      * @param relativePath path from src/test/java/org/openhab/binding/mqtt/homeassistant/internal
155      * @return path
156      */
157     protected Path getResourcePath(String relativePath) {
158         try {
159             return Paths.get(AbstractHomeAssistantTests.class.getResource(relativePath).toURI());
160         } catch (URISyntaxException e) {
161             Assertions.fail(e);
162         }
163         throw new IllegalArgumentException();
164     }
165
166     protected String getResourceAsString(String relativePath) {
167         try {
168             return Files.readString(getResourcePath(relativePath));
169         } catch (IOException e) {
170             Assertions.fail(e);
171         }
172         throw new IllegalArgumentException();
173     }
174
175     protected byte[] getResourceAsByteArray(String relativePath) {
176         try {
177             return Files.readAllBytes(getResourcePath(relativePath));
178         } catch (IOException e) {
179             Assertions.fail(e);
180         }
181         throw new IllegalArgumentException();
182     }
183
184     protected static String configTopicToMqtt(String configTopic) {
185         return HandlerConfiguration.DEFAULT_BASETOPIC + "/" + configTopic + "/config";
186     }
187 }