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.hue.internal.clip2;
15 import static org.junit.jupiter.api.Assertions.*;
17 import java.io.BufferedReader;
18 import java.io.FileReader;
19 import java.io.IOException;
20 import java.lang.reflect.Field;
21 import java.time.Duration;
22 import java.util.List;
23 import java.util.Optional;
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.junit.jupiter.api.Test;
28 import org.openhab.binding.hue.internal.dto.clip2.ActionEntry;
29 import org.openhab.binding.hue.internal.dto.clip2.Alerts;
30 import org.openhab.binding.hue.internal.dto.clip2.Button;
31 import org.openhab.binding.hue.internal.dto.clip2.Dimming;
32 import org.openhab.binding.hue.internal.dto.clip2.Effects;
33 import org.openhab.binding.hue.internal.dto.clip2.Event;
34 import org.openhab.binding.hue.internal.dto.clip2.LightLevel;
35 import org.openhab.binding.hue.internal.dto.clip2.MetaData;
36 import org.openhab.binding.hue.internal.dto.clip2.MirekSchema;
37 import org.openhab.binding.hue.internal.dto.clip2.Motion;
38 import org.openhab.binding.hue.internal.dto.clip2.Power;
39 import org.openhab.binding.hue.internal.dto.clip2.ProductData;
40 import org.openhab.binding.hue.internal.dto.clip2.RelativeRotary;
41 import org.openhab.binding.hue.internal.dto.clip2.Resource;
42 import org.openhab.binding.hue.internal.dto.clip2.ResourceReference;
43 import org.openhab.binding.hue.internal.dto.clip2.Resources;
44 import org.openhab.binding.hue.internal.dto.clip2.Rotation;
45 import org.openhab.binding.hue.internal.dto.clip2.RotationEvent;
46 import org.openhab.binding.hue.internal.dto.clip2.Temperature;
47 import org.openhab.binding.hue.internal.dto.clip2.TimedEffects;
48 import org.openhab.binding.hue.internal.dto.clip2.enums.ActionType;
49 import org.openhab.binding.hue.internal.dto.clip2.enums.Archetype;
50 import org.openhab.binding.hue.internal.dto.clip2.enums.BatteryStateType;
51 import org.openhab.binding.hue.internal.dto.clip2.enums.ButtonEventType;
52 import org.openhab.binding.hue.internal.dto.clip2.enums.DirectionType;
53 import org.openhab.binding.hue.internal.dto.clip2.enums.EffectType;
54 import org.openhab.binding.hue.internal.dto.clip2.enums.ResourceType;
55 import org.openhab.binding.hue.internal.dto.clip2.enums.RotationEventType;
56 import org.openhab.binding.hue.internal.dto.clip2.enums.ZigbeeStatus;
57 import org.openhab.binding.hue.internal.dto.clip2.helper.Setters;
58 import org.openhab.core.library.types.DecimalType;
59 import org.openhab.core.library.types.HSBType;
60 import org.openhab.core.library.types.OnOffType;
61 import org.openhab.core.library.types.PercentType;
62 import org.openhab.core.library.types.QuantityType;
63 import org.openhab.core.library.types.StringType;
64 import org.openhab.core.types.State;
65 import org.openhab.core.types.UnDefType;
66 import org.openhab.core.util.ColorUtil;
68 import com.google.gson.Gson;
69 import com.google.gson.JsonElement;
70 import com.google.gson.JsonObject;
71 import com.google.gson.JsonParser;
72 import com.google.gson.JsonSyntaxException;
75 * JUnit test for CLIP 2 DTOs.
77 * @author Andrew Fiddian-Green - Initial contribution
82 private static final Gson GSON = new Gson();
83 private static final Double MINIMUM_DIMMING_LEVEL = Double.valueOf(12.34f);
86 * Load the test JSON payload string from a file
88 private String load(String fileName) {
89 try (FileReader file = new FileReader(String.format("src/test/resources/%s.json", fileName));
90 BufferedReader reader = new BufferedReader(file)) {
91 StringBuilder builder = new StringBuilder();
93 while ((line = reader.readLine()) != null) {
94 builder.append(line).append("\n");
96 return builder.toString();
97 } catch (IOException e) {
105 String json = load(ResourceType.BUTTON.name().toLowerCase());
106 Resources resources = GSON.fromJson(json, Resources.class);
107 assertNotNull(resources);
108 List<Resource> list = resources.getResources();
110 assertEquals(43, list.size());
111 Resource item = list.get(0);
112 assertEquals(ResourceType.BUTTON, item.getType());
113 Button button = item.getButton();
114 assertNotNull(button);
115 assertEquals(ButtonEventType.SHORT_RELEASE, button.getLastEvent());
120 String json = load(ResourceType.DEVICE.name().toLowerCase());
121 Resources resources = GSON.fromJson(json, Resources.class);
122 assertNotNull(resources);
123 List<Resource> list = resources.getResources();
125 assertEquals(34, list.size());
126 boolean itemFound = false;
127 for (Resource item : list) {
128 assertEquals(ResourceType.DEVICE, item.getType());
129 ProductData productData = item.getProductData();
130 assertNotNull(productData);
131 if (productData.getProductArchetype() == Archetype.BRIDGE_V2) {
133 assertEquals("BSB002", productData.getModelId());
134 assertEquals("Signify Netherlands B.V.", productData.getManufacturerName());
135 assertEquals("Philips hue", productData.getProductName());
136 assertNull(productData.getHardwarePlatformType());
137 assertTrue(productData.getCertified());
138 assertEquals("1.53.1953188020", productData.getSoftwareVersion());
142 assertTrue(itemFound);
146 void testDevicePower() {
147 String json = load(ResourceType.DEVICE_POWER.name().toLowerCase());
148 Resources resources = GSON.fromJson(json, Resources.class);
149 assertNotNull(resources);
150 List<Resource> list = resources.getResources();
152 assertEquals(16, list.size());
153 Resource item = list.get(0);
154 assertEquals(ResourceType.DEVICE_POWER, item.getType());
155 Power power = item.getPowerState();
156 assertNotNull(power);
157 assertEquals(60, power.getBatteryLevel());
158 assertEquals(BatteryStateType.NORMAL, power.getBatteryState());
162 void testGroupedLight() {
163 String json = load(ResourceType.GROUPED_LIGHT.name().toLowerCase());
164 Resources resources = GSON.fromJson(json, Resources.class);
165 assertNotNull(resources);
166 List<Resource> list = resources.getResources();
168 assertEquals(15, list.size());
170 for (Resource item : list) {
171 assertEquals(ResourceType.GROUPED_LIGHT, item.getType());
173 switch (item.getId()) {
174 case "db4fd630-3798-40de-b642-c1ef464bf770":
176 assertEquals(OnOffType.OFF, item.getOnOffState());
177 assertEquals(PercentType.ZERO, item.getBrightnessState());
178 alert = item.getAlerts();
179 assertNotNull(alert);
180 for (ActionType actionValue : alert.getActionValues()) {
181 assertEquals(ActionType.BREATHE, actionValue);
184 case "9228d710-3c54-4ae4-8c88-bfe57d8fd220":
186 assertEquals(OnOffType.ON, item.getOnOffState());
187 assertEquals(PercentType.HUNDRED, item.getBrightnessState());
188 alert = item.getAlerts();
189 assertNotNull(alert);
190 for (ActionType actionValue : alert.getActionValues()) {
191 assertEquals(ActionType.BREATHE, actionValue);
197 assertEquals(2, itemsFound);
202 String json = load(ResourceType.LIGHT.name().toLowerCase());
203 Resources resources = GSON.fromJson(json, Resources.class);
204 assertNotNull(resources);
205 List<Resource> list = resources.getResources();
207 assertEquals(17, list.size());
208 int itemFoundCount = 0;
209 for (Resource item : list) {
210 assertEquals(ResourceType.LIGHT, item.getType());
211 MetaData metaData = item.getMetaData();
212 assertNotNull(metaData);
213 String name = metaData.getName();
216 if (name.contains("Bay Window Lamp")) {
218 assertEquals(ResourceType.LIGHT, item.getType());
219 assertEquals(OnOffType.OFF, item.getOnOffState());
220 state = item.getBrightnessState();
221 assertTrue(state instanceof PercentType);
222 assertEquals(0, ((PercentType) state).doubleValue(), 0.1);
223 item.setOnOff(OnOffType.ON);
224 state = item.getBrightnessState();
225 assertTrue(state instanceof PercentType);
226 assertEquals(93.0, ((PercentType) state).doubleValue(), 0.1);
227 assertEquals(UnDefType.UNDEF, item.getColorTemperaturePercentState());
228 state = item.getColorState();
229 assertTrue(state instanceof HSBType);
230 double[] xy = ColorUtil.hsbToXY((HSBType) state);
231 assertEquals(0.6367, xy[0], 0.01); // note: rounding errors !!
232 assertEquals(0.3503, xy[1], 0.01); // note: rounding errors !!
233 assertEquals(item.getBrightnessState(), ((HSBType) state).getBrightness());
234 Alerts alert = item.getAlerts();
235 assertNotNull(alert);
236 for (ActionType actionValue : alert.getActionValues()) {
237 assertEquals(ActionType.BREATHE, actionValue);
240 if (name.contains("Table Lamp A")) {
242 assertEquals(ResourceType.LIGHT, item.getType());
243 assertEquals(OnOffType.OFF, item.getOnOffState());
244 state = item.getBrightnessState();
245 assertTrue(state instanceof PercentType);
246 assertEquals(0, ((PercentType) state).doubleValue(), 0.1);
247 item.setOnOff(OnOffType.ON);
248 state = item.getBrightnessState();
249 assertTrue(state instanceof PercentType);
250 assertEquals(56.7, ((PercentType) state).doubleValue(), 0.1);
251 MirekSchema mirekSchema = item.getMirekSchema();
252 assertNotNull(mirekSchema);
253 assertEquals(153, mirekSchema.getMirekMinimum());
254 assertEquals(454, mirekSchema.getMirekMaximum());
256 // test color temperature percent value on light's own scale
257 state = item.getColorTemperaturePercentState();
258 assertTrue(state instanceof PercentType);
259 assertEquals(96.3, ((PercentType) state).doubleValue(), 0.1);
260 state = item.getColorTemperatureAbsoluteState();
261 assertTrue(state instanceof QuantityType<?>);
262 assertEquals(2257.3, ((QuantityType<?>) state).doubleValue(), 0.1);
264 // test color temperature percent value on the default (full) scale
265 MirekSchema temp = item.getMirekSchema();
266 item.setMirekSchema(MirekSchema.DEFAULT_SCHEMA);
267 state = item.getColorTemperaturePercentState();
268 assertTrue(state instanceof PercentType);
269 assertEquals(83.6, ((PercentType) state).doubleValue(), 0.1);
270 state = item.getColorTemperatureAbsoluteState();
271 assertTrue(state instanceof QuantityType<?>);
272 assertEquals(2257.3, ((QuantityType<?>) state).doubleValue(), 0.1);
273 item.setMirekSchema(temp);
275 // change colour temperature percent to zero
276 Setters.setColorTemperaturePercent(item, PercentType.ZERO, null);
277 assertEquals(PercentType.ZERO, item.getColorTemperaturePercentState());
278 state = item.getColorTemperatureAbsoluteState();
279 assertTrue(state instanceof QuantityType<?>);
280 assertEquals(6535.9, ((QuantityType<?>) state).doubleValue(), 0.1);
282 // change colour temperature percent to 100
283 Setters.setColorTemperaturePercent(item, PercentType.HUNDRED, null);
284 assertEquals(PercentType.HUNDRED, item.getColorTemperaturePercentState());
285 state = item.getColorTemperatureAbsoluteState();
286 assertTrue(state instanceof QuantityType<?>);
287 assertEquals(2202.6, ((QuantityType<?>) state).doubleValue(), 0.1);
289 // change colour temperature kelvin to 4000 K
290 Setters.setColorTemperatureAbsolute(item, QuantityType.valueOf("4000 K"), null);
291 state = item.getColorTemperaturePercentState();
292 assertTrue(state instanceof PercentType);
293 assertEquals(32.2, ((PercentType) state).doubleValue(), 0.1);
294 assertEquals(QuantityType.valueOf("4000 K"), item.getColorTemperatureAbsoluteState());
296 assertEquals(UnDefType.NULL, item.getColorState());
297 Alerts alert = item.getAlerts();
298 assertNotNull(alert);
299 for (ActionType actionValue : alert.getActionValues()) {
300 assertEquals(ActionType.BREATHE, actionValue);
304 assertEquals(2, itemFoundCount);
308 void testLightLevel() {
309 String json = load(ResourceType.LIGHT_LEVEL.name().toLowerCase());
310 Resources resources = GSON.fromJson(json, Resources.class);
311 assertNotNull(resources);
312 List<Resource> list = resources.getResources();
314 assertEquals(1, list.size());
315 Resource item = list.get(0);
316 assertEquals(ResourceType.LIGHT_LEVEL, item.getType());
317 Boolean enabled = item.getEnabled();
318 assertNotNull(enabled);
320 LightLevel lightLevel = item.getLightLevel();
321 assertNotNull(lightLevel);
322 assertEquals(12725, lightLevel.getLightLevel());
323 assertTrue(lightLevel.isLightLevelValid());
327 void testRelativeRotary() {
328 String json = load(ResourceType.RELATIVE_ROTARY.name().toLowerCase());
329 Resources resources = GSON.fromJson(json, Resources.class);
330 assertNotNull(resources);
331 List<Resource> list = resources.getResources();
333 assertEquals(1, list.size());
334 Resource item = list.get(0);
335 assertEquals(ResourceType.RELATIVE_ROTARY, item.getType());
336 RelativeRotary relativeRotary = item.getRelativeRotary();
337 assertNotNull(relativeRotary);
338 RotationEvent rotationEvent = relativeRotary.getLastEvent();
339 assertNotNull(rotationEvent);
340 assertEquals(RotationEventType.REPEAT, rotationEvent.getAction());
341 Rotation rotation = rotationEvent.getRotation();
342 assertNotNull(rotation);
343 assertEquals(DirectionType.CLOCK_WISE, rotation.getDirection());
344 assertEquals(400, rotation.getDuration());
345 assertEquals(30, rotation.getSteps());
346 assertEquals(new DecimalType(30), relativeRotary.getStepsState());
347 assertEquals(new StringType(ButtonEventType.REPEAT.name()), relativeRotary.getActionState());
351 void testResourceMerging() {
352 // create resource one
353 Resource one = new Resource(ResourceType.LIGHT).setId("AARDVARK");
355 // preset the minimum dimming level
357 Dimming dimming = new Dimming().setMinimumDimmingLevel(MINIMUM_DIMMING_LEVEL);
358 Field dimming2 = one.getClass().getDeclaredField("dimming");
359 dimming2.setAccessible(true);
360 dimming2.set(one, dimming);
361 } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
364 Setters.setColorXy(one, HSBType.RED, null);
365 Setters.setDimming(one, PercentType.HUNDRED, null);
366 assertTrue(one.getColorState() instanceof HSBType);
367 assertEquals(PercentType.HUNDRED, one.getBrightnessState());
368 assertTrue(HSBType.RED.closeTo((HSBType) one.getColorState(), 0.01));
370 // switching off should change HSB and Brightness
371 one.setOnOff(OnOffType.OFF);
372 assertEquals(0, ((HSBType) one.getColorState()).getBrightness().doubleValue(), 0.01);
373 assertEquals(PercentType.ZERO, one.getBrightnessState());
374 one.setOnOff(OnOffType.ON);
376 // setting brightness to zero should change it to the minimum dimming level
377 Setters.setDimming(one, PercentType.ZERO, null);
378 assertEquals(MINIMUM_DIMMING_LEVEL, ((HSBType) one.getColorState()).getBrightness().doubleValue(), 0.01);
379 assertEquals(MINIMUM_DIMMING_LEVEL, ((PercentType) one.getBrightnessState()).doubleValue(), 0.01);
380 one.setOnOff(OnOffType.ON);
382 // null its Dimming field
384 Field dimming = one.getClass().getDeclaredField("dimming");
385 dimming.setAccessible(true);
386 dimming.set(one, null);
387 } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
391 // confirm that brightness is no longer valid, and therefore that color has also changed
392 assertEquals(UnDefType.NULL, one.getBrightnessState());
393 assertTrue(one.getColorState() instanceof HSBType);
394 assertTrue((new HSBType(DecimalType.ZERO, PercentType.HUNDRED, new PercentType(50)))
395 .closeTo((HSBType) one.getColorState(), 0.01));
397 PercentType testBrightness = new PercentType(42);
399 // create resource two
400 Resource two = new Resource(ResourceType.DEVICE).setId("ALLIGATOR");
402 Setters.setDimming(two, testBrightness, null);
403 assertEquals(UnDefType.NULL, two.getColorState());
404 assertEquals(testBrightness, two.getBrightnessState());
407 Setters.setResource(one, two);
409 // confirm that brightness and color are both once more valid
410 assertEquals("AARDVARK", one.getId());
411 assertEquals(ResourceType.LIGHT, one.getType());
412 assertEquals(testBrightness, one.getBrightnessState());
413 assertTrue(one.getColorState() instanceof HSBType);
414 assertTrue((new HSBType(DecimalType.ZERO, PercentType.HUNDRED, testBrightness))
415 .closeTo((HSBType) one.getColorState(), 0.01));
419 void testRoomGroup() {
420 String json = load(ResourceType.ROOM.name().toLowerCase());
421 Resources resources = GSON.fromJson(json, Resources.class);
422 assertNotNull(resources);
423 List<Resource> list = resources.getResources();
425 assertEquals(6, list.size());
426 Resource item = list.get(0);
427 assertEquals(ResourceType.ROOM, item.getType());
428 List<ResourceReference> children = item.getChildren();
429 assertEquals(2, children.size());
430 ResourceReference child = children.get(0);
431 assertNotNull(child);
432 assertEquals("0d47bd3d-d82b-4a21-893c-299bff18e22a", child.getId());
433 assertEquals(ResourceType.DEVICE, child.getType());
434 List<ResourceReference> services = item.getServiceReferences();
435 assertEquals(1, services.size());
436 ResourceReference service = services.get(0);
437 assertNotNull(service);
438 assertEquals("08947162-67be-4ed5-bfce-f42dade42416", service.getId());
439 assertEquals(ResourceType.GROUPED_LIGHT, service.getType());
444 String json = load(ResourceType.SCENE.name().toLowerCase());
445 Resources resources = GSON.fromJson(json, Resources.class);
446 assertNotNull(resources);
447 List<Resource> list = resources.getResources();
449 assertEquals(123, list.size());
450 Resource item = list.get(0);
451 List<ActionEntry> actions = item.getActions();
452 assertNotNull(actions);
453 assertEquals(3, actions.size());
454 ActionEntry actionEntry = actions.get(0);
455 assertNotNull(actionEntry);
456 Resource action = actionEntry.getAction();
457 assertNotNull(action);
458 assertEquals(OnOffType.ON, action.getOnOffState());
462 void testSensor2Motion() {
463 String json = load(ResourceType.MOTION.name().toLowerCase());
464 Resources resources = GSON.fromJson(json, Resources.class);
465 assertNotNull(resources);
466 List<Resource> list = resources.getResources();
468 assertEquals(1, list.size());
469 Resource item = list.get(0);
470 assertEquals(ResourceType.MOTION, item.getType());
471 Boolean enabled = item.getEnabled();
472 assertNotNull(enabled);
474 Motion motion = item.getMotion();
475 assertNotNull(motion);
476 assertTrue(motion.isMotion());
477 assertTrue(motion.isMotionValid());
481 void testSetGetPureColors() {
482 Resource resource = new Resource(ResourceType.LIGHT);
483 assertNotNull(resource);
485 HSBType cyan = new HSBType("180,100,100");
486 HSBType yellow = new HSBType("60,100,100");
487 HSBType magenta = new HSBType("300,100,100");
489 for (HSBType color : Set.of(HSBType.WHITE, HSBType.RED, HSBType.GREEN, HSBType.BLUE, cyan, yellow, magenta)) {
490 Setters.setColorXy(resource, color, null);
491 State state = resource.getColorState();
492 assertTrue(state instanceof HSBType);
493 assertTrue(color.closeTo((HSBType) state, 0.01));
498 void testSseLightOrGroupEvent() {
499 String json = load("event");
500 List<Event> eventList = GSON.fromJson(json, Event.EVENT_LIST_TYPE);
501 assertNotNull(eventList);
502 assertEquals(3, eventList.size());
503 Event event = eventList.get(0);
504 List<Resource> resources = event.getData();
505 assertEquals(9, resources.size());
506 for (Resource r : resources) {
507 ResourceType type = r.getType();
508 assertTrue(ResourceType.LIGHT == type || ResourceType.GROUPED_LIGHT == type);
513 void testSseSceneEvent() {
514 String json = load("event");
515 List<Event> eventList = GSON.fromJson(json, Event.EVENT_LIST_TYPE);
516 assertNotNull(eventList);
517 assertEquals(3, eventList.size());
518 Event event = eventList.get(2);
519 List<Resource> resources = event.getData();
520 assertEquals(6, resources.size());
521 Resource resource = resources.get(1);
522 assertEquals(ResourceType.SCENE, resource.getType());
523 JsonObject status = resource.getStatus();
524 assertNotNull(status);
525 JsonElement active = status.get("active");
526 assertNotNull(active);
527 assertTrue(active.isJsonPrimitive());
528 assertEquals("inactive", active.getAsString());
529 Optional<Boolean> isActive = resource.getSceneActive();
530 assertTrue(isActive.isPresent());
531 assertEquals(Boolean.FALSE, isActive.get());
535 void testTemperature() {
536 String json = load(ResourceType.TEMPERATURE.name().toLowerCase());
537 Resources resources = GSON.fromJson(json, Resources.class);
538 assertNotNull(resources);
539 List<Resource> list = resources.getResources();
541 assertEquals(1, list.size());
542 Resource item = list.get(0);
543 assertEquals(ResourceType.TEMPERATURE, item.getType());
544 Temperature temperature = item.getTemperature();
545 assertNotNull(temperature);
546 assertEquals(17.2, temperature.getTemperature(), 0.1);
547 assertTrue(temperature.isTemperatureValid());
551 void testValidJson() {
552 for (ResourceType res : ResourceType.values()) {
553 if (!ResourceType.SSE_TYPES.contains(res)) {
555 String file = res.name().toLowerCase();
556 String json = load(file);
557 JsonElement jsonElement = JsonParser.parseString(json);
558 assertTrue(jsonElement.isJsonObject());
559 } catch (JsonSyntaxException e) {
567 void testZigbeeStatus() {
568 String json = load(ResourceType.ZIGBEE_CONNECTIVITY.name().toLowerCase());
569 Resources resources = GSON.fromJson(json, Resources.class);
570 assertNotNull(resources);
571 List<Resource> list = resources.getResources();
573 assertEquals(35, list.size());
574 Resource item = list.get(0);
575 assertEquals(ResourceType.ZIGBEE_CONNECTIVITY, item.getType());
576 ZigbeeStatus zigbeeStatus = item.getZigbeeStatus();
577 assertNotNull(zigbeeStatus);
578 assertEquals("Connected", zigbeeStatus.toString());
582 void testZoneGroup() {
583 String json = load(ResourceType.ZONE.name().toLowerCase());
584 Resources resources = GSON.fromJson(json, Resources.class);
585 assertNotNull(resources);
586 List<Resource> list = resources.getResources();
588 assertEquals(7, list.size());
589 Resource item = list.get(0);
590 assertEquals(ResourceType.ZONE, item.getType());
591 List<ResourceReference> children = item.getChildren();
592 assertEquals(1, children.size());
593 ResourceReference child = children.get(0);
594 assertNotNull(child);
595 assertEquals("bcad47a0-3f1f-498c-a8aa-3cf389965219", child.getId());
596 assertEquals(ResourceType.LIGHT, child.getType());
597 List<ResourceReference> services = item.getServiceReferences();
598 assertEquals(1, services.size());
599 ResourceReference service = services.get(0);
600 assertNotNull(service);
601 assertEquals("db4fd630-3798-40de-b642-c1ef464bf770", service.getId());
602 assertEquals(ResourceType.GROUPED_LIGHT, service.getType());
606 void testFixedEffectSetter() {
609 Effects resultEffect;
612 source = new Resource(ResourceType.LIGHT);
613 target = new Resource(ResourceType.LIGHT);
614 Setters.setResource(target, source);
615 assertNull(target.getFixedEffects());
617 // valid source fixed effects
618 source = new Resource(ResourceType.LIGHT).setFixedEffects(
619 new Effects().setStatusValues(List.of("NO_EFFECT", "SPARKLE", "CANDLE")).setEffect(EffectType.SPARKLE));
620 target = new Resource(ResourceType.LIGHT);
621 Setters.setResource(target, source);
622 resultEffect = target.getFixedEffects();
623 assertNotNull(resultEffect);
624 assertEquals(EffectType.SPARKLE, resultEffect.getEffect());
625 assertEquals(3, resultEffect.getStatusValues().size());
627 // valid but different source and target fixed effects
628 source = new Resource(ResourceType.LIGHT).setFixedEffects(
629 new Effects().setStatusValues(List.of("NO_EFFECT", "SPARKLE", "CANDLE")).setEffect(EffectType.SPARKLE));
630 target = new Resource(ResourceType.LIGHT).setFixedEffects(
631 new Effects().setStatusValues(List.of("NO_EFFECT", "FIRE")).setEffect(EffectType.FIRE));
632 Setters.setResource(target, source);
633 resultEffect = target.getFixedEffects();
634 assertNotNull(resultEffect);
635 assertNotEquals(EffectType.SPARKLE, resultEffect.getEffect());
636 assertEquals(3, resultEffect.getStatusValues().size());
638 // partly valid source fixed effects
639 source = new Resource(ResourceType.LIGHT).setFixedEffects(new Effects().setStatusValues(List.of("SPARKLE"))
640 .setEffect(EffectType.SPARKLE).setStatusValues(List.of()));
641 target = new Resource(ResourceType.LIGHT);
642 Setters.setResource(target, source);
643 resultEffect = target.getFixedEffects();
644 assertNotNull(resultEffect);
645 assertEquals(EffectType.SPARKLE, resultEffect.getEffect());
646 assertEquals(0, resultEffect.getStatusValues().size());
647 assertFalse(resultEffect.allows(EffectType.SPARKLE));
648 assertFalse(resultEffect.allows(EffectType.NO_EFFECT));
652 void testTimedEffectSetter() {
655 Effects resultEffect;
658 source = new Resource(ResourceType.LIGHT);
659 target = new Resource(ResourceType.LIGHT);
660 Setters.setResource(target, source);
661 assertNull(target.getTimedEffects());
663 // valid source timed effects
664 source = new Resource(ResourceType.LIGHT).setTimedEffects((TimedEffects) new TimedEffects()
665 .setStatusValues(List.of("NO_EFFECT", "SUNRISE")).setEffect(EffectType.NO_EFFECT));
666 target = new Resource(ResourceType.LIGHT);
667 Setters.setResource(target, source);
668 resultEffect = target.getTimedEffects();
669 assertNotNull(resultEffect);
670 assertEquals(EffectType.NO_EFFECT, resultEffect.getEffect());
671 assertEquals(2, resultEffect.getStatusValues().size());
673 // valid but different source and target timed effects
674 source = new Resource(ResourceType.LIGHT)
675 .setTimedEffects((TimedEffects) new TimedEffects().setDuration(Duration.ofMinutes(11))
676 .setStatusValues(List.of("NO_EFFECT", "SPARKLE", "CANDLE")).setEffect(EffectType.SPARKLE));
677 target = new Resource(ResourceType.LIGHT).setTimedEffects((TimedEffects) new TimedEffects()
678 .setStatusValues(List.of("NO_EFFECT", "FIRE")).setEffect(EffectType.FIRE));
679 Setters.setResource(target, source);
680 resultEffect = target.getTimedEffects();
681 assertNotNull(resultEffect);
682 assertNotEquals(EffectType.SPARKLE, resultEffect.getEffect());
683 assertEquals(3, resultEffect.getStatusValues().size());
684 assertTrue(resultEffect instanceof TimedEffects);
685 assertEquals(Duration.ofMinutes(11), ((TimedEffects) resultEffect).getDuration());
687 // partly valid source timed effects
688 source = new Resource(ResourceType.LIGHT).setTimedEffects((TimedEffects) new TimedEffects()
689 .setStatusValues(List.of("SUNRISE")).setEffect(EffectType.SUNRISE).setStatusValues(List.of()));
690 target = new Resource(ResourceType.LIGHT);
691 Setters.setResource(target, source);
692 resultEffect = target.getTimedEffects();
693 assertNotNull(resultEffect);
694 assertEquals(EffectType.SUNRISE, resultEffect.getEffect());
695 assertEquals(0, resultEffect.getStatusValues().size());
696 assertFalse(resultEffect.allows(EffectType.SPARKLE));
697 assertFalse(resultEffect.allows(EffectType.NO_EFFECT));
698 assertTrue(resultEffect instanceof TimedEffects);
699 assertNull(((TimedEffects) resultEffect).getDuration());
701 target.setTimedEffectsDuration(Duration.ofSeconds(22));
702 assertEquals(Duration.ofSeconds(22), ((TimedEffects) resultEffect).getDuration());
704 // source timed effect with duration
705 source = new Resource(ResourceType.LIGHT)
706 .setTimedEffects((TimedEffects) new TimedEffects().setDuration(Duration.ofMillis(44))
707 .setStatusValues(List.of("SUNRISE")).setEffect(EffectType.SUNRISE).setStatusValues(List.of()));
708 target = new Resource(ResourceType.LIGHT);
709 Setters.setResource(target, source);
710 resultEffect = target.getTimedEffects();
711 assertNotNull(resultEffect);
712 assertTrue(resultEffect instanceof TimedEffects);
713 assertEquals(Duration.ofMillis(44), ((TimedEffects) resultEffect).getDuration());