2 * Copyright (c) 2010-2024 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.mielecloud.internal.webservice;
15 import static org.junit.jupiter.api.Assertions.assertNotNull;
16 import static org.mockito.ArgumentMatchers.any;
17 import static org.mockito.Mockito.*;
18 import static org.openhab.binding.mielecloud.internal.util.MockUtil.mockDevice;
20 import java.util.Arrays;
21 import java.util.HashSet;
22 import java.util.Objects;
23 import java.util.concurrent.ExecutionException;
24 import java.util.concurrent.TimeoutException;
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
28 import org.junit.jupiter.api.BeforeEach;
29 import org.junit.jupiter.api.Test;
30 import org.openhab.binding.mielecloud.internal.webservice.api.ActionsState;
31 import org.openhab.binding.mielecloud.internal.webservice.api.DeviceState;
32 import org.openhab.binding.mielecloud.internal.webservice.api.json.Actions;
33 import org.openhab.binding.mielecloud.internal.webservice.api.json.Device;
34 import org.openhab.binding.mielecloud.internal.webservice.api.json.DeviceCollection;
37 * @author Björn Lange - Initial contribution
40 public class DeviceStateDispatcherTest {
41 private static final String FIRST_DEVICE_IDENTIFIER = "000124430016";
42 private static final String SECOND_DEVICE_IDENTIFIER = "000124430017";
43 private static final String UNKNOWN_DEVICE_IDENTIFIER = "100124430016";
46 private Device firstDevice;
48 private Device secondDevice;
50 private DeviceCollection devices;
52 private Device getFirstDevice() {
53 assertNotNull(firstDevice);
54 return Objects.requireNonNull(firstDevice);
57 private Device getSecondDevice() {
58 assertNotNull(secondDevice);
59 return Objects.requireNonNull(secondDevice);
62 private DeviceCollection getDevices() {
63 assertNotNull(devices);
64 return Objects.requireNonNull(devices);
69 firstDevice = mockDevice(FIRST_DEVICE_IDENTIFIER);
70 secondDevice = mockDevice(SECOND_DEVICE_IDENTIFIER);
72 devices = mock(DeviceCollection.class);
73 when(getDevices().getDeviceIdentifiers())
74 .thenReturn(new HashSet<String>(Arrays.asList(FIRST_DEVICE_IDENTIFIER, SECOND_DEVICE_IDENTIFIER)));
75 when(getDevices().getDevice(FIRST_DEVICE_IDENTIFIER)).thenReturn(getFirstDevice());
76 when(getDevices().getDevice(SECOND_DEVICE_IDENTIFIER)).thenReturn(getSecondDevice());
80 public void testAddListenerDispatchesStateUpdatesToPassedListenerForCachedDevices()
81 throws InterruptedException, TimeoutException, ExecutionException {
83 DeviceStateListener listener = mock(DeviceStateListener.class);
85 DeviceStateDispatcher dispatcher = new DeviceStateDispatcher();
86 dispatcher.dispatchDeviceStateUpdates(getDevices());
89 dispatcher.addListener(listener);
92 verify(listener).onDeviceStateUpdated(new DeviceState(FIRST_DEVICE_IDENTIFIER, firstDevice));
93 verify(listener).onDeviceStateUpdated(new DeviceState(SECOND_DEVICE_IDENTIFIER, secondDevice));
94 verifyNoMoreInteractions(listener);
98 public void testDeviceStateUpdatesAreNotDispatchedToRemovedListeners() {
100 DeviceStateListener listener = mock(DeviceStateListener.class);
102 DeviceStateDispatcher dispatcher = new DeviceStateDispatcher();
103 dispatcher.addListener(listener);
106 dispatcher.removeListener(listener);
107 dispatcher.dispatchDeviceStateUpdates(getDevices());
110 verifyNoMoreInteractions(listener);
114 public void testClearCachePreventsDeviceStateUpdateDispatchingOnListenerRegistration() {
116 DeviceStateListener listener = mock(DeviceStateListener.class);
118 DeviceStateDispatcher dispatcher = new DeviceStateDispatcher();
119 dispatcher.dispatchDeviceStateUpdates(getDevices());
122 dispatcher.clearCache();
123 dispatcher.addListener(listener);
126 verifyNoMoreInteractions(listener);
130 public void testDeviceStateUpdatesAreDispatchedToSubscribedListeners() {
132 DeviceStateListener listener = mock(DeviceStateListener.class);
134 DeviceStateDispatcher dispatcher = new DeviceStateDispatcher();
135 dispatcher.addListener(listener);
138 dispatcher.dispatchDeviceStateUpdates(getDevices());
141 verify(listener).onDeviceStateUpdated(new DeviceState(FIRST_DEVICE_IDENTIFIER, firstDevice));
142 verify(listener).onDeviceStateUpdated(new DeviceState(SECOND_DEVICE_IDENTIFIER, secondDevice));
143 verifyNoMoreInteractions(listener);
147 public void testRemovalEventsAreDispatchedToSubscribedListeners()
148 throws InterruptedException, TimeoutException, ExecutionException {
150 DeviceStateListener listener = mock(DeviceStateListener.class);
152 Device deviceWithUnknownIdentifier = mockDevice(UNKNOWN_DEVICE_IDENTIFIER);
153 DeviceCollection devicesWithUnknownDevice = mock(DeviceCollection.class);
154 when(devicesWithUnknownDevice.getDeviceIdentifiers())
155 .thenReturn(new HashSet<String>(Arrays.asList(UNKNOWN_DEVICE_IDENTIFIER)));
156 when(devicesWithUnknownDevice.getDevice(UNKNOWN_DEVICE_IDENTIFIER)).thenReturn(deviceWithUnknownIdentifier);
158 DeviceStateDispatcher dispatcher = new DeviceStateDispatcher();
159 dispatcher.dispatchDeviceStateUpdates(devicesWithUnknownDevice);
160 dispatcher.clearCache();
161 dispatcher.addListener(listener);
164 dispatcher.dispatchDeviceStateUpdates(getDevices());
167 verify(listener).onDeviceRemoved(UNKNOWN_DEVICE_IDENTIFIER);
168 verify(listener, times(2)).onDeviceStateUpdated(any());
169 verifyNoMoreInteractions(listener);
173 public void testRemovalEventsAreDispatchedToSubscribedListenersMatchingAllDeviceIds()
174 throws InterruptedException, TimeoutException, ExecutionException {
176 DeviceStateListener listener = mock(DeviceStateListener.class);
178 Device deviceWithUnknownIdentifier = mockDevice(UNKNOWN_DEVICE_IDENTIFIER);
179 DeviceCollection devicesWithUnknownDevice = mock(DeviceCollection.class);
180 when(devicesWithUnknownDevice.getDeviceIdentifiers())
181 .thenReturn(new HashSet<String>(Arrays.asList(UNKNOWN_DEVICE_IDENTIFIER)));
182 when(devicesWithUnknownDevice.getDevice(UNKNOWN_DEVICE_IDENTIFIER)).thenReturn(deviceWithUnknownIdentifier);
184 DeviceCollection emptyDevices = mock(DeviceCollection.class);
185 when(emptyDevices.getDeviceIdentifiers()).thenReturn(new HashSet<String>());
187 DeviceStateDispatcher dispatcher = new DeviceStateDispatcher();
188 dispatcher.dispatchDeviceStateUpdates(devicesWithUnknownDevice);
189 dispatcher.clearCache();
190 dispatcher.addListener(listener);
193 dispatcher.dispatchDeviceStateUpdates(emptyDevices);
196 verify(listener).onDeviceRemoved(UNKNOWN_DEVICE_IDENTIFIER);
197 verifyNoMoreInteractions(listener);
201 public void testDeviceEventDispatchingForSubscribedListenersWithAnyDeviceIdFilter()
202 throws InterruptedException, TimeoutException, ExecutionException {
204 DeviceStateListener listener = mock(DeviceStateListener.class);
206 DeviceStateDispatcher dispatcher = new DeviceStateDispatcher();
207 dispatcher.addListener(listener);
210 dispatcher.dispatchDeviceStateUpdates(getDevices());
213 verify(listener).onDeviceStateUpdated(new DeviceState(FIRST_DEVICE_IDENTIFIER, firstDevice));
214 verify(listener).onDeviceStateUpdated(new DeviceState(SECOND_DEVICE_IDENTIFIER, secondDevice));
215 verifyNoMoreInteractions(listener);
219 public void testActionsEventDispatchingForSubscribedListeners()
220 throws InterruptedException, TimeoutException, ExecutionException {
222 DeviceStateListener listener = mock(DeviceStateListener.class);
223 Actions actions = mock(Actions.class);
225 DeviceStateDispatcher dispatcher = new DeviceStateDispatcher();
226 dispatcher.addListener(listener);
229 dispatcher.dispatchActionStateUpdates(FIRST_DEVICE_IDENTIFIER, actions);
232 verify(listener).onProcessActionUpdated(new ActionsState(FIRST_DEVICE_IDENTIFIER, actions));
233 verifyNoMoreInteractions(listener);
237 public void testDeviceStateDispatcherDispatchesDeviceStatesAndActions() {
239 DeviceStateListener listener = mock(DeviceStateListener.class);
240 Actions actions = mock(Actions.class);
242 DeviceStateDispatcher dispatcher = new DeviceStateDispatcher();
243 dispatcher.addListener(listener);
245 dispatcher.dispatchDeviceStateUpdates(getDevices());
246 dispatcher.dispatchActionStateUpdates(FIRST_DEVICE_IDENTIFIER, actions);
249 dispatcher.dispatchDeviceState(FIRST_DEVICE_IDENTIFIER);
252 verify(listener, times(2)).onDeviceStateUpdated(new DeviceState(FIRST_DEVICE_IDENTIFIER, firstDevice));
253 verify(listener).onDeviceStateUpdated(new DeviceState(SECOND_DEVICE_IDENTIFIER, secondDevice));
254 verify(listener).onProcessActionUpdated(new ActionsState(FIRST_DEVICE_IDENTIFIER, actions));
255 verifyNoMoreInteractions(listener);