]> git.basschouten.com Git - openhab-addons.git/blob
8368a90aab8b5897ac4073fe530239d7931cc9eb
[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.hue.internal.handler;
14
15 import static org.eclipse.jdt.annotation.Checks.requireNonNull;
16 import static org.hamcrest.CoreMatchers.equalTo;
17 import static org.hamcrest.MatcherAssert.assertThat;
18 import static org.junit.jupiter.api.Assertions.*;
19 import static org.openhab.binding.hue.internal.HueBindingConstants.*;
20 import static org.openhab.binding.hue.internal.config.HueBridgeConfig.HTTP;
21 import static org.openhab.core.thing.Thing.PROPERTY_SERIAL_NUMBER;
22
23 import java.io.IOException;
24 import java.lang.reflect.Field;
25 import java.util.concurrent.ScheduledExecutorService;
26
27 import org.junit.jupiter.api.BeforeEach;
28 import org.junit.jupiter.api.Test;
29 import org.openhab.binding.hue.internal.AbstractHueOSGiTestParent;
30 import org.openhab.binding.hue.internal.HueBridge;
31 import org.openhab.binding.hue.internal.HueConfigStatusMessage;
32 import org.openhab.binding.hue.internal.exceptions.ApiException;
33 import org.openhab.binding.hue.internal.exceptions.LinkButtonException;
34 import org.openhab.binding.hue.internal.exceptions.UnauthorizedException;
35 import org.openhab.core.common.ThreadPoolManager;
36 import org.openhab.core.config.core.Configuration;
37 import org.openhab.core.config.core.status.ConfigStatusMessage;
38 import org.openhab.core.thing.Bridge;
39 import org.openhab.core.thing.ThingRegistry;
40 import org.openhab.core.thing.ThingStatus;
41 import org.openhab.core.thing.ThingStatusDetail;
42 import org.openhab.core.thing.ThingTypeUID;
43 import org.openhab.core.thing.ThingUID;
44
45 /**
46  * Tests for {@link HueBridgeHandler}.
47  *
48  * @author Oliver Libutzki - Initial contribution
49  * @author Michael Grammling - Initial contribution
50  * @author Denis Dudnik - switched to internally integrated source of Jue library
51  */
52 public class HueBridgeHandlerOSGiTest extends AbstractHueOSGiTestParent {
53
54     private static final ThingTypeUID BRIDGE_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "bridge");
55     private static final String TEST_USER_NAME = "eshTestUser";
56     private static final String DUMMY_HOST = "1.2.3.4";
57
58     private ThingRegistry thingRegistry;
59
60     private ScheduledExecutorService scheduler;
61
62     @BeforeEach
63     public void setUp() {
64         registerVolatileStorageService();
65         thingRegistry = getService(ThingRegistry.class, ThingRegistry.class);
66         assertNotNull(thingRegistry);
67
68         scheduler = ThreadPoolManager.getScheduledPool("hueBridgeTest");
69     }
70
71     @Test
72     public void assertThatANewUserIsAddedToConfigIfNotExistingYet() {
73         Configuration configuration = new Configuration();
74         configuration.put(HOST, DUMMY_HOST);
75         configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
76         Bridge bridge = createBridgeThing(configuration);
77
78         HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
79         hueBridgeHandler.thingUpdated(bridge);
80
81         injectBridge(hueBridgeHandler, new HueBridge(DUMMY_HOST, 80, HTTP, scheduler) {
82             @Override
83             public String link(String deviceType) throws IOException, ApiException {
84                 return TEST_USER_NAME;
85             }
86         });
87
88         hueBridgeHandler.onNotAuthenticated();
89
90         assertThat(bridge.getConfiguration().get(USER_NAME), equalTo(TEST_USER_NAME));
91     }
92
93     @Test
94     public void assertThatAnExistingUserIsUsedIfAuthenticationWasSuccessful() {
95         Configuration configuration = new Configuration();
96         configuration.put(HOST, DUMMY_HOST);
97         configuration.put(USER_NAME, TEST_USER_NAME);
98         configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
99         Bridge bridge = createBridgeThing(configuration);
100
101         HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
102         hueBridgeHandler.thingUpdated(bridge);
103
104         injectBridge(hueBridgeHandler, new HueBridge(DUMMY_HOST, 80, HTTP, scheduler) {
105             @Override
106             public void authenticate(String userName) throws IOException, ApiException {
107             }
108         });
109
110         hueBridgeHandler.onNotAuthenticated();
111
112         assertThat(bridge.getConfiguration().get(USER_NAME), equalTo(TEST_USER_NAME));
113     }
114
115     @Test
116     public void assertCorrectStatusIfAuthenticationFailedForOldUser() {
117         Configuration configuration = new Configuration();
118         configuration.put(HOST, DUMMY_HOST);
119         configuration.put(USER_NAME, "notAuthenticatedUser");
120         configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
121         Bridge bridge = createBridgeThing(configuration);
122
123         HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
124         hueBridgeHandler.thingUpdated(bridge);
125
126         injectBridge(hueBridgeHandler, new HueBridge(DUMMY_HOST, 80, HTTP, scheduler) {
127             @Override
128             public void authenticate(String userName) throws IOException, ApiException {
129                 throw new UnauthorizedException();
130             }
131         });
132
133         hueBridgeHandler.onNotAuthenticated();
134
135         assertEquals("notAuthenticatedUser", bridge.getConfiguration().get(USER_NAME));
136         waitForAssert(() -> assertEquals(ThingStatus.OFFLINE, bridge.getStatus()));
137         assertEquals(ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, bridge.getStatusInfo().getStatusDetail());
138     }
139
140     @Test
141     public void verifyStatusIfLinkButtonIsNotPressed() {
142         Configuration configuration = new Configuration();
143         configuration.put(HOST, DUMMY_HOST);
144         configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
145         Bridge bridge = createBridgeThing(configuration);
146
147         HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
148         hueBridgeHandler.thingUpdated(bridge);
149
150         injectBridge(hueBridgeHandler, new HueBridge(DUMMY_HOST, 80, HTTP, scheduler) {
151             @Override
152             public String link(String deviceType) throws IOException, ApiException {
153                 throw new LinkButtonException();
154             }
155         });
156
157         hueBridgeHandler.onNotAuthenticated();
158
159         assertNull(bridge.getConfiguration().get(USER_NAME));
160         waitForAssert(() -> assertEquals(ThingStatus.OFFLINE, bridge.getStatus()));
161         assertEquals(ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, bridge.getStatusInfo().getStatusDetail());
162     }
163
164     @Test
165     public void verifyStatusIfNewUserCannotBeCreated() {
166         Configuration configuration = new Configuration();
167         configuration.put(HOST, DUMMY_HOST);
168         configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
169         Bridge bridge = createBridgeThing(configuration);
170
171         HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
172         hueBridgeHandler.thingUpdated(bridge);
173
174         injectBridge(hueBridgeHandler, new HueBridge(DUMMY_HOST, 80, HTTP, scheduler) {
175             @Override
176             public String link(String deviceType) throws IOException, ApiException {
177                 throw new ApiException();
178             }
179         });
180
181         hueBridgeHandler.onNotAuthenticated();
182
183         assertNull(bridge.getConfiguration().get(USER_NAME));
184         waitForAssert(() -> assertEquals(ThingStatus.OFFLINE, bridge.getStatus()));
185         waitForAssert(() -> assertEquals(ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR,
186                 bridge.getStatusInfo().getStatusDetail()));
187     }
188
189     @Test
190     public void verifyOfflineIsSetWithoutBridgeOfflineStatus() {
191         Configuration configuration = new Configuration();
192         configuration.put(HOST, DUMMY_HOST);
193         configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
194         Bridge bridge = createBridgeThing(configuration);
195
196         HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
197         hueBridgeHandler.thingUpdated(bridge);
198
199         hueBridgeHandler.onConnectionLost();
200
201         waitForAssert(() -> assertEquals(ThingStatus.OFFLINE, bridge.getStatus()));
202         assertNotEquals(ThingStatusDetail.BRIDGE_OFFLINE, bridge.getStatusInfo().getStatusDetail());
203     }
204
205     @Test
206     public void assertThatAStatusConfigurationMessageForMissingBridgeIPIsProperlyReturnedIPIsNull() {
207         Configuration configuration = new Configuration();
208         configuration.put(HOST, null);
209         configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
210
211         Bridge bridge = createBridgeThing(configuration);
212
213         HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
214
215         ConfigStatusMessage expected = ConfigStatusMessage.Builder.error(HOST)
216                 .withMessageKeySuffix(HueConfigStatusMessage.IP_ADDRESS_MISSING).withArguments(HOST).build();
217
218         waitForAssert(() -> assertEquals(expected, hueBridgeHandler.getConfigStatus().iterator().next()));
219     }
220
221     @Test
222     public void assertThatAStatusConfigurationMessageForMissingBridgeIPIsProperlyReturnedIPIsAnEmptyString() {
223         Configuration configuration = new Configuration();
224         configuration.put(HOST, "");
225         configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
226
227         Bridge bridge = createBridgeThing(configuration);
228
229         HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
230
231         ConfigStatusMessage expected = ConfigStatusMessage.Builder.error(HOST)
232                 .withMessageKeySuffix(HueConfigStatusMessage.IP_ADDRESS_MISSING).withArguments(HOST).build();
233
234         waitForAssert(() -> assertEquals(expected, hueBridgeHandler.getConfigStatus().iterator().next()));
235     }
236
237     private Bridge createBridgeThing(Configuration configuration) {
238         Bridge bridge = (Bridge) thingRegistry.createThingOfType(BRIDGE_THING_TYPE_UID,
239                 new ThingUID(BRIDGE_THING_TYPE_UID, "testBridge"), null, "Bridge", configuration);
240
241         bridge = requireNonNull(bridge, "Bridge is null");
242         thingRegistry.add(bridge);
243         return bridge;
244     }
245
246     private void injectBridge(HueBridgeHandler hueBridgeHandler, HueBridge bridge) {
247         try {
248             Field hueBridgeField = hueBridgeHandler.getClass().getDeclaredField("hueBridge");
249             hueBridgeField.setAccessible(true);
250             hueBridgeField.set(hueBridgeHandler, bridge);
251         } catch (Exception e) {
252             throw new AssertionError(e);
253         }
254     }
255 }