2 * Copyright (c) 2010-2020 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.persistence.dynamodb.internal;
15 import static org.junit.jupiter.api.Assertions.*;
17 import java.io.IOException;
18 import java.math.BigDecimal;
19 import java.time.Instant;
20 import java.time.ZoneId;
21 import java.time.ZonedDateTime;
22 import java.util.Objects;
23 import java.util.TimeZone;
25 import org.eclipse.jdt.annotation.NonNullByDefault;
26 import org.junit.jupiter.api.Test;
27 import org.openhab.core.items.Item;
28 import org.openhab.core.library.items.CallItem;
29 import org.openhab.core.library.items.ColorItem;
30 import org.openhab.core.library.items.ContactItem;
31 import org.openhab.core.library.items.DateTimeItem;
32 import org.openhab.core.library.items.DimmerItem;
33 import org.openhab.core.library.items.LocationItem;
34 import org.openhab.core.library.items.NumberItem;
35 import org.openhab.core.library.items.RollershutterItem;
36 import org.openhab.core.library.items.StringItem;
37 import org.openhab.core.library.items.SwitchItem;
38 import org.openhab.core.library.types.DateTimeType;
39 import org.openhab.core.library.types.DecimalType;
40 import org.openhab.core.library.types.HSBType;
41 import org.openhab.core.library.types.OnOffType;
42 import org.openhab.core.library.types.OpenClosedType;
43 import org.openhab.core.library.types.PercentType;
44 import org.openhab.core.library.types.PointType;
45 import org.openhab.core.library.types.StringListType;
46 import org.openhab.core.library.types.StringType;
47 import org.openhab.core.library.types.UpDownType;
48 import org.openhab.core.persistence.HistoricItem;
49 import org.openhab.core.types.State;
50 import org.openhab.core.types.UnDefType;
53 * Test for AbstractDynamoDBItem.fromState and AbstractDynamoDBItem.asHistoricItem for all kind of states
55 * @author Sami Salonen - Initial contribution
58 public class AbstractDynamoDBItemSerializationTest {
60 private final ZonedDateTime date = ZonedDateTime.ofInstant(Instant.ofEpochSecond(400), ZoneId.systemDefault());
63 * Generic function testing serialization of item state to internal format in DB. In other words, conversion of
64 * Item with state to DynamoDBItem
66 * @param state item state
67 * @param expectedState internal format in DB representing the item state
68 * @return dynamo db item
71 public DynamoDBItem<?> testStateGeneric(State state, Object expectedState) throws IOException {
72 DynamoDBItem<?> dbItem = AbstractDynamoDBItem.fromState("item1", state, date);
74 assertEquals("item1", dbItem.getName());
75 assertEquals(date, dbItem.getTime());
76 Object actualState = dbItem.getState();
77 assertNotNull(actualState);
78 Objects.requireNonNull(actualState);
79 if (expectedState instanceof BigDecimal) {
80 BigDecimal expectedRounded = DynamoDBBigDecimalItem.loseDigits(((BigDecimal) expectedState));
81 assertEquals(0, expectedRounded.compareTo((BigDecimal) actualState),
82 String.format("Expected state %s (%s but with some digits lost) did not match actual state %s",
83 expectedRounded, expectedState, actualState));
85 assertEquals(expectedState, actualState);
91 * Test state deserialization, that is DynamoDBItem conversion to HistoricItem
93 * @param dbItem dynamo db item
94 * @param item parameter for DynamoDBItem.asHistoricItem
95 * @param expectedState Expected state of the historic item. DecimalTypes are compared with reduced accuracy
99 public HistoricItem testAsHistoricGeneric(DynamoDBItem<?> dbItem, Item item, Object expectedState)
101 HistoricItem historicItem = dbItem.asHistoricItem(item);
103 assertEquals("item1", historicItem.getName());
104 assertEquals(date, historicItem.getTimestamp());
105 assertEquals(expectedState.getClass(), historicItem.getState().getClass());
106 if (expectedState instanceof DecimalType) {
107 // serialization loses accuracy, take this into consideration
108 BigDecimal expectedRounded = DynamoDBBigDecimalItem
109 .loseDigits(((DecimalType) expectedState).toBigDecimal());
110 BigDecimal actual = ((DecimalType) historicItem.getState()).toBigDecimal();
111 assertEquals(0, expectedRounded.compareTo(actual),
112 String.format("Expected state %s (%s but with some digits lost) did not match actual state %s",
113 expectedRounded, expectedState, actual));
115 assertEquals(expectedState, historicItem.getState());
121 public void testUndefWithNumberItem() throws IOException {
122 final DynamoDBItem<?> dbitem = testStateGeneric(UnDefType.UNDEF, "<org.openhab.core.types.UnDefType.UNDEF>");
123 assertTrue(dbitem instanceof DynamoDBStringItem);
124 testAsHistoricGeneric(dbitem, new NumberItem("foo"), UnDefType.UNDEF);
128 public void testCallTypeWithCallItem() throws IOException {
129 final DynamoDBItem<?> dbitem = testStateGeneric(new StringListType("origNum", "destNum"), "origNum,destNum");
130 testAsHistoricGeneric(dbitem, new CallItem("foo"), new StringListType("origNum", "destNum"));
134 public void testOpenClosedTypeWithContactItem() throws IOException {
135 final DynamoDBItem<?> dbitemOpen = testStateGeneric(OpenClosedType.CLOSED, BigDecimal.ZERO);
136 testAsHistoricGeneric(dbitemOpen, new ContactItem("foo"), OpenClosedType.CLOSED);
138 final DynamoDBItem<?> dbitemClosed = testStateGeneric(OpenClosedType.OPEN, BigDecimal.ONE);
139 testAsHistoricGeneric(dbitemClosed, new ContactItem("foo"), OpenClosedType.OPEN);
143 public void testDateTimeTypeWithDateTimeItem() throws IOException {
144 ZonedDateTime zdt = ZonedDateTime.parse("2016-05-01T13:46:00.050Z");
145 DynamoDBItem<?> dbitem = testStateGeneric(new DateTimeType(zdt.toString()), "2016-05-01T13:46:00.050Z");
146 testAsHistoricGeneric(dbitem, new DateTimeItem("foo"),
147 new DateTimeType(zdt.withZoneSameInstant(ZoneId.systemDefault())));
151 public void testDateTimeTypeWithStringItem() throws IOException {
152 DynamoDBItem<?> dbitem = testStateGeneric(new DateTimeType(ZonedDateTime.parse("2016-05-01T13:46:00.050Z")),
153 "2016-05-01T13:46:00.050Z");
154 testAsHistoricGeneric(dbitem, new StringItem("foo"), new StringType("2016-05-01T13:46:00.050Z"));
158 public void testDateTimeTypeLocalWithDateTimeItem() throws IOException {
159 DynamoDBItem<?> dbitem = testStateGeneric(new DateTimeType("2016-07-17T19:38:07.050+0300"),
160 "2016-07-17T16:38:07.050Z");
162 ZonedDateTime expectedZdt = Instant.ofEpochMilli(1468773487050L).atZone(ZoneId.systemDefault());
163 testAsHistoricGeneric(dbitem, new DateTimeItem("foo"), new DateTimeType(expectedZdt));
167 public void testDateTimeTypeLocalWithStringItem() throws IOException {
168 Instant instant = Instant.ofEpochMilli(1468773487050L); // GMT: Sun, 17 Jul 2016 16:38:07.050 GMT
169 ZonedDateTime zdt = instant.atZone(TimeZone.getTimeZone("GMT+03:00").toZoneId());
170 DynamoDBItem<?> dbitem = testStateGeneric(new DateTimeType(zdt), "2016-07-17T16:38:07.050Z");
171 testAsHistoricGeneric(dbitem, new StringItem("foo"), new StringType("2016-07-17T16:38:07.050Z"));
175 public void testPointTypeWithLocationItem() throws IOException {
176 final PointType point = new PointType(new DecimalType(60.3), new DecimalType(30.2), new DecimalType(510.90));
177 String expected = point.getLatitude().toBigDecimal().toString() + ","
178 + point.getLongitude().toBigDecimal().toString() + "," + point.getAltitude().toBigDecimal().toString();
179 DynamoDBItem<?> dbitem = testStateGeneric(point, expected);
180 testAsHistoricGeneric(dbitem, new LocationItem("foo"), point);
184 public void testDecimalTypeWithNumberItem() throws IOException {
185 DynamoDBItem<?> dbitem = testStateGeneric(new DecimalType("3.2"), new BigDecimal("3.2"));
186 testAsHistoricGeneric(dbitem, new NumberItem("foo"), new DecimalType("3.2"));
190 public void testPercentTypeWithColorItem() throws IOException {
191 DynamoDBItem<?> dbitem = testStateGeneric(new PercentType(new BigDecimal("3.2")), new BigDecimal("3.2"));
192 testAsHistoricGeneric(dbitem, new ColorItem("foo"), new PercentType(new BigDecimal("3.2")));
196 public void testPercentTypeWithDimmerItem() throws IOException {
197 DynamoDBItem<?> dbitem = testStateGeneric(new PercentType(new BigDecimal("3.2")), new BigDecimal("3.2"));
198 testAsHistoricGeneric(dbitem, new DimmerItem("foo"), new PercentType(new BigDecimal("3.2")));
202 public void testPercentTypeWithRollerShutterItem() throws IOException {
203 DynamoDBItem<?> dbitem = testStateGeneric(new PercentType(new BigDecimal("3.2")), new BigDecimal("3.2"));
204 testAsHistoricGeneric(dbitem, new RollershutterItem("foo"), new PercentType(new BigDecimal("3.2")));
208 public void testPercentTypeWithNumberItem() throws IOException {
209 DynamoDBItem<?> dbitem = testStateGeneric(new PercentType(new BigDecimal("3.2")), new BigDecimal("3.2"));
210 // note: comes back as DecimalType instead of the original PercentType
211 testAsHistoricGeneric(dbitem, new NumberItem("foo"), new DecimalType(new BigDecimal("3.2")));
215 public void testUpDownTypeWithRollershutterItem() throws IOException {
216 // note: comes back as PercentType instead of the original UpDownType
217 DynamoDBItem<?> dbItemDown = testStateGeneric(UpDownType.DOWN, BigDecimal.ZERO);
218 testAsHistoricGeneric(dbItemDown, new RollershutterItem("foo"), new PercentType(BigDecimal.ZERO));
220 DynamoDBItem<?> dbItemUp = testStateGeneric(UpDownType.UP, BigDecimal.ONE);
221 testAsHistoricGeneric(dbItemUp, new RollershutterItem("foo"), new PercentType(BigDecimal.ONE));
225 public void testStringTypeWithStringItem() throws IOException {
226 DynamoDBItem<?> dbitem = testStateGeneric(new StringType("foo bar"), "foo bar");
227 testAsHistoricGeneric(dbitem, new StringItem("foo"), new StringType("foo bar"));
231 public void testOnOffTypeWithColorItem() throws IOException {
232 DynamoDBItem<?> dbitemOff = testStateGeneric(OnOffType.OFF, BigDecimal.ZERO);
233 testAsHistoricGeneric(dbitemOff, new ColorItem("foo"), new PercentType(BigDecimal.ZERO));
235 DynamoDBItem<?> dbitemOn = testStateGeneric(OnOffType.ON, BigDecimal.ONE);
236 testAsHistoricGeneric(dbitemOn, new ColorItem("foo"), new PercentType(BigDecimal.ONE));
240 public void testOnOffTypeWithDimmerItem() throws IOException {
241 DynamoDBItem<?> dbitemOff = testStateGeneric(OnOffType.OFF, BigDecimal.ZERO);
242 testAsHistoricGeneric(dbitemOff, new DimmerItem("foo"), new PercentType(BigDecimal.ZERO));
244 DynamoDBItem<?> dbitemOn = testStateGeneric(OnOffType.ON, BigDecimal.ONE);
245 testAsHistoricGeneric(dbitemOn, new DimmerItem("foo"), new PercentType(BigDecimal.ONE));
249 public void testOnOffTypeWithSwitchItem() throws IOException {
250 DynamoDBItem<?> dbitemOff = testStateGeneric(OnOffType.OFF, BigDecimal.ZERO);
251 testAsHistoricGeneric(dbitemOff, new SwitchItem("foo"), OnOffType.OFF);
253 DynamoDBItem<?> dbitemOn = testStateGeneric(OnOffType.ON, BigDecimal.ONE);
254 testAsHistoricGeneric(dbitemOn, new SwitchItem("foo"), OnOffType.ON);
258 public void testHSBTypeWithColorItem() throws IOException {
259 HSBType hsb = new HSBType(new DecimalType(1.5), new PercentType(new BigDecimal(2.5)),
260 new PercentType(new BigDecimal(3.5)));
261 DynamoDBItem<?> dbitem = testStateGeneric(hsb, "1.5,2.5,3.5");
262 testAsHistoricGeneric(dbitem, new ColorItem("foo"), hsb);