]> git.basschouten.com Git - openhab-addons.git/blob
4fc8e06eccc47ea3b649666ddf1f67b586bcc99d
[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.mielecloud.internal.auth;
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.io.IOException;
20 import java.util.Map;
21 import java.util.Objects;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.junit.jupiter.api.Test;
26 import org.mockito.invocation.InvocationOnMock;
27 import org.mockito.stubbing.Answer;
28 import org.openhab.binding.mielecloud.internal.MieleCloudBindingTestConstants;
29 import org.openhab.binding.mielecloud.internal.util.ReflectionUtil;
30 import org.openhab.core.auth.client.oauth2.AccessTokenRefreshListener;
31 import org.openhab.core.auth.client.oauth2.AccessTokenResponse;
32 import org.openhab.core.auth.client.oauth2.OAuthClientService;
33 import org.openhab.core.auth.client.oauth2.OAuthFactory;
34 import org.openhab.core.auth.client.oauth2.OAuthResponseException;
35
36 /**
37  * @author Björn Lange - Initial contribution
38  */
39 @NonNullByDefault
40 public class OpenHabOAuthTokenRefresherTest {
41     private static final String ACCESS_TOKEN = "DE_0123456789abcdef0123456789abcdef";
42
43     private boolean hasAccessTokenRefreshListenerForServiceHandle(OpenHabOAuthTokenRefresher refresher,
44             String serviceHandle)
45             throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
46         return ReflectionUtil
47                 .<Map<String, @Nullable AccessTokenRefreshListener>> getPrivate(refresher, "listenerByServiceHandle")
48                 .get(MieleCloudBindingTestConstants.SERVICE_HANDLE) != null;
49     }
50
51     private AccessTokenRefreshListener getAccessTokenRefreshListenerByServiceHandle(
52             OpenHabOAuthTokenRefresher refresher, String serviceHandle)
53             throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
54         AccessTokenRefreshListener listener = ReflectionUtil
55                 .<Map<String, @Nullable AccessTokenRefreshListener>> getPrivate(refresher, "listenerByServiceHandle")
56                 .get(MieleCloudBindingTestConstants.SERVICE_HANDLE);
57         assertNotNull(listener);
58         return Objects.requireNonNull(listener);
59     }
60
61     @Test
62     public void whenTheAccountWasNotConfiguredPriorToTheThingInitializingThenNoRefreshListenerCanBeRegistered() {
63         // given:
64         OAuthFactory oauthFactory = mock(OAuthFactory.class);
65         OpenHabOAuthTokenRefresher refresher = new OpenHabOAuthTokenRefresher(oauthFactory);
66         OAuthTokenRefreshListener listener = mock(OAuthTokenRefreshListener.class);
67
68         // when:
69         assertThrows(OAuthException.class, () -> {
70             refresher.setRefreshListener(listener, MieleCloudBindingTestConstants.SERVICE_HANDLE);
71         });
72     }
73
74     @Test
75     public void whenARefreshListenerIsRegisteredThenAListenerIsRegisteredAtTheClientService()
76             throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
77         // given:
78         OAuthClientService oauthClientService = mock(OAuthClientService.class);
79
80         OAuthFactory oauthFactory = mock(OAuthFactory.class);
81         when(oauthFactory.getOAuthClientService(MieleCloudBindingTestConstants.SERVICE_HANDLE))
82                 .thenReturn(oauthClientService);
83
84         OpenHabOAuthTokenRefresher refresher = new OpenHabOAuthTokenRefresher(oauthFactory);
85
86         OAuthTokenRefreshListener listener = mock(OAuthTokenRefreshListener.class);
87
88         // when:
89         refresher.setRefreshListener(listener, MieleCloudBindingTestConstants.SERVICE_HANDLE);
90
91         // then:
92         verify(oauthClientService).addAccessTokenRefreshListener(any());
93         assertNotNull(
94                 getAccessTokenRefreshListenerByServiceHandle(refresher, MieleCloudBindingTestConstants.SERVICE_HANDLE));
95     }
96
97     @Test
98     public void whenTokenIsRefreshedThenTheListenerIsCalledWithTheNewAccessToken()
99             throws org.openhab.core.auth.client.oauth2.OAuthException, IOException, OAuthResponseException {
100         // given:
101         AccessTokenResponse accessTokenResponse = new AccessTokenResponse();
102         accessTokenResponse.setAccessToken(ACCESS_TOKEN);
103
104         OAuthClientService oauthClientService = mock(OAuthClientService.class);
105
106         OAuthFactory oauthFactory = mock(OAuthFactory.class);
107         when(oauthFactory.getOAuthClientService(MieleCloudBindingTestConstants.SERVICE_HANDLE))
108                 .thenReturn(oauthClientService);
109
110         OpenHabOAuthTokenRefresher refresher = new OpenHabOAuthTokenRefresher(oauthFactory);
111         when(oauthClientService.refreshToken()).thenAnswer(new Answer<@Nullable AccessTokenResponse>() {
112             @Override
113             @Nullable
114             public AccessTokenResponse answer(@Nullable InvocationOnMock invocation) throws Throwable {
115                 getAccessTokenRefreshListenerByServiceHandle(refresher, MieleCloudBindingTestConstants.SERVICE_HANDLE)
116                         .onAccessTokenResponse(accessTokenResponse);
117                 return accessTokenResponse;
118             }
119         });
120
121         OAuthTokenRefreshListener listener = mock(OAuthTokenRefreshListener.class);
122         refresher.setRefreshListener(listener, MieleCloudBindingTestConstants.SERVICE_HANDLE);
123
124         // when:
125         refresher.refreshToken(MieleCloudBindingTestConstants.SERVICE_HANDLE);
126
127         // then:
128         verify(listener).onNewAccessToken(ACCESS_TOKEN);
129     }
130
131     @Test
132     public void whenTokenIsRefreshedAndNoAccessTokenIsProvidedThenTheListenerIsNotNotified()
133             throws org.openhab.core.auth.client.oauth2.OAuthException, IOException, OAuthResponseException {
134         // given:
135         AccessTokenResponse accessTokenResponse = new AccessTokenResponse();
136
137         OAuthClientService oauthClientService = mock(OAuthClientService.class);
138
139         OAuthFactory oauthFactory = mock(OAuthFactory.class);
140         when(oauthFactory.getOAuthClientService(MieleCloudBindingTestConstants.SERVICE_HANDLE))
141                 .thenReturn(oauthClientService);
142
143         OpenHabOAuthTokenRefresher refresher = new OpenHabOAuthTokenRefresher(oauthFactory);
144         when(oauthClientService.refreshToken()).thenAnswer(new Answer<@Nullable AccessTokenResponse>() {
145             @Override
146             @Nullable
147             public AccessTokenResponse answer(@Nullable InvocationOnMock invocation) throws Throwable {
148                 getAccessTokenRefreshListenerByServiceHandle(refresher, MieleCloudBindingTestConstants.SERVICE_HANDLE)
149                         .onAccessTokenResponse(accessTokenResponse);
150                 return accessTokenResponse;
151             }
152         });
153
154         OAuthTokenRefreshListener listener = mock(OAuthTokenRefreshListener.class);
155         refresher.setRefreshListener(listener, MieleCloudBindingTestConstants.SERVICE_HANDLE);
156
157         // when:
158         assertThrows(OAuthException.class, () -> {
159             try {
160                 refresher.refreshToken(MieleCloudBindingTestConstants.SERVICE_HANDLE);
161             } catch (OAuthException e) {
162                 verifyNoInteractions(listener);
163                 throw e;
164             }
165         });
166     }
167
168     @Test
169     public void whenTokenRefreshFailsWithOAuthExceptionThenTheListenerIsNotNotified()
170             throws org.openhab.core.auth.client.oauth2.OAuthException, IOException, OAuthResponseException {
171         // given:
172         OAuthClientService oauthClientService = mock(OAuthClientService.class);
173         when(oauthClientService.refreshToken()).thenThrow(new org.openhab.core.auth.client.oauth2.OAuthException());
174
175         OAuthFactory oauthFactory = mock(OAuthFactory.class);
176         when(oauthFactory.getOAuthClientService(MieleCloudBindingTestConstants.SERVICE_HANDLE))
177                 .thenReturn(oauthClientService);
178
179         OpenHabOAuthTokenRefresher refresher = new OpenHabOAuthTokenRefresher(oauthFactory);
180
181         OAuthTokenRefreshListener listener = mock(OAuthTokenRefreshListener.class);
182         refresher.setRefreshListener(listener, MieleCloudBindingTestConstants.SERVICE_HANDLE);
183
184         // when:
185         assertThrows(OAuthException.class, () -> {
186             try {
187                 refresher.refreshToken(MieleCloudBindingTestConstants.SERVICE_HANDLE);
188             } catch (OAuthException e) {
189                 verifyNoInteractions(listener);
190                 throw e;
191             }
192         });
193     }
194
195     @Test
196     public void whenTokenRefreshFailsDueToNetworkErrorThenTheListenerIsNotNotified()
197             throws org.openhab.core.auth.client.oauth2.OAuthException, IOException, OAuthResponseException {
198         // given:
199         OAuthClientService oauthClientService = mock(OAuthClientService.class);
200         when(oauthClientService.refreshToken()).thenThrow(new IOException());
201
202         OAuthFactory oauthFactory = mock(OAuthFactory.class);
203         when(oauthFactory.getOAuthClientService(MieleCloudBindingTestConstants.SERVICE_HANDLE))
204                 .thenReturn(oauthClientService);
205
206         OpenHabOAuthTokenRefresher refresher = new OpenHabOAuthTokenRefresher(oauthFactory);
207
208         OAuthTokenRefreshListener listener = mock(OAuthTokenRefreshListener.class);
209         refresher.setRefreshListener(listener, MieleCloudBindingTestConstants.SERVICE_HANDLE);
210
211         // when:
212         assertThrows(OAuthException.class, () -> {
213             try {
214                 refresher.refreshToken(MieleCloudBindingTestConstants.SERVICE_HANDLE);
215             } catch (OAuthException e) {
216                 verifyNoInteractions(listener);
217                 throw e;
218             }
219         });
220     }
221
222     @Test
223     public void whenTokenRefreshFailsDueToAnIllegalResponseThenTheListenerIsNotNotified()
224             throws org.openhab.core.auth.client.oauth2.OAuthException, IOException, OAuthResponseException {
225         // given:
226         OAuthClientService oauthClientService = mock(OAuthClientService.class);
227         when(oauthClientService.refreshToken()).thenThrow(new OAuthResponseException());
228
229         OAuthFactory oauthFactory = mock(OAuthFactory.class);
230         when(oauthFactory.getOAuthClientService(MieleCloudBindingTestConstants.SERVICE_HANDLE))
231                 .thenReturn(oauthClientService);
232
233         OpenHabOAuthTokenRefresher refresher = new OpenHabOAuthTokenRefresher(oauthFactory);
234
235         OAuthTokenRefreshListener listener = mock(OAuthTokenRefreshListener.class);
236         refresher.setRefreshListener(listener, MieleCloudBindingTestConstants.SERVICE_HANDLE);
237
238         // when:
239         assertThrows(OAuthException.class, () -> {
240             try {
241                 refresher.refreshToken(MieleCloudBindingTestConstants.SERVICE_HANDLE);
242             } catch (OAuthException e) {
243                 verifyNoInteractions(listener);
244                 throw e;
245             }
246         });
247     }
248
249     @Test
250     public void whenTheRefreshListenerIsUnsetAndWasNotRegisteredBeforeThenNothingHappens()
251             throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
252         // given:
253         OAuthFactory oauthFactory = mock(OAuthFactory.class);
254         OpenHabOAuthTokenRefresher refresher = new OpenHabOAuthTokenRefresher(oauthFactory);
255
256         // when:
257         refresher.unsetRefreshListener(MieleCloudBindingTestConstants.SERVICE_HANDLE);
258
259         // then:
260         assertFalse(hasAccessTokenRefreshListenerForServiceHandle(refresher,
261                 MieleCloudBindingTestConstants.SERVICE_HANDLE));
262     }
263
264     @Test
265     public void whenTheRefreshListenerIsUnsetAndTheClientServiceIsNotAvailableThenTheListenerIsCleared()
266             throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
267         // given:
268         OAuthClientService oauthClientService = mock(OAuthClientService.class);
269
270         OAuthFactory oauthFactory = mock(OAuthFactory.class);
271         when(oauthFactory.getOAuthClientService(MieleCloudBindingTestConstants.SERVICE_HANDLE))
272                 .thenReturn(oauthClientService);
273
274         OpenHabOAuthTokenRefresher refresher = new OpenHabOAuthTokenRefresher(oauthFactory);
275
276         OAuthTokenRefreshListener listener = mock(OAuthTokenRefreshListener.class);
277
278         refresher.setRefreshListener(listener, MieleCloudBindingTestConstants.SERVICE_HANDLE);
279
280         // when:
281         refresher.unsetRefreshListener(MieleCloudBindingTestConstants.SERVICE_HANDLE);
282
283         // then:
284         assertFalse(hasAccessTokenRefreshListenerForServiceHandle(refresher,
285                 MieleCloudBindingTestConstants.SERVICE_HANDLE));
286     }
287
288     @Test
289     public void whenTheRefreshListenerIsUnsetThenTheListenerIsClearedAndRemovedFromTheClientService()
290             throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException {
291         // given:
292         OAuthClientService oauthClientService = mock(OAuthClientService.class);
293
294         OAuthFactory oauthFactory = mock(OAuthFactory.class);
295         when(oauthFactory.getOAuthClientService(MieleCloudBindingTestConstants.SERVICE_HANDLE))
296                 .thenReturn(oauthClientService);
297
298         OpenHabOAuthTokenRefresher refresher = new OpenHabOAuthTokenRefresher(oauthFactory);
299
300         OAuthTokenRefreshListener listener = mock(OAuthTokenRefreshListener.class);
301
302         refresher.setRefreshListener(listener, MieleCloudBindingTestConstants.SERVICE_HANDLE);
303
304         // when:
305         refresher.unsetRefreshListener(MieleCloudBindingTestConstants.SERVICE_HANDLE);
306
307         // then:
308         verify(oauthClientService).removeAccessTokenRefreshListener(any());
309         assertFalse(hasAccessTokenRefreshListenerForServiceHandle(refresher,
310                 MieleCloudBindingTestConstants.SERVICE_HANDLE));
311     }
312
313     @Test
314     public void whenTokensAreRemovedThenTheRuntimeIsRequestedToDeleteServiceAndAccessToken()
315             throws org.openhab.core.auth.client.oauth2.OAuthException, IOException, OAuthResponseException {
316         // given:
317         OAuthClientService oauthClientService = mock(OAuthClientService.class);
318
319         OAuthFactory oauthFactory = mock(OAuthFactory.class);
320         when(oauthFactory.getOAuthClientService(MieleCloudBindingTestConstants.SERVICE_HANDLE))
321                 .thenReturn(oauthClientService);
322
323         OpenHabOAuthTokenRefresher refresher = new OpenHabOAuthTokenRefresher(oauthFactory);
324
325         OAuthTokenRefreshListener listener = mock(OAuthTokenRefreshListener.class);
326         refresher.setRefreshListener(listener, MieleCloudBindingTestConstants.SERVICE_HANDLE);
327
328         // when:
329         refresher.removeTokensFromStorage(MieleCloudBindingTestConstants.SERVICE_HANDLE);
330
331         // then:
332         verify(oauthFactory).deleteServiceAndAccessToken(MieleCloudBindingTestConstants.SERVICE_HANDLE);
333     }
334 }