2 * Copyright (c) 2010-2023 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.livisismarthome.internal;
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.mockito.ArgumentMatchers.any;
17 import static org.mockito.Mockito.*;
20 import java.util.concurrent.Future;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.jetty.client.HttpClient;
24 import org.eclipse.jetty.websocket.api.Session;
25 import org.eclipse.jetty.websocket.api.StatusCode;
26 import org.eclipse.jetty.websocket.client.WebSocketClient;
27 import org.junit.jupiter.api.BeforeEach;
28 import org.junit.jupiter.api.Test;
29 import org.openhab.binding.livisismarthome.internal.listener.EventListener;
32 * @author Sven Strohschein - Initial contribution
35 public class LivisiWebSocketTest {
37 private @NonNullByDefault({}) LivisiWebSocketAccessible webSocket;
38 private @NonNullByDefault({}) EventListenerDummy eventListener;
39 private @NonNullByDefault({}) WebSocketClient webSocketClientMock;
40 private @NonNullByDefault({}) Session sessionMock;
43 @SuppressWarnings("unchecked")
44 public void before() throws Exception {
45 sessionMock = mock(Session.class);
47 Future<Session> futureMock = mock(Future.class);
48 when(futureMock.get()).thenReturn(sessionMock);
50 webSocketClientMock = mock(WebSocketClient.class);
51 when(webSocketClientMock.connect(any(), any())).thenReturn(futureMock);
53 HttpClient httpClientMock = mock(HttpClient.class);
55 eventListener = new EventListenerDummy();
56 webSocket = new LivisiWebSocketAccessible(httpClientMock, eventListener, new URI(""), 1000);
60 public void testStart() throws Exception {
63 assertTrue(webSocket.isRunning());
67 public void testStop() throws Exception {
72 assertFalse(webSocket.isRunning());
76 public void testOnCloseAfterStop() throws Exception {
79 assertFalse(eventListener.isOnEventCalled());
80 assertFalse(eventListener.isOnErrorCalled());
81 assertFalse(eventListener.isConnectionClosedCalled());
84 webSocket.onClose(StatusCode.ABNORMAL, "Test");
86 assertFalse(eventListener.isOnEventCalled());
87 assertFalse(eventListener.isOnErrorCalled());
88 // stop() itself causes a (abnormal) close event, that shouldn't get noticed
89 // (otherwise it would cause a reconnect event which would lead to an infinite loop ...)
90 assertFalse(eventListener.isConnectionClosedCalled());
94 public void testOnCloseAfterRestart() throws Exception {
97 assertFalse(eventListener.isOnEventCalled());
98 assertFalse(eventListener.isOnErrorCalled());
99 assertFalse(eventListener.isConnectionClosedCalled());
102 webSocket.onClose(StatusCode.ABNORMAL, "Test");
104 assertFalse(eventListener.isOnEventCalled());
105 assertFalse(eventListener.isOnErrorCalled());
106 // stop() itself causes a (abnormal) close event, that shouldn't get noticed
107 // (otherwise it would cause a reconnect event which would lead to an infinite loop ...)
108 assertFalse(eventListener.isConnectionClosedCalled());
112 webSocket.onClose(StatusCode.ABNORMAL, "Test");
114 assertFalse(eventListener.isOnEventCalled());
115 assertFalse(eventListener.isOnErrorCalled());
116 // A close event after a restart of the web socket should get recognized again
117 assertTrue(eventListener.isConnectionClosedCalled());
121 public void testOnCloseAbnormal() throws Exception {
124 assertFalse(eventListener.isOnEventCalled());
125 assertFalse(eventListener.isOnErrorCalled());
126 assertFalse(eventListener.isConnectionClosedCalled());
128 webSocket.onClose(StatusCode.ABNORMAL, "Test");
130 assertFalse(eventListener.isOnEventCalled());
131 assertFalse(eventListener.isOnErrorCalled());
132 assertTrue(eventListener.isConnectionClosedCalled());
136 public void testOnCloseNormal() throws Exception {
139 assertFalse(eventListener.isOnEventCalled());
140 assertFalse(eventListener.isOnErrorCalled());
141 assertFalse(eventListener.isConnectionClosedCalled());
143 webSocket.onClose(StatusCode.NORMAL, "Test");
145 assertFalse(eventListener.isOnEventCalled());
146 assertFalse(eventListener.isOnErrorCalled());
147 // Nothing should get noticed when a normal close is executed (for example by stopping OpenHAB)
148 assertFalse(eventListener.isConnectionClosedCalled());
152 public void testOnMessage() throws Exception {
155 assertFalse(eventListener.isOnEventCalled());
156 assertFalse(eventListener.isOnErrorCalled());
157 assertFalse(eventListener.isConnectionClosedCalled());
159 webSocket.onMessage("Test-Message");
161 assertTrue(eventListener.isOnEventCalled());
162 assertFalse(eventListener.isOnErrorCalled());
163 assertFalse(eventListener.isConnectionClosedCalled());
167 public void testOnMessageAfterStop() throws Exception {
170 assertFalse(eventListener.isOnEventCalled());
171 assertFalse(eventListener.isOnErrorCalled());
172 assertFalse(eventListener.isConnectionClosedCalled());
175 webSocket.onClose(StatusCode.ABNORMAL, "Test");
176 webSocket.onMessage("Test-Message");
178 assertFalse(eventListener.isOnEventCalled());
179 assertFalse(eventListener.isOnErrorCalled());
180 assertFalse(eventListener.isConnectionClosedCalled());
184 public void testOnError() throws Exception {
187 assertFalse(eventListener.isOnEventCalled());
188 assertFalse(eventListener.isOnErrorCalled());
189 assertFalse(eventListener.isConnectionClosedCalled());
191 webSocket.onError(new RuntimeException("Test-Exception"));
193 assertFalse(eventListener.isOnEventCalled());
194 assertTrue(eventListener.isOnErrorCalled());
195 assertFalse(eventListener.isConnectionClosedCalled());
198 private void startWebSocket() throws Exception {
200 when(sessionMock.isOpen()).thenReturn(true);
202 webSocket.onConnect(sessionMock);
205 private class LivisiWebSocketAccessible extends LivisiWebSocket {
207 private LivisiWebSocketAccessible(HttpClient httpClient, EventListener eventListener, URI webSocketURI,
208 int maxIdleTimeout) {
209 super(httpClient, eventListener, webSocketURI, maxIdleTimeout);
213 WebSocketClient createWebSocketClient() {
214 return webSocketClientMock;
218 void startWebSocketClient(WebSocketClient client) {
222 void stopWebSocketClient(WebSocketClient client) {
226 private static class EventListenerDummy implements EventListener {
228 private boolean isOnEventCalled;
229 private boolean isOnErrorCalled;
230 private boolean isConnectionClosedCalled;
233 public void onEvent(String msg) {
234 isOnEventCalled = true;
238 public void onError(Throwable cause) {
239 isOnErrorCalled = true;
243 public void connectionClosed() {
244 isConnectionClosedCalled = true;
247 public boolean isOnEventCalled() {
248 return isOnEventCalled;
251 public boolean isOnErrorCalled() {
252 return isOnErrorCalled;
255 public boolean isConnectionClosedCalled() {
256 return isConnectionClosedCalled;