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.boschshc.internal.discovery;
15 import static org.hamcrest.CoreMatchers.is;
16 import static org.hamcrest.CoreMatchers.not;
17 import static org.hamcrest.CoreMatchers.nullValue;
18 import static org.hamcrest.MatcherAssert.assertThat;
19 import static org.junit.jupiter.api.Assertions.assertNotNull;
20 import static org.junit.jupiter.api.Assertions.assertNull;
21 import static org.junit.jupiter.api.Assertions.assertSame;
22 import static org.junit.jupiter.api.Assertions.assertTrue;
23 import static org.mockito.ArgumentMatchers.any;
24 import static org.mockito.ArgumentMatchers.anyLong;
25 import static org.mockito.Mockito.mock;
26 import static org.mockito.Mockito.when;
28 import java.net.ConnectException;
29 import java.util.concurrent.ExecutionException;
31 import javax.jmdns.ServiceInfo;
33 import org.eclipse.jdt.annotation.NonNullByDefault;
34 import org.eclipse.jdt.annotation.Nullable;
35 import org.eclipse.jetty.client.HttpClient;
36 import org.eclipse.jetty.client.api.ContentResponse;
37 import org.eclipse.jetty.client.api.Request;
38 import org.eclipse.jetty.http.HttpMethod;
39 import org.eclipse.jetty.http.HttpStatus;
40 import org.junit.jupiter.api.BeforeEach;
41 import org.junit.jupiter.api.Test;
42 import org.junit.jupiter.api.extension.ExtendWith;
43 import org.mockito.Mock;
44 import org.mockito.Spy;
45 import org.mockito.junit.jupiter.MockitoExtension;
46 import org.mockito.junit.jupiter.MockitoSettings;
47 import org.mockito.quality.Strictness;
48 import org.openhab.binding.boschshc.internal.devices.BoschSHCBindingConstants;
49 import org.openhab.binding.boschshc.internal.devices.bridge.dto.PublicInformation;
50 import org.openhab.core.config.discovery.DiscoveryResult;
51 import org.openhab.core.thing.ThingUID;
54 * BridgeDiscoveryParticipant Tester.
56 * @author Gerd Zanker - Initial contribution
58 @ExtendWith(MockitoExtension.class)
59 @MockitoSettings(strictness = Strictness.LENIENT)
61 class BridgeDiscoveryParticipantTest {
63 private @NonNullByDefault({}) BridgeDiscoveryParticipant fixture;
65 private final String url = "https://192.168.0.123:8446/smarthome/public/information";
66 private final String urlOtherDevice = "https://192.168.0.1:8446/smarthome/public/information";
68 private @Mock @NonNullByDefault({}) ServiceInfo shcBridge;
69 private @Mock @NonNullByDefault({}) ServiceInfo otherDevice;
71 private @Mock @NonNullByDefault({}) ContentResponse contentResponse;
74 * Spy needed because some final methods can't be mocked
76 private @Spy @NonNullByDefault({}) HttpClient mockHttpClient;
79 public void beforeEach() throws Exception {
80 when(shcBridge.getHostAddresses()).thenReturn(new String[] { "192.168.0.123" });
81 when(shcBridge.getName()).thenReturn("Bosch SHC [xx-xx-xx-xx-xx-xx]");
83 when(otherDevice.getHostAddresses()).thenReturn(new String[] { "192.168.0.1" });
84 when(otherDevice.getName()).thenReturn("Other Device");
86 when(contentResponse.getContentAsString()).thenReturn(
87 "{\"apiVersions\":[\"2.9\",\"3.2\"], \"shcIpAddress\":\"192.168.0.123\", \"shcGeneration\":\"SHC_1\"}");
88 when(contentResponse.getStatus()).thenReturn(HttpStatus.OK_200);
90 Request mockRequest = mock(Request.class);
91 when(mockRequest.send()).thenReturn(contentResponse);
92 when(mockRequest.method(any(HttpMethod.class))).thenReturn(mockRequest);
93 when(mockRequest.timeout(anyLong(), any())).thenReturn(mockRequest);
95 when(mockHttpClient.newRequest(url)).thenReturn(mockRequest);
97 Request failingRequest = mock(Request.class);
98 when(failingRequest.method(any(HttpMethod.class))).thenReturn(failingRequest);
99 when(failingRequest.timeout(anyLong(), any())).thenReturn(failingRequest);
100 when(failingRequest.send()).thenThrow(new ExecutionException(new ConnectException("Connection refused")));
102 when(mockHttpClient.newRequest(urlOtherDevice)).thenReturn(failingRequest);
104 fixture = new BridgeDiscoveryParticipant(mockHttpClient);
109 * Method: getSupportedThingTypeUIDs()
114 void testGetSupportedThingTypeUIDs() {
115 assertTrue(fixture.getSupportedThingTypeUIDs().contains(BoschSHCBindingConstants.THING_TYPE_SHC));
120 * Method: getServiceType()
124 void testGetServiceType() throws Exception {
125 assertThat(fixture.getServiceType(), is("_http._tcp.local."));
129 void testCreateResult() throws Exception {
130 DiscoveryResult result = fixture.createResult(shcBridge);
131 assertNotNull(result);
132 assertThat(result.getBindingId(), is(BoschSHCBindingConstants.BINDING_ID));
133 assertThat(result.getThingUID().getId(), is("192-168-0-123"));
134 assertThat(result.getThingTypeUID().getId(), is("shc"));
135 assertThat(result.getLabel(), is("Bosch Smart Home Controller (192.168.0.123)"));
139 void testCreateResultOtherDevice() throws Exception {
140 DiscoveryResult result = fixture.createResult(otherDevice);
145 void testCreateResultNoIPAddress() throws Exception {
146 when(shcBridge.getHostAddresses()).thenReturn(new String[] { "" });
147 DiscoveryResult result = fixture.createResult(shcBridge);
152 void testGetThingUID() throws Exception {
153 ThingUID thingUID = fixture.getThingUID(shcBridge);
154 assertNotNull(thingUID);
155 assertThat(thingUID.getBindingId(), is(BoschSHCBindingConstants.BINDING_ID));
156 assertThat(thingUID.getId(), is("192-168-0-123"));
160 void testGetThingUIDOtherDevice() throws Exception {
161 assertNull(fixture.getThingUID(otherDevice));
165 void testGetBridgeAddress() throws Exception {
167 PublicInformation bridgeInformation = fixture.discoverBridge("192.168.0.123");
168 assertThat(bridgeInformation, not(nullValue()));
169 assertThat(bridgeInformation.shcIpAddress, is("192.168.0.123"));
173 void testGetBridgeAddressOtherDevice() throws Exception {
174 assertThat(fixture.discoverBridge("192.168.0.1"), is(nullValue()));
178 void testGetPublicInformationFromPossibleBridgeAddress() throws Exception {
180 PublicInformation bridgeInformation = fixture.getPublicInformationFromPossibleBridgeAddress("192.168.0.123");
181 assertThat(bridgeInformation, not(nullValue()));
182 assertThat(bridgeInformation.shcIpAddress, is("192.168.0.123"));
186 void testGetPublicInformationFromPossibleBridgeAddressInvalidContent() throws Exception {
187 when(contentResponse.getContentAsString()).thenReturn("{\"nothing\":\"useful\"}");
189 fixture = new BridgeDiscoveryParticipant(mockHttpClient);
190 assertThat(fixture.getPublicInformationFromPossibleBridgeAddress("192.168.0.123"), is(nullValue()));
194 void testGetPublicInformationFromPossibleBridgeAddressInvalidStatus() throws Exception {
195 when(contentResponse.getStatus()).thenReturn(HttpStatus.BAD_REQUEST_400);
197 fixture = new BridgeDiscoveryParticipant(mockHttpClient);
198 assertThat(fixture.getPublicInformationFromPossibleBridgeAddress("192.168.0.123"), is(nullValue()));
202 void testGetOrComputePublicInformation() throws Exception {
204 PublicInformation result = fixture.getOrComputePublicInformation("192.168.0.123");
205 assertNotNull(result);
207 PublicInformation result2 = fixture.getOrComputePublicInformation("192.168.0.123");
208 assertSame(result, result2);