/** * Copyright (c) 2010-2016, openHAB.org and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.openhab.persistence.dynamodb.internal; import static org.junit.Assert.*; import java.io.IOException; import java.math.BigDecimal; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import org.apache.commons.lang.StringUtils; import org.junit.Test; import org.openhab.core.items.Item; import org.openhab.core.library.items.ColorItem; import org.openhab.core.library.items.ContactItem; import org.openhab.core.library.items.DateTimeItem; import org.openhab.core.library.items.DimmerItem; import org.openhab.core.library.items.LocationItem; import org.openhab.core.library.items.NumberItem; import org.openhab.core.library.items.RollershutterItem; import org.openhab.core.library.items.StringItem; import org.openhab.core.library.items.SwitchItem; import org.openhab.core.library.types.DateTimeType; import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.HSBType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.OpenClosedType; import org.openhab.core.library.types.PercentType; import org.openhab.core.library.types.PointType; import org.openhab.core.library.types.StringType; import org.openhab.core.library.types.UpDownType; import org.openhab.core.persistence.HistoricItem; import org.openhab.core.types.State; import org.openhab.core.types.UnDefType; import org.openhab.library.tel.items.CallItem; import org.openhab.library.tel.types.CallType; /** * Test for AbstractDynamoDBItem.fromState and AbstractDynamoDBItem.asHistoricItem for all kind of states * * @author Sami Salonen */ public class AbstractDynamoDBItemSerializationTest { private final Date date = new Date(400); /** * Generic function testing serialization of item state to internal format in DB. In other words, conversion of * Item with state to DynamoDBItem * * @param state item state * @param expectedState internal format in DB representing the item state * @return dynamo db item * @throws IOException */ @SuppressWarnings("unchecked") public DynamoDBItem<?> testStateGeneric(State state, Object expectedState) throws IOException { DynamoDBItem<?> dbItem = AbstractDynamoDBItem.fromState("item1", state, date); assertEquals("item1", dbItem.getName()); assertEquals(date, dbItem.getTime()); if (expectedState instanceof BigDecimal) { assertTrue(DynamoDBBigDecimalItem.loseDigits(((BigDecimal) expectedState)) .compareTo((((DynamoDBItem<BigDecimal>) dbItem).getState())) == 0); } else { assertEquals(expectedState, dbItem.getState()); } return dbItem; } /** * Test state deserialization, that is DynamoDBItem conversion to HistoricItem * * @param dbItem dynamo db item * @param item parameter for DynamoDBItem.asHistoricItem * @param expectedState Expected state of the historic item. DecimalTypes are compared with reduced accuracy * @return * @throws IOException */ public HistoricItem testAsHistoricGeneric(DynamoDBItem<?> dbItem, Item item, Object expectedState) throws IOException { HistoricItem historicItem = dbItem.asHistoricItem(item); assertEquals("item1", historicItem.getName()); assertEquals(date, historicItem.getTimestamp()); assertEquals(expectedState.getClass(), historicItem.getState().getClass()); if (expectedState instanceof DecimalType) { // serialization loses accuracy, take this into consideration assertTrue(DynamoDBBigDecimalItem.loseDigits(((DecimalType) expectedState).toBigDecimal()) .compareTo(((DecimalType) historicItem.getState()).toBigDecimal()) == 0); } else if (expectedState instanceof CallType) { // CallType has buggy equals, let's compare strings instead assertEquals(expectedState.toString(), historicItem.getState().toString()); } else { assertEquals(expectedState, historicItem.getState()); } return historicItem; } @Test public void testUndefWithNumberItem() throws IOException { final DynamoDBItem<?> dbitem = testStateGeneric(UnDefType.UNDEF, "<org.openhab.core.types.UnDefType.UNDEF>"); assertTrue(dbitem instanceof DynamoDBStringItem); testAsHistoricGeneric(dbitem, new NumberItem("foo"), UnDefType.UNDEF); } @Test public void testCallTypeWithCallItem() throws IOException { final DynamoDBItem<?> dbitem = testStateGeneric(new CallType("origNum", "destNum"), "destNum##origNum"); testAsHistoricGeneric(dbitem, new CallItem("foo"), new CallType("origNum", "destNum")); } @Test public void testOpenClosedTypeWithContactItem() throws IOException { final DynamoDBItem<?> dbitemOpen = testStateGeneric(OpenClosedType.CLOSED, BigDecimal.ZERO); testAsHistoricGeneric(dbitemOpen, new ContactItem("foo"), OpenClosedType.CLOSED); final DynamoDBItem<?> dbitemClosed = testStateGeneric(OpenClosedType.OPEN, BigDecimal.ONE); testAsHistoricGeneric(dbitemClosed, new ContactItem("foo"), OpenClosedType.OPEN); } @Test public void testDateTimeTypeWithDateTimeItem() throws IOException { Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); calendar.set(2016, Calendar.MAY, 1, 13, 46, 0); calendar.set(Calendar.MILLISECOND, 50); DynamoDBItem<?> dbitem = testStateGeneric(new DateTimeType(calendar), "2016-05-01T13:46:00.050Z"); testAsHistoricGeneric(dbitem, new DateTimeItem("foo"), new DateTimeType(calendar)); } @Test public void testDateTimeTypeWithStringItem() throws IOException { Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); calendar.set(2016, Calendar.MAY, 1, 13, 46, 0); calendar.set(Calendar.MILLISECOND, 50); DynamoDBItem<?> dbitem = testStateGeneric(new DateTimeType(calendar), "2016-05-01T13:46:00.050Z"); testAsHistoricGeneric(dbitem, new StringItem("foo"), new StringType("2016-05-01T13:46:00.050Z")); } @Test public void testDateTimeTypeLocalWithDateTimeItem() throws IOException { Calendar calendar = Calendar.getInstance(); calendar.setTimeZone(TimeZone.getTimeZone("GMT+03:00")); calendar.setTimeInMillis(1468773487050L); // GMT: Sun, 17 Jul 2016 16:38:07.050 GMT DynamoDBItem<?> dbitem = testStateGeneric(new DateTimeType(calendar), "2016-07-17T16:38:07.050Z"); // when deserializing data, we get the date in UTC Calendar Calendar expectedCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); expectedCal.setTimeInMillis(1468773487050L); testAsHistoricGeneric(dbitem, new DateTimeItem("foo"), new DateTimeType(expectedCal)); } @Test public void testDateTimeTypeLocalWithStringItem() throws IOException { Calendar calendar = Calendar.getInstance(); calendar.setTimeZone(TimeZone.getTimeZone("GMT+03:00")); calendar.setTimeInMillis(1468773487050L); // GMT: Sun, 17 Jul 2016 16:38:07.050 GMT DynamoDBItem<?> dbitem = testStateGeneric(new DateTimeType(calendar), "2016-07-17T16:38:07.050Z"); testAsHistoricGeneric(dbitem, new StringItem("foo"), new StringType("2016-07-17T16:38:07.050Z")); } @Test public void testPointTypeWithLocationItem() throws IOException { final PointType point = new PointType(new DecimalType(60.3), new DecimalType(30.2), new DecimalType(510.90)); String expected = StringUtils.join( new String[] { point.getLatitude().toBigDecimal().toString(), point.getLongitude().toBigDecimal().toString(), point.getAltitude().toBigDecimal().toString() }, ","); DynamoDBItem<?> dbitem = testStateGeneric(point, expected); testAsHistoricGeneric(dbitem, new LocationItem("foo"), point); } @Test public void testDecimalTypeWithNumberItem() throws IOException { DynamoDBItem<?> dbitem = testStateGeneric(new DecimalType(3.2), new BigDecimal(3.2)); testAsHistoricGeneric(dbitem, new NumberItem("foo"), new DecimalType(3.2)); } @Test public void testPercentTypeWithColorItem() throws IOException { DynamoDBItem<?> dbitem = testStateGeneric(new PercentType(new BigDecimal(3.2)), new BigDecimal(3.2)); testAsHistoricGeneric(dbitem, new ColorItem("foo"), new PercentType(new BigDecimal(3.2))); } @Test public void testPercentTypeWithDimmerItem() throws IOException { DynamoDBItem<?> dbitem = testStateGeneric(new PercentType(new BigDecimal(3.2)), new BigDecimal(3.2)); testAsHistoricGeneric(dbitem, new DimmerItem("foo"), new PercentType(new BigDecimal(3.2))); } @Test public void testPercentTypeWithRollerShutterItem() throws IOException { DynamoDBItem<?> dbitem = testStateGeneric(new PercentType(new BigDecimal(3.2)), new BigDecimal(3.2)); testAsHistoricGeneric(dbitem, new RollershutterItem("foo"), new PercentType(new BigDecimal(3.2))); } @Test public void testPercentTypeWithNumberItem() throws IOException { DynamoDBItem<?> dbitem = testStateGeneric(new PercentType(new BigDecimal(3.2)), new BigDecimal(3.2)); // note: comes back as DecimalType instead of the original PercentType testAsHistoricGeneric(dbitem, new NumberItem("foo"), new DecimalType(new BigDecimal(3.2))); } @Test public void testUpDownTypeWithRollershutterItem() throws IOException { // note: comes back as PercentType instead of the original UpDownType DynamoDBItem<?> dbItemDown = testStateGeneric(UpDownType.DOWN, BigDecimal.ZERO); testAsHistoricGeneric(dbItemDown, new RollershutterItem("foo"), new PercentType(BigDecimal.ZERO)); DynamoDBItem<?> dbItemUp = testStateGeneric(UpDownType.UP, BigDecimal.ONE); testAsHistoricGeneric(dbItemUp, new RollershutterItem("foo"), new PercentType(BigDecimal.ONE)); } @Test public void testStringTypeWithStringItem() throws IOException { DynamoDBItem<?> dbitem = testStateGeneric(new StringType("foo bar"), "foo bar"); testAsHistoricGeneric(dbitem, new StringItem("foo"), new StringType("foo bar")); } @Test public void testOnOffTypeWithColorItem() throws IOException { DynamoDBItem<?> dbitemOff = testStateGeneric(OnOffType.OFF, BigDecimal.ZERO); testAsHistoricGeneric(dbitemOff, new ColorItem("foo"), new PercentType(BigDecimal.ZERO)); DynamoDBItem<?> dbitemOn = testStateGeneric(OnOffType.ON, BigDecimal.ONE); testAsHistoricGeneric(dbitemOn, new ColorItem("foo"), new PercentType(BigDecimal.ONE)); } @Test public void testOnOffTypeWithDimmerItem() throws IOException { DynamoDBItem<?> dbitemOff = testStateGeneric(OnOffType.OFF, BigDecimal.ZERO); testAsHistoricGeneric(dbitemOff, new DimmerItem("foo"), new PercentType(BigDecimal.ZERO)); DynamoDBItem<?> dbitemOn = testStateGeneric(OnOffType.ON, BigDecimal.ONE); testAsHistoricGeneric(dbitemOn, new DimmerItem("foo"), new PercentType(BigDecimal.ONE)); } @Test public void testOnOffTypeWithSwitchItem() throws IOException { DynamoDBItem<?> dbitemOff = testStateGeneric(OnOffType.OFF, BigDecimal.ZERO); testAsHistoricGeneric(dbitemOff, new SwitchItem("foo"), OnOffType.OFF); DynamoDBItem<?> dbitemOn = testStateGeneric(OnOffType.ON, BigDecimal.ONE); testAsHistoricGeneric(dbitemOn, new SwitchItem("foo"), OnOffType.ON); } @Test public void testHSBTypeWithColorItem() throws IOException { HSBType hsb = new HSBType(new DecimalType(1.5), new PercentType(new BigDecimal(2.5)), new PercentType(new BigDecimal(3.5))); DynamoDBItem<?> dbitem = testStateGeneric(hsb, "1.5,2.5,3.5"); testAsHistoricGeneric(dbitem, new ColorItem("foo"), hsb); } }