]> git.basschouten.com Git - openhab-addons.git/blob
9588045fc913f6ba260bd04133070b17dd16c248
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.livisismarthome.internal;
14
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.mockito.ArgumentMatchers.any;
17 import static org.mockito.Mockito.*;
18
19 import java.net.URI;
20 import java.util.concurrent.Future;
21
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;
30
31 /**
32  * @author Sven Strohschein - Initial contribution
33  */
34 @NonNullByDefault
35 public class LivisiWebSocketTest {
36
37     private @NonNullByDefault({}) LivisiWebSocketAccessible webSocket;
38     private @NonNullByDefault({}) EventListenerDummy eventListener;
39     private @NonNullByDefault({}) WebSocketClient webSocketClientMock;
40     private @NonNullByDefault({}) Session sessionMock;
41
42     @BeforeEach
43     @SuppressWarnings("unchecked")
44     public void before() throws Exception {
45         sessionMock = mock(Session.class);
46
47         Future<Session> futureMock = mock(Future.class);
48         when(futureMock.get()).thenReturn(sessionMock);
49
50         webSocketClientMock = mock(WebSocketClient.class);
51         when(webSocketClientMock.connect(any(), any())).thenReturn(futureMock);
52
53         HttpClient httpClientMock = mock(HttpClient.class);
54
55         eventListener = new EventListenerDummy();
56         webSocket = new LivisiWebSocketAccessible(httpClientMock, eventListener, new URI(""), 1000);
57     }
58
59     @Test
60     public void testStart() throws Exception {
61         startWebSocket();
62
63         assertTrue(webSocket.isRunning());
64     }
65
66     @Test
67     public void testStop() throws Exception {
68         startWebSocket();
69
70         webSocket.stop();
71
72         assertFalse(webSocket.isRunning());
73     }
74
75     @Test
76     public void testOnCloseAfterStop() throws Exception {
77         startWebSocket();
78
79         assertFalse(eventListener.isOnEventCalled());
80         assertFalse(eventListener.isOnErrorCalled());
81         assertFalse(eventListener.isConnectionClosedCalled());
82
83         webSocket.stop();
84         webSocket.onClose(StatusCode.ABNORMAL, "Test");
85
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());
91     }
92
93     @Test
94     public void testOnCloseAfterRestart() throws Exception {
95         startWebSocket();
96
97         assertFalse(eventListener.isOnEventCalled());
98         assertFalse(eventListener.isOnErrorCalled());
99         assertFalse(eventListener.isConnectionClosedCalled());
100
101         webSocket.stop();
102         webSocket.onClose(StatusCode.ABNORMAL, "Test");
103
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());
109
110         startWebSocket();
111
112         webSocket.onClose(StatusCode.ABNORMAL, "Test");
113
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());
118     }
119
120     @Test
121     public void testOnCloseAbnormal() throws Exception {
122         startWebSocket();
123
124         assertFalse(eventListener.isOnEventCalled());
125         assertFalse(eventListener.isOnErrorCalled());
126         assertFalse(eventListener.isConnectionClosedCalled());
127
128         webSocket.onClose(StatusCode.ABNORMAL, "Test");
129
130         assertFalse(eventListener.isOnEventCalled());
131         assertFalse(eventListener.isOnErrorCalled());
132         assertTrue(eventListener.isConnectionClosedCalled());
133     }
134
135     @Test
136     public void testOnCloseNormal() throws Exception {
137         startWebSocket();
138
139         assertFalse(eventListener.isOnEventCalled());
140         assertFalse(eventListener.isOnErrorCalled());
141         assertFalse(eventListener.isConnectionClosedCalled());
142
143         webSocket.onClose(StatusCode.NORMAL, "Test");
144
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());
149     }
150
151     @Test
152     public void testOnMessage() throws Exception {
153         startWebSocket();
154
155         assertFalse(eventListener.isOnEventCalled());
156         assertFalse(eventListener.isOnErrorCalled());
157         assertFalse(eventListener.isConnectionClosedCalled());
158
159         webSocket.onMessage("Test-Message");
160
161         assertTrue(eventListener.isOnEventCalled());
162         assertFalse(eventListener.isOnErrorCalled());
163         assertFalse(eventListener.isConnectionClosedCalled());
164     }
165
166     @Test
167     public void testOnMessageAfterStop() throws Exception {
168         startWebSocket();
169
170         assertFalse(eventListener.isOnEventCalled());
171         assertFalse(eventListener.isOnErrorCalled());
172         assertFalse(eventListener.isConnectionClosedCalled());
173
174         webSocket.stop();
175         webSocket.onClose(StatusCode.ABNORMAL, "Test");
176         webSocket.onMessage("Test-Message");
177
178         assertFalse(eventListener.isOnEventCalled());
179         assertFalse(eventListener.isOnErrorCalled());
180         assertFalse(eventListener.isConnectionClosedCalled());
181     }
182
183     @Test
184     public void testOnError() throws Exception {
185         startWebSocket();
186
187         assertFalse(eventListener.isOnEventCalled());
188         assertFalse(eventListener.isOnErrorCalled());
189         assertFalse(eventListener.isConnectionClosedCalled());
190
191         webSocket.onError(new RuntimeException("Test-Exception"));
192
193         assertFalse(eventListener.isOnEventCalled());
194         assertTrue(eventListener.isOnErrorCalled());
195         assertFalse(eventListener.isConnectionClosedCalled());
196     }
197
198     private void startWebSocket() throws Exception {
199         webSocket.start();
200         when(sessionMock.isOpen()).thenReturn(true);
201
202         webSocket.onConnect(sessionMock);
203     }
204
205     private class LivisiWebSocketAccessible extends LivisiWebSocket {
206
207         private LivisiWebSocketAccessible(HttpClient httpClient, EventListener eventListener, URI webSocketURI,
208                 int maxIdleTimeout) {
209             super(httpClient, eventListener, webSocketURI, maxIdleTimeout);
210         }
211
212         @Override
213         WebSocketClient createWebSocketClient() {
214             return webSocketClientMock;
215         }
216
217         @Override
218         void startWebSocketClient(WebSocketClient client) {
219         }
220
221         @Override
222         void stopWebSocketClient(WebSocketClient client) {
223         }
224     }
225
226     private static class EventListenerDummy implements EventListener {
227
228         private boolean isOnEventCalled;
229         private boolean isOnErrorCalled;
230         private boolean isConnectionClosedCalled;
231
232         @Override
233         public void onEvent(String msg) {
234             isOnEventCalled = true;
235         }
236
237         @Override
238         public void onError(Throwable cause) {
239             isOnErrorCalled = true;
240         }
241
242         @Override
243         public void connectionClosed() {
244             isConnectionClosedCalled = true;
245         }
246
247         public boolean isOnEventCalled() {
248             return isOnEventCalled;
249         }
250
251         public boolean isOnErrorCalled() {
252             return isOnErrorCalled;
253         }
254
255         public boolean isConnectionClosedCalled() {
256             return isConnectionClosedCalled;
257         }
258     }
259 }