]> git.basschouten.com Git - openhab-addons.git/blob
c0c9c121f77e70270b6e6868ff41b6b805ac93b2
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2020 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         assertEquals(ThingStatusDetail.OFFLINE.CONFIGURATION_ERROR, bridge.getStatusInfo().getStatusDetail());
186     }
187
188     @Test
189     public void verifyOfflineIsSetWithoutBridgeOfflineStatus() {
190         Configuration configuration = new Configuration();
191         configuration.put(HOST, DUMMY_HOST);
192         configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
193         Bridge bridge = createBridgeThing(configuration);
194
195         HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
196         hueBridgeHandler.thingUpdated(bridge);
197
198         hueBridgeHandler.onConnectionLost();
199
200         waitForAssert(() -> assertEquals(ThingStatus.OFFLINE, bridge.getStatus()));
201         assertNotEquals(ThingStatusDetail.BRIDGE_OFFLINE, bridge.getStatusInfo().getStatusDetail());
202     }
203
204     @Test
205     public void assertThatAStatusConfigurationMessageForMissingBridgeIPIsProperlyReturnedIPIsNull() {
206         Configuration configuration = new Configuration();
207         configuration.put(HOST, null);
208         configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
209
210         Bridge bridge = createBridgeThing(configuration);
211
212         HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
213
214         ConfigStatusMessage expected = ConfigStatusMessage.Builder.error(HOST)
215                 .withMessageKeySuffix(HueConfigStatusMessage.IP_ADDRESS_MISSING).withArguments(HOST).build();
216
217         waitForAssert(() -> assertEquals(expected, hueBridgeHandler.getConfigStatus().iterator().next()));
218     }
219
220     @Test
221     public void assertThatAStatusConfigurationMessageForMissingBridgeIPIsProperlyReturnedIPIsAnEmptyString() {
222         Configuration configuration = new Configuration();
223         configuration.put(HOST, "");
224         configuration.put(PROPERTY_SERIAL_NUMBER, "testSerialNumber");
225
226         Bridge bridge = createBridgeThing(configuration);
227
228         HueBridgeHandler hueBridgeHandler = getThingHandler(bridge, HueBridgeHandler.class);
229
230         ConfigStatusMessage expected = ConfigStatusMessage.Builder.error(HOST)
231                 .withMessageKeySuffix(HueConfigStatusMessage.IP_ADDRESS_MISSING).withArguments(HOST).build();
232
233         waitForAssert(() -> assertEquals(expected, hueBridgeHandler.getConfigStatus().iterator().next()));
234     }
235
236     private Bridge createBridgeThing(Configuration configuration) {
237         Bridge bridge = (Bridge) thingRegistry.createThingOfType(BRIDGE_THING_TYPE_UID,
238                 new ThingUID(BRIDGE_THING_TYPE_UID, "testBridge"), null, "Bridge", configuration);
239
240         bridge = requireNonNull(bridge, "Bridge is null");
241         thingRegistry.add(bridge);
242         return bridge;
243     }
244
245     private void injectBridge(HueBridgeHandler hueBridgeHandler, HueBridge bridge) {
246         try {
247             Field hueBridgeField = hueBridgeHandler.getClass().getDeclaredField("hueBridge");
248             hueBridgeField.setAccessible(true);
249             hueBridgeField.set(hueBridgeHandler, bridge);
250         } catch (Exception e) {
251             throw new AssertionError(e);
252         }
253     }
254 }