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.hue.internal.handler;
15 import static org.openhab.core.thing.Thing.PROPERTY_SERIAL_NUMBER;
16 import static org.hamcrest.CoreMatchers.equalTo;
17 import static org.junit.Assert.*;
18 import static org.openhab.binding.hue.internal.HueBindingConstants.*;
19 import static org.openhab.binding.hue.internal.config.HueBridgeConfig.HTTP;
21 import java.io.IOException;
22 import java.lang.reflect.Field;
23 import java.util.concurrent.ScheduledExecutorService;
25 import org.openhab.core.config.core.Configuration;
26 import org.openhab.core.config.core.status.ConfigStatusMessage;
27 import org.openhab.core.common.ThreadPoolManager;
28 import org.openhab.core.thing.Bridge;
29 import org.openhab.core.thing.ThingRegistry;
30 import org.openhab.core.thing.ThingStatus;
31 import org.openhab.core.thing.ThingStatusDetail;
32 import org.openhab.core.thing.ThingTypeUID;
33 import org.openhab.core.thing.ThingUID;
34 import org.junit.Before;
35 import org.junit.Test;
36 import org.openhab.binding.hue.internal.AbstractHueOSGiTestParent;
37 import org.openhab.binding.hue.internal.HueBridge;
38 import org.openhab.binding.hue.internal.HueConfigStatusMessage;
39 import org.openhab.binding.hue.internal.exceptions.ApiException;
40 import org.openhab.binding.hue.internal.exceptions.LinkButtonException;
41 import org.openhab.binding.hue.internal.exceptions.UnauthorizedException;
44 * Tests for {@link HueBridgeHandler}.
46 * @author Oliver Libutzki - Initial contribution
47 * @author Michael Grammling - Initial contribution
48 * @author Denis Dudnik - switched to internally integrated source of Jue library
50 public class HueBridgeHandlerOSGiTest extends AbstractHueOSGiTestParent {
52 private final ThingTypeUID BRIDGE_THING_TYPE_UID = new ThingTypeUID(BINDING_ID, "bridge");
53 private static final String TEST_USER_NAME = "eshTestUser";
54 private static final String DUMMY_HOST = "1.2.3.4";
56 private ThingRegistry thingRegistry;
58 private ScheduledExecutorService scheduler;
62 registerVolatileStorageService();
63 thingRegistry = getService(ThingRegistry.class, ThingRegistry.class);
64 assertNotNull(thingRegistry);
66 scheduler = ThreadPoolManager.getScheduledPool("hueBridgeTest");
70 public void assertThatANewUserIsAddedToConfigIfNotExistingYet() {
71 Configuration configuration = new Configuration();
72 configuration.put(HOST, DUMMY_HOST);
73 configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
74 Bridge bridge = createBridgeThing(configuration);
76 HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
77 hueBridgeHandler.thingUpdated(bridge);
79 injectBridge(hueBridgeHandler, new HueBridge(DUMMY_HOST, 80, HTTP, scheduler) {
81 public String link(String deviceType) throws IOException, ApiException {
82 return TEST_USER_NAME;
86 hueBridgeHandler.onNotAuthenticated();
88 assertThat(bridge.getConfiguration().get(USER_NAME), equalTo(TEST_USER_NAME));
92 public void assertThatAnExistingUserIsUsedIfAuthenticationWasSuccessful() {
93 Configuration configuration = new Configuration();
94 configuration.put(HOST, DUMMY_HOST);
95 configuration.put(USER_NAME, TEST_USER_NAME);
96 configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
97 Bridge bridge = createBridgeThing(configuration);
99 HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
100 hueBridgeHandler.thingUpdated(bridge);
102 injectBridge(hueBridgeHandler, new HueBridge(DUMMY_HOST, 80, HTTP, scheduler) {
104 public void authenticate(String userName) throws IOException, ApiException {
108 hueBridgeHandler.onNotAuthenticated();
110 assertThat(bridge.getConfiguration().get(USER_NAME), equalTo(TEST_USER_NAME));
114 public void assertCorrectStatusIfAuthenticationFailedForOldUser() {
115 Configuration configuration = new Configuration();
116 configuration.put(HOST, DUMMY_HOST);
117 configuration.put(USER_NAME, "notAuthenticatedUser");
118 configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
119 Bridge bridge = createBridgeThing(configuration);
121 HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
122 hueBridgeHandler.thingUpdated(bridge);
124 injectBridge(hueBridgeHandler, new HueBridge(DUMMY_HOST, 80, HTTP, scheduler) {
126 public void authenticate(String userName) throws IOException, ApiException {
127 throw new UnauthorizedException();
131 hueBridgeHandler.onNotAuthenticated();
133 assertEquals("notAuthenticatedUser", bridge.getConfiguration().get(USER_NAME));
134 assertEquals(ThingStatus.OFFLINE, bridge.getStatus());
135 assertEquals(ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, bridge.getStatusInfo().getStatusDetail());
139 public void verifyStatusIfLinkButtonIsNotPressed() {
140 Configuration configuration = new Configuration();
141 configuration.put(HOST, DUMMY_HOST);
142 configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
143 Bridge bridge = createBridgeThing(configuration);
145 HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
146 hueBridgeHandler.thingUpdated(bridge);
148 injectBridge(hueBridgeHandler, new HueBridge(DUMMY_HOST, 80, HTTP, scheduler) {
150 public String link(String deviceType) throws IOException, ApiException {
151 throw new LinkButtonException();
155 hueBridgeHandler.onNotAuthenticated();
157 assertNull(bridge.getConfiguration().get(USER_NAME));
158 assertEquals(ThingStatus.OFFLINE, bridge.getStatus());
159 assertEquals(ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, bridge.getStatusInfo().getStatusDetail());
163 public void verifyStatusIfNewUserCannotBeCreated() {
164 Configuration configuration = new Configuration();
165 configuration.put(HOST, DUMMY_HOST);
166 configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
167 Bridge bridge = createBridgeThing(configuration);
169 HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
170 hueBridgeHandler.thingUpdated(bridge);
172 injectBridge(hueBridgeHandler, new HueBridge(DUMMY_HOST, 80, HTTP, scheduler) {
174 public String link(String deviceType) throws IOException, ApiException {
175 throw new ApiException();
179 hueBridgeHandler.onNotAuthenticated();
181 assertNull(bridge.getConfiguration().get(USER_NAME));
182 assertEquals(ThingStatus.OFFLINE, bridge.getStatus());
183 assertEquals(ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, bridge.getStatusInfo().getStatusDetail());
187 public void verifyOfflineIsSetWithoutBridgeOfflineStatus() {
188 Configuration configuration = new Configuration();
189 configuration.put(HOST, DUMMY_HOST);
190 configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
191 Bridge bridge = createBridgeThing(configuration);
193 HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
194 hueBridgeHandler.thingUpdated(bridge);
196 hueBridgeHandler.onConnectionLost();
198 assertEquals(ThingStatus.OFFLINE, bridge.getStatus());
199 assertNotEquals(ThingStatusDetail.BRIDGE_OFFLINE, bridge.getStatusInfo().getStatusDetail());
203 public void assertThatAStatusConfigurationMessageForMissingBridgeIPIsProperlyReturnedIPIsNull() {
204 Configuration configuration = new Configuration();
205 configuration.put(HOST, null);
206 configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
208 Bridge bridge = createBridgeThing(configuration);
210 HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
212 ConfigStatusMessage expected = ConfigStatusMessage.Builder.error(HOST)
213 .withMessageKeySuffix(HueConfigStatusMessage.IP_ADDRESS_MISSING).withArguments(HOST).build();
215 waitForAssert(() -> assertEquals(expected, hueBridgeHandler.getConfigStatus().iterator().next()));
219 public void assertThatAStatusConfigurationMessageForMissingBridgeIPIsProperlyReturnedIPIsAnEmptyString() {
220 Configuration configuration = new Configuration();
221 configuration.put(HOST, "");
222 configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
224 Bridge bridge = createBridgeThing(configuration);
226 HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
228 ConfigStatusMessage expected = ConfigStatusMessage.Builder.error(HOST)
229 .withMessageKeySuffix(HueConfigStatusMessage.IP_ADDRESS_MISSING).withArguments(HOST).build();
231 waitForAssert(() -> assertEquals(expected, hueBridgeHandler.getConfigStatus().iterator().next()));
234 private Bridge createBridgeThing(Configuration configuration) {
235 Bridge bridge = (Bridge) thingRegistry.createThingOfType(BRIDGE_THING_TYPE_UID,
236 new ThingUID(BRIDGE_THING_TYPE_UID, "testBridge"), null, "Bridge", configuration);
238 assertNotNull(bridge);
239 thingRegistry.add(bridge);
243 private void injectBridge(HueBridgeHandler hueBridgeHandler, HueBridge bridge) {
245 Field hueBridgeField = hueBridgeHandler.getClass().getDeclaredField("hueBridge");
246 hueBridgeField.setAccessible(true);
247 hueBridgeField.set(hueBridgeHandler, bridge);
248 } catch (Exception e) {
249 throw new AssertionError(e);