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.TimeZone;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.junit.jupiter.api.Test;
26 import org.openhab.core.items.Item;
27 import org.openhab.core.library.items.CallItem;
28 import org.openhab.core.library.items.ColorItem;
29 import org.openhab.core.library.items.ContactItem;
30 import org.openhab.core.library.items.DateTimeItem;
31 import org.openhab.core.library.items.DimmerItem;
32 import org.openhab.core.library.items.LocationItem;
33 import org.openhab.core.library.items.NumberItem;
34 import org.openhab.core.library.items.RollershutterItem;
35 import org.openhab.core.library.items.StringItem;
36 import org.openhab.core.library.items.SwitchItem;
37 import org.openhab.core.library.types.DateTimeType;
38 import org.openhab.core.library.types.DecimalType;
39 import org.openhab.core.library.types.HSBType;
40 import org.openhab.core.library.types.OnOffType;
41 import org.openhab.core.library.types.OpenClosedType;
42 import org.openhab.core.library.types.PercentType;
43 import org.openhab.core.library.types.PointType;
44 import org.openhab.core.library.types.StringListType;
45 import org.openhab.core.library.types.StringType;
46 import org.openhab.core.library.types.UpDownType;
47 import org.openhab.core.persistence.HistoricItem;
48 import org.openhab.core.types.State;
49 import org.openhab.core.types.UnDefType;
52 * Test for AbstractDynamoDBItem.fromState and AbstractDynamoDBItem.asHistoricItem for all kind of states
54 * @author Sami Salonen - Initial contribution
57 public class AbstractDynamoDBItemSerializationTest {
59 private final ZonedDateTime date = ZonedDateTime.ofInstant(Instant.ofEpochSecond(400), ZoneId.systemDefault());
62 * Generic function testing serialization of item state to internal format in DB. In other words, conversion of
63 * Item with state to DynamoDBItem
65 * @param state item state
66 * @param expectedState internal format in DB representing the item state
67 * @return dynamo db item
70 public DynamoDBItem<?> testStateGeneric(State state, Object expectedState) throws IOException {
71 DynamoDBItem<?> dbItem = AbstractDynamoDBItem.fromState("item1", state, date);
73 assertEquals("item1", dbItem.getName());
74 assertEquals(date, dbItem.getTime());
75 Object actualState = dbItem.getState();
76 if (expectedState instanceof BigDecimal) {
77 BigDecimal expectedRounded = DynamoDBBigDecimalItem.loseDigits(((BigDecimal) expectedState));
78 assertEquals(0, expectedRounded.compareTo((BigDecimal) actualState),
79 String.format("Expected state %s (%s but with some digits lost) did not match actual state %s",
80 expectedRounded, expectedState, actualState));
82 assertEquals(expectedState, actualState);
88 * Test state deserialization, that is DynamoDBItem conversion to HistoricItem
90 * @param dbItem dynamo db item
91 * @param item parameter for DynamoDBItem.asHistoricItem
92 * @param expectedState Expected state of the historic item. DecimalTypes are compared with reduced accuracy
96 public HistoricItem testAsHistoricGeneric(DynamoDBItem<?> dbItem, Item item, Object expectedState)
98 HistoricItem historicItem = dbItem.asHistoricItem(item);
100 assertEquals("item1", historicItem.getName());
101 assertEquals(date, historicItem.getTimestamp());
102 assertEquals(expectedState.getClass(), historicItem.getState().getClass());
103 if (expectedState instanceof DecimalType) {
104 // serialization loses accuracy, take this into consideration
105 BigDecimal expectedRounded = DynamoDBBigDecimalItem
106 .loseDigits(((DecimalType) expectedState).toBigDecimal());
107 BigDecimal actual = ((DecimalType) historicItem.getState()).toBigDecimal();
108 assertEquals(0, expectedRounded.compareTo(actual),
109 String.format("Expected state %s (%s but with some digits lost) did not match actual state %s",
110 expectedRounded, expectedState, actual));
112 assertEquals(expectedState, historicItem.getState());
118 public void testUndefWithNumberItem() throws IOException {
119 final DynamoDBItem<?> dbitem = testStateGeneric(UnDefType.UNDEF, "<org.openhab.core.types.UnDefType.UNDEF>");
120 assertTrue(dbitem instanceof DynamoDBStringItem);
121 testAsHistoricGeneric(dbitem, new NumberItem("foo"), UnDefType.UNDEF);
125 public void testCallTypeWithCallItem() throws IOException {
126 final DynamoDBItem<?> dbitem = testStateGeneric(new StringListType("origNum", "destNum"), "origNum,destNum");
127 testAsHistoricGeneric(dbitem, new CallItem("foo"), new StringListType("origNum", "destNum"));
131 public void testOpenClosedTypeWithContactItem() throws IOException {
132 final DynamoDBItem<?> dbitemOpen = testStateGeneric(OpenClosedType.CLOSED, BigDecimal.ZERO);
133 testAsHistoricGeneric(dbitemOpen, new ContactItem("foo"), OpenClosedType.CLOSED);
135 final DynamoDBItem<?> dbitemClosed = testStateGeneric(OpenClosedType.OPEN, BigDecimal.ONE);
136 testAsHistoricGeneric(dbitemClosed, new ContactItem("foo"), OpenClosedType.OPEN);
140 public void testDateTimeTypeWithDateTimeItem() throws IOException {
141 ZonedDateTime zdt = ZonedDateTime.parse("2016-05-01T13:46:00.050Z");
142 DynamoDBItem<?> dbitem = testStateGeneric(new DateTimeType(zdt.toString()), "2016-05-01T13:46:00.050Z");
143 testAsHistoricGeneric(dbitem, new DateTimeItem("foo"),
144 new DateTimeType(zdt.withZoneSameInstant(ZoneId.systemDefault())));
148 public void testDateTimeTypeWithStringItem() throws IOException {
149 DynamoDBItem<?> dbitem = testStateGeneric(new DateTimeType(ZonedDateTime.parse("2016-05-01T13:46:00.050Z")),
150 "2016-05-01T13:46:00.050Z");
151 testAsHistoricGeneric(dbitem, new StringItem("foo"), new StringType("2016-05-01T13:46:00.050Z"));
155 public void testDateTimeTypeLocalWithDateTimeItem() throws IOException {
156 DynamoDBItem<?> dbitem = testStateGeneric(new DateTimeType("2016-07-17T19:38:07.050+0300"),
157 "2016-07-17T16:38:07.050Z");
159 ZonedDateTime expectedZdt = Instant.ofEpochMilli(1468773487050L).atZone(ZoneId.systemDefault());
160 testAsHistoricGeneric(dbitem, new DateTimeItem("foo"), new DateTimeType(expectedZdt));
164 public void testDateTimeTypeLocalWithStringItem() throws IOException {
165 Instant instant = Instant.ofEpochMilli(1468773487050L); // GMT: Sun, 17 Jul 2016 16:38:07.050 GMT
166 ZonedDateTime zdt = instant.atZone(TimeZone.getTimeZone("GMT+03:00").toZoneId());
167 DynamoDBItem<?> dbitem = testStateGeneric(new DateTimeType(zdt), "2016-07-17T16:38:07.050Z");
168 testAsHistoricGeneric(dbitem, new StringItem("foo"), new StringType("2016-07-17T16:38:07.050Z"));
172 public void testPointTypeWithLocationItem() throws IOException {
173 final PointType point = new PointType(new DecimalType(60.3), new DecimalType(30.2), new DecimalType(510.90));
174 String expected = point.getLatitude().toBigDecimal().toString() + ","
175 + point.getLongitude().toBigDecimal().toString() + "," + point.getAltitude().toBigDecimal().toString();
176 DynamoDBItem<?> dbitem = testStateGeneric(point, expected);
177 testAsHistoricGeneric(dbitem, new LocationItem("foo"), point);
181 public void testDecimalTypeWithNumberItem() throws IOException {
182 DynamoDBItem<?> dbitem = testStateGeneric(new DecimalType("3.2"), new BigDecimal("3.2"));
183 testAsHistoricGeneric(dbitem, new NumberItem("foo"), new DecimalType("3.2"));
187 public void testPercentTypeWithColorItem() throws IOException {
188 DynamoDBItem<?> dbitem = testStateGeneric(new PercentType(new BigDecimal("3.2")), new BigDecimal("3.2"));
189 testAsHistoricGeneric(dbitem, new ColorItem("foo"), new PercentType(new BigDecimal("3.2")));
193 public void testPercentTypeWithDimmerItem() throws IOException {
194 DynamoDBItem<?> dbitem = testStateGeneric(new PercentType(new BigDecimal("3.2")), new BigDecimal("3.2"));
195 testAsHistoricGeneric(dbitem, new DimmerItem("foo"), new PercentType(new BigDecimal("3.2")));
199 public void testPercentTypeWithRollerShutterItem() throws IOException {
200 DynamoDBItem<?> dbitem = testStateGeneric(new PercentType(new BigDecimal("3.2")), new BigDecimal("3.2"));
201 testAsHistoricGeneric(dbitem, new RollershutterItem("foo"), new PercentType(new BigDecimal("3.2")));
205 public void testPercentTypeWithNumberItem() throws IOException {
206 DynamoDBItem<?> dbitem = testStateGeneric(new PercentType(new BigDecimal("3.2")), new BigDecimal("3.2"));
207 // note: comes back as DecimalType instead of the original PercentType
208 testAsHistoricGeneric(dbitem, new NumberItem("foo"), new DecimalType(new BigDecimal("3.2")));
212 public void testUpDownTypeWithRollershutterItem() throws IOException {
213 // note: comes back as PercentType instead of the original UpDownType
214 DynamoDBItem<?> dbItemDown = testStateGeneric(UpDownType.DOWN, BigDecimal.ZERO);
215 testAsHistoricGeneric(dbItemDown, new RollershutterItem("foo"), new PercentType(BigDecimal.ZERO));
217 DynamoDBItem<?> dbItemUp = testStateGeneric(UpDownType.UP, BigDecimal.ONE);
218 testAsHistoricGeneric(dbItemUp, new RollershutterItem("foo"), new PercentType(BigDecimal.ONE));
222 public void testStringTypeWithStringItem() throws IOException {
223 DynamoDBItem<?> dbitem = testStateGeneric(new StringType("foo bar"), "foo bar");
224 testAsHistoricGeneric(dbitem, new StringItem("foo"), new StringType("foo bar"));
228 public void testOnOffTypeWithColorItem() throws IOException {
229 DynamoDBItem<?> dbitemOff = testStateGeneric(OnOffType.OFF, BigDecimal.ZERO);
230 testAsHistoricGeneric(dbitemOff, new ColorItem("foo"), new PercentType(BigDecimal.ZERO));
232 DynamoDBItem<?> dbitemOn = testStateGeneric(OnOffType.ON, BigDecimal.ONE);
233 testAsHistoricGeneric(dbitemOn, new ColorItem("foo"), new PercentType(BigDecimal.ONE));
237 public void testOnOffTypeWithDimmerItem() throws IOException {
238 DynamoDBItem<?> dbitemOff = testStateGeneric(OnOffType.OFF, BigDecimal.ZERO);
239 testAsHistoricGeneric(dbitemOff, new DimmerItem("foo"), new PercentType(BigDecimal.ZERO));
241 DynamoDBItem<?> dbitemOn = testStateGeneric(OnOffType.ON, BigDecimal.ONE);
242 testAsHistoricGeneric(dbitemOn, new DimmerItem("foo"), new PercentType(BigDecimal.ONE));
246 public void testOnOffTypeWithSwitchItem() throws IOException {
247 DynamoDBItem<?> dbitemOff = testStateGeneric(OnOffType.OFF, BigDecimal.ZERO);
248 testAsHistoricGeneric(dbitemOff, new SwitchItem("foo"), OnOffType.OFF);
250 DynamoDBItem<?> dbitemOn = testStateGeneric(OnOffType.ON, BigDecimal.ONE);
251 testAsHistoricGeneric(dbitemOn, new SwitchItem("foo"), OnOffType.ON);
255 public void testHSBTypeWithColorItem() throws IOException {
256 HSBType hsb = new HSBType(new DecimalType(1.5), new PercentType(new BigDecimal(2.5)),
257 new PercentType(new BigDecimal(3.5)));
258 DynamoDBItem<?> dbitem = testStateGeneric(hsb, "1.5,2.5,3.5");
259 testAsHistoricGeneric(dbitem, new ColorItem("foo"), hsb);