]> git.basschouten.com Git - openhab-addons.git/blob
d005cb906fbe6a981057d7e23b68be332a759a43
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2024 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.clip2;
14
15 import static org.hamcrest.CoreMatchers.*;
16 import static org.hamcrest.MatcherAssert.assertThat;
17 import static org.junit.jupiter.api.Assertions.assertThrows;
18
19 import java.util.ArrayList;
20 import java.util.List;
21 import java.util.stream.Stream;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.junit.jupiter.api.Test;
25 import org.junit.jupiter.params.ParameterizedTest;
26 import org.junit.jupiter.params.provider.Arguments;
27 import org.junit.jupiter.params.provider.MethodSource;
28 import org.openhab.binding.hue.internal.api.dto.clip2.ColorTemperature;
29 import org.openhab.binding.hue.internal.api.dto.clip2.Dimming;
30 import org.openhab.binding.hue.internal.api.dto.clip2.Effects;
31 import org.openhab.binding.hue.internal.api.dto.clip2.OnState;
32 import org.openhab.binding.hue.internal.api.dto.clip2.Resource;
33 import org.openhab.binding.hue.internal.api.dto.clip2.enums.ResourceType;
34 import org.openhab.binding.hue.internal.api.dto.clip2.helper.Setters;
35 import org.openhab.binding.hue.internal.exceptions.DTOPresentButEmptyException;
36
37 /**
38  * Tests for {@link Setters}.
39  * 
40  * @author Jacob Laursen - Initial contribution
41  */
42 @NonNullByDefault
43 public class SettersTest {
44
45     /**
46      * Tests merging of on state and dimming for same resource.
47      *
48      * Input:
49      * - Resource 1: type=light/grouped_light, sparse, id=1, on=on
50      * - Resource 2: type=light/grouped_light, sparse, id=1, dimming=50
51      *
52      * Expected output:
53      * - Resource 1: type=light/grouped_light, sparse, id=1, on=on, dimming=50
54      * 
55      * @throws DTOPresentButEmptyException
56      */
57     @ParameterizedTest
58     @MethodSource("provideLightResourceTypes")
59     void mergeLightResourcesMergeOnStateAndDimmingWhenSparseAndSameId(ResourceType resourceType)
60             throws DTOPresentButEmptyException {
61         List<Resource> resources = new ArrayList<>();
62
63         Resource resource1 = createResource(resourceType, "1");
64         resource1.setOnState(createOnState(true));
65         resources.add(resource1);
66
67         Resource resource2 = createResource(resourceType, "1");
68         resource2.setDimming(createDimming(50));
69         resources.add(resource2);
70
71         Setters.mergeLightResources(resources);
72
73         assertThat(resources.size(), is(equalTo(1)));
74         Resource mergedResource = resources.get(0);
75         assertThat(mergedResource.getId(), is(equalTo(resource1.getId())));
76         assertThat(mergedResource.getType(), is(equalTo(resourceType)));
77         assertThat(mergedResource.hasFullState(), is(false));
78         OnState actualOnState = mergedResource.getOnState();
79         assertThat(actualOnState, is(notNullValue()));
80         if (actualOnState != null) {
81             assertThat(actualOnState.isOn(), is(true));
82         }
83         Dimming actualDimming = mergedResource.getDimming();
84         assertThat(actualDimming, is(notNullValue()));
85         if (actualDimming != null) {
86             assertThat(actualDimming.getBrightness(), is(equalTo(50.0)));
87         }
88     }
89
90     private static Stream<Arguments> provideLightResourceTypes() {
91         return Stream.of(Arguments.of(ResourceType.LIGHT), Arguments.of(ResourceType.GROUPED_LIGHT));
92     }
93
94     /**
95      * Tests merging of dimming for same resource where last value wins.
96      *
97      * Input:
98      * - Resource 1: type=light, sparse, id=1, dimming=49
99      * - Resource 2: type=light, sparse, id=1, dimming=50
100      *
101      * Expected output:
102      * - Resource 1: type=light, sparse, id=1, dimming=50
103      * 
104      * @throws DTOPresentButEmptyException
105      */
106     @Test
107     void mergeLightResourcesMergeDimmingToLatestValueWhenSparseAndSameId() throws DTOPresentButEmptyException {
108         List<Resource> resources = new ArrayList<>();
109
110         Resource resource1 = createResource(ResourceType.LIGHT, "1");
111         resource1.setDimming(createDimming(49));
112         resources.add(resource1);
113
114         Resource resource2 = createResource(ResourceType.LIGHT, "1");
115         resource2.setDimming(createDimming(50));
116         resources.add(resource2);
117
118         Setters.mergeLightResources(resources);
119
120         assertThat(resources.size(), is(equalTo(1)));
121         Resource mergedResource = resources.get(0);
122         assertThat(mergedResource.hasFullState(), is(false));
123         Dimming actualDimming = mergedResource.getDimming();
124         assertThat(actualDimming, is(notNullValue()));
125         if (actualDimming != null) {
126             assertThat(actualDimming.getBrightness(), is(equalTo(50.0)));
127         }
128     }
129
130     /**
131      * Tests merging of HSB type fields while keeping resource with effects.
132      *
133      * Input:
134      * - Resource 1: type=light, sparse, id=1, dimming=49
135      * - Resource 2: type=light, sparse, id=1, on=on, dimming=50, effect=xxx
136      *
137      * Expected output:
138      * - Resource 1: type=light, sparse, id=1, on=on, dimming=50
139      * - Resource 2: type=light, sparse, id=1, effect=xxx
140      * 
141      * @throws DTOPresentButEmptyException
142      */
143     @Test
144     void mergeLightResourcesMergeHSBFieldsDoNotRemoveResourceWithEffect() throws DTOPresentButEmptyException {
145         List<Resource> resources = new ArrayList<>();
146
147         Resource resource1 = createResource(ResourceType.LIGHT, "1");
148         resource1.setDimming(createDimming(49));
149         resources.add(resource1);
150
151         Resource resource2 = createResource(ResourceType.LIGHT, "1");
152         resource2.setDimming(createDimming(50));
153         resource2.setOnState(createOnState(true));
154         resource2.setFixedEffects(new Effects());
155         resources.add(resource2);
156
157         Setters.mergeLightResources(resources);
158
159         assertThat(resources.size(), is(equalTo(2)));
160         Resource mergedResource = resources.get(0);
161         assertThat(mergedResource.hasFullState(), is(false));
162         OnState actualOnState = mergedResource.getOnState();
163         assertThat(actualOnState, is(notNullValue()));
164         if (actualOnState != null) {
165             assertThat(actualOnState.isOn(), is(true));
166         }
167         Dimming actualDimming = mergedResource.getDimming();
168         assertThat(actualDimming, is(notNullValue()));
169         if (actualDimming != null) {
170             assertThat(actualDimming.getBrightness(), is(equalTo(50.0)));
171         }
172
173         Resource effectsResource = resources.get(1);
174         assertThat(effectsResource.hasFullState(), is(false));
175         assertThat(effectsResource.getFixedEffects(), is(notNullValue()));
176     }
177
178     /**
179      * Tests leaving different resources separated.
180      *
181      * Input:
182      * - Resource 1: type=light, sparse, id=1, on=on
183      * - Resource 2: type=light, sparse, id=2, dimming=50
184      *
185      * Expected output:
186      * - Resource 1: type=light, sparse, id=1, on=on
187      * - Resource 2: type=light, sparse, id=2, dimming=50
188      * 
189      * @throws DTOPresentButEmptyException
190      */
191     @Test
192     void mergeLightResourcesDoNotMergeOnStateAndDimmingWhenSparseAndDifferentId() throws DTOPresentButEmptyException {
193         List<Resource> resources = new ArrayList<>();
194
195         Resource resource1 = createResource(ResourceType.LIGHT, "1");
196         resource1.setOnState(createOnState(true));
197         resources.add(resource1);
198
199         Resource resource2 = createResource(ResourceType.LIGHT, "2");
200         resource2.setDimming(createDimming(50));
201         resources.add(resource2);
202
203         Setters.mergeLightResources(resources);
204
205         assertThat(resources.size(), is(equalTo(2)));
206         Resource firstResource = resources.get(0);
207         OnState actualOnState = firstResource.getOnState();
208         assertThat(actualOnState, is(notNullValue()));
209         if (actualOnState != null) {
210             assertThat(actualOnState.isOn(), is(true));
211         }
212         assertThat(firstResource.getDimming(), is(nullValue()));
213
214         Resource secondResource = resources.get(1);
215         assertThat(secondResource.getOnState(), is(nullValue()));
216         Dimming actualDimming = secondResource.getDimming();
217         assertThat(actualDimming, is(notNullValue()));
218         if (actualDimming != null) {
219             assertThat(actualDimming.getBrightness(), is(equalTo(50.0)));
220         }
221     }
222
223     /**
224      * Tests merging of on state and dimming for same resource when full is first.
225      *
226      * Input:
227      * - Resource 1: type=light, full, id=1, on=on
228      *
229      * Expected output:
230      * - Exception thrown, full state is not supported/expected.
231      * 
232      * @throws DTOPresentButEmptyException
233      */
234     @Test
235     void mergeLightResourcesMergeOnStateAndDimmingWhenFullStateFirstAndSameId() throws DTOPresentButEmptyException {
236         List<Resource> resources = new ArrayList<>();
237
238         Resource resource = new Resource(ResourceType.LIGHT);
239         resource.setId("1");
240
241         resources.add(resource);
242
243         assertThrows(IllegalStateException.class, () -> Setters.mergeLightResources(resources));
244     }
245
246     /**
247      * Tests leaving resources with on state and color temperature separated.
248      * In this case they could be merged, but it's not needed.
249      *
250      * Input:
251      * - Resource 1: type=light, sparse, id=1, on=on
252      * - Resource 2: type=light, sparse, id=1, color temperature=370 mirek
253      *
254      * Expected output:
255      * - Resource 1: type=light, sparse, id=1, on=on
256      * - Resource 2: type=light, sparse, id=1, color temperature=370 mirek
257      * 
258      * @throws DTOPresentButEmptyException
259      */
260     @Test
261     void mergeLightResourcesDoNotMergeOnStateAndColorTemperatureWhenSparseAndSameId()
262             throws DTOPresentButEmptyException {
263         List<Resource> resources = new ArrayList<>();
264
265         Resource resource1 = createResource(ResourceType.LIGHT, "1");
266         resource1.setOnState(createOnState(true));
267         resources.add(resource1);
268
269         Resource resource2 = createResource(ResourceType.LIGHT, "1");
270         resource2.setColorTemperature(createColorTemperature(370));
271         resources.add(resource2);
272
273         Setters.mergeLightResources(resources);
274
275         assertThat(resources.size(), is(equalTo(2)));
276         Resource firstResource = resources.get(0);
277         OnState actualOnState = firstResource.getOnState();
278         assertThat(actualOnState, is(notNullValue()));
279         if (actualOnState != null) {
280             assertThat(actualOnState.isOn(), is(true));
281         }
282         assertThat(firstResource.getColorTemperature(), is(nullValue()));
283
284         Resource secondResource = resources.get(1);
285         assertThat(secondResource.getOnState(), is(nullValue()));
286         ColorTemperature actualColorTemperature = secondResource.getColorTemperature();
287         assertThat(actualColorTemperature, is(notNullValue()));
288         if (actualColorTemperature != null) {
289             assertThat(actualColorTemperature.getMirek(), is(equalTo(370L)));
290         }
291     }
292
293     /**
294      * Tests merging resources with on state/color and leaving color temperature separated.
295      * In this case they could be merged, but it's not needed.
296      *
297      * Input:
298      * - Resource 1: type=light, sparse, id=1, on=on
299      * - Resource 2: type=light, sparse, id=1, dimming=50, color temperature=370 mirek
300      *
301      * Expected output:
302      * - Resource 1: type=light, sparse, id=1, on=on, dimming=50
303      * - Resource 2: type=light, sparse, id=1, color temperature=370 mirek
304      * 
305      * @throws DTOPresentButEmptyException
306      */
307     @Test
308     void mergeLightResourcesMergeOnStateAndDimmingButNotColorTemperatureWhenSparseAndSameId()
309             throws DTOPresentButEmptyException {
310         List<Resource> resources = new ArrayList<>();
311
312         Resource resource1 = createResource(ResourceType.LIGHT, "1");
313         resource1.setOnState(createOnState(true));
314         resources.add(resource1);
315
316         Resource resource2 = createResource(ResourceType.LIGHT, "1");
317         resource2.setDimming(createDimming(50));
318         resource2.setColorTemperature(createColorTemperature(370));
319         resources.add(resource2);
320
321         Setters.mergeLightResources(resources);
322
323         assertThat(resources.size(), is(equalTo(2)));
324         Resource firstResource = resources.get(0);
325         OnState actualOnState = firstResource.getOnState();
326         assertThat(actualOnState, is(notNullValue()));
327         if (actualOnState != null) {
328             assertThat(actualOnState.isOn(), is(true));
329         }
330         Dimming actualDimming = firstResource.getDimming();
331         assertThat(actualDimming, is(notNullValue()));
332         if (actualDimming != null) {
333             assertThat(actualDimming.getBrightness(), is(equalTo(50.0)));
334         }
335         assertThat(firstResource.getColorTemperature(), is(nullValue()));
336
337         Resource secondResource = resources.get(1);
338         assertThat(secondResource.getOnState(), is(nullValue()));
339         assertThat(secondResource.getDimming(), is(nullValue()));
340         ColorTemperature actualColorTemperature = secondResource.getColorTemperature();
341         assertThat(actualColorTemperature, is(notNullValue()));
342         if (actualColorTemperature != null) {
343             assertThat(actualColorTemperature.getMirek(), is(equalTo(370L)));
344         }
345     }
346
347     /**
348      * Tests preserving resource with on state and color temperature.
349      *
350      * Input:
351      * - Resource 1: type=light, sparse, id=1, on=on, color temperature=370
352      *
353      * Expected output:
354      * - Resource 1: type=light, sparse, id=1, on=on, color temperature=370
355      * 
356      * @throws DTOPresentButEmptyException
357      */
358     @Test
359     void mergeLightResourcesSeparateOnStateAndColorTemperatureWhenSparseAndSameId() throws DTOPresentButEmptyException {
360         List<Resource> resources = new ArrayList<>();
361
362         Resource resource = createResource(ResourceType.LIGHT, "1");
363         resource.setOnState(createOnState(true));
364         resource.setColorTemperature(createColorTemperature(370));
365         resources.add(resource);
366
367         Setters.mergeLightResources(resources);
368
369         assertThat(resources.size(), is(equalTo(1)));
370
371         Resource firstResource = resources.get(0);
372         OnState actualOnState = firstResource.getOnState();
373         assertThat(actualOnState, is(notNullValue()));
374         if (actualOnState != null) {
375             assertThat(actualOnState.isOn(), is(true));
376         }
377         ColorTemperature actualColorTemperature = firstResource.getColorTemperature();
378         assertThat(actualColorTemperature, is(notNullValue()));
379         if (actualColorTemperature != null) {
380             assertThat(actualColorTemperature.getMirek(), is(equalTo(370L)));
381         }
382     }
383
384     /**
385      * Tests that resources that are not light or grouped_light will not throw.
386      *
387      * Input:
388      * - Resource 1: type=motion, sparse, id=1
389      *
390      * Expected output:
391      * - Resource 1: type=motion, sparse, id=1
392      * 
393      * @throws DTOPresentButEmptyException
394      */
395     @Test
396     void mergeLightResourcesNonLightResourceShouldNotThrow() throws DTOPresentButEmptyException {
397         List<Resource> resources = new ArrayList<>();
398
399         Resource resource = createResource(ResourceType.MOTION, "1");
400         resources.add(resource);
401
402         Setters.mergeLightResources(resources);
403
404         assertThat(resources.size(), is(equalTo(1)));
405
406         Resource firstResource = resources.get(0);
407         assertThat(firstResource.getType(), is(equalTo(ResourceType.MOTION)));
408     }
409
410     private OnState createOnState(boolean on) {
411         OnState onState = new OnState();
412         onState.setOn(on);
413
414         return onState;
415     }
416
417     private Dimming createDimming(double brightness) {
418         Dimming dimming = new Dimming();
419         dimming.setBrightness(brightness);
420
421         return dimming;
422     }
423
424     private ColorTemperature createColorTemperature(double mirek) {
425         ColorTemperature colorTemperature = new ColorTemperature();
426         colorTemperature.setMirek(mirek);
427
428         return colorTemperature;
429     }
430
431     private Resource createResource(ResourceType resourceType, String id) {
432         Resource resource = new Resource(resourceType);
433         resource.setId(id);
434         resource.markAsSparse();
435
436         return resource;
437     }
438 }