/** * 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.util.Date; import java.util.Iterator; import org.junit.Assume; import org.junit.BeforeClass; import org.junit.Test; import org.openhab.core.persistence.FilterCriteria; import org.openhab.core.persistence.FilterCriteria.Operator; import org.openhab.core.persistence.FilterCriteria.Ordering; import org.openhab.core.persistence.HistoricItem; import org.openhab.core.types.State; /** * This is abstract class helping with integration testing the persistence service. Different kind of queries are tested * against actual dynamo db database. * * * Inheritor of this base class needs to store two states of one item in a static method annotated with @BeforeClass. * This * static * class should update the private static fields * beforeStore (date before storing anything), afterStore1 (after storing first item, but before storing second item), * afterStore2 (after storing second item). The item name must correspond to getItemName. The first state needs to be * smaller than the second state. * * To have more comprehensive tests, the inheritor class can define getQueryItemStateBetween to provide a value between * the two states. Null can be used to omit the additional tests. * * * See DimmerItemIntegrationTest for example how to use this base class. * * @author Sami Salonen * */ public abstract class AbstractTwoItemIntegrationTest extends BaseIntegrationTest { protected static Date beforeStore; protected static Date afterStore1; protected static Date afterStore2; protected abstract String getItemName(); /** * State of the time item stored first, should be smaller than the second value * * @return */ protected abstract State getFirstItemState(); /** * State of the time item stored second, should be larger than the first value * * @return */ protected abstract State getSecondItemState(); /** * State that is between the first and second. Use null to omit extended tests using this value. * * @return */ protected abstract State getQueryItemStateBetween(); protected void assertStateEquals(State expected, State actual) { assertEquals(expected, actual); } @BeforeClass public static void checkService() throws InterruptedException { String msg = "DynamoDB integration tests will be skipped. Did you specify AWS credentials for testing? " + "See BaseIntegrationTest for more details"; if (service == null) { System.out.println(msg); } Assume.assumeTrue(msg, service != null); } /** * Asserts that iterable contains correct items and nothing else * */ private void assertIterableContainsItems(Iterable<HistoricItem> iterable, boolean ascending) { Iterator<HistoricItem> iterator = iterable.iterator(); HistoricItem actual1 = iterator.next(); HistoricItem actual2 = iterator.next(); assertFalse(iterator.hasNext()); for (HistoricItem actual : new HistoricItem[] { actual1, actual2 }) { assertEquals(getItemName(), actual.getName()); } HistoricItem storedFirst; HistoricItem storedSecond; if (ascending) { storedFirst = actual1; storedSecond = actual2; } else { storedFirst = actual2; storedSecond = actual1; } assertStateEquals(getFirstItemState(), storedFirst.getState()); assertTrue(storedFirst.getTimestamp().before(afterStore1)); assertTrue(storedFirst.getTimestamp().after(beforeStore)); assertStateEquals(getSecondItemState(), storedSecond.getState()); assertTrue(storedSecond.getTimestamp().before(afterStore2)); assertTrue(storedSecond.getTimestamp().after(afterStore1)); } @Test public void testQueryUsingName() { FilterCriteria criteria = new FilterCriteria(); criteria.setOrdering(Ordering.ASCENDING); criteria.setItemName(getItemName()); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); assertIterableContainsItems(iterable, true); } @Test public void testQueryUsingNameAndStart() { FilterCriteria criteria = new FilterCriteria(); criteria.setOrdering(Ordering.ASCENDING); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); assertIterableContainsItems(iterable, true); } @Test public void testQueryUsingNameAndStartNoMatch() { FilterCriteria criteria = new FilterCriteria(); criteria.setItemName(getItemName()); criteria.setBeginDate(afterStore2); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); assertFalse(iterable.iterator().hasNext()); } @Test public void testQueryUsingNameAndEnd() { FilterCriteria criteria = new FilterCriteria(); criteria.setOrdering(Ordering.ASCENDING); criteria.setItemName(getItemName()); criteria.setEndDate(afterStore2); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); assertIterableContainsItems(iterable, true); } @Test public void testQueryUsingNameAndEndNoMatch() { FilterCriteria criteria = new FilterCriteria(); criteria.setItemName(getItemName()); criteria.setEndDate(beforeStore); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); assertFalse(iterable.iterator().hasNext()); } @Test public void testQueryUsingNameAndStartAndEnd() { FilterCriteria criteria = new FilterCriteria(); criteria.setOrdering(Ordering.ASCENDING); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); criteria.setEndDate(afterStore2); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); assertIterableContainsItems(iterable, true); } @Test public void testQueryUsingNameAndStartAndEndDesc() { FilterCriteria criteria = new FilterCriteria(); criteria.setOrdering(Ordering.DESCENDING); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); criteria.setEndDate(afterStore2); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); assertIterableContainsItems(iterable, false); } @Test public void testQueryUsingNameAndStartAndEndWithNEQOperator() { FilterCriteria criteria = new FilterCriteria(); criteria.setOperator(Operator.NEQ); criteria.setState(getSecondItemState()); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); criteria.setEndDate(afterStore2); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); Iterator<HistoricItem> iterator = iterable.iterator(); HistoricItem actual1 = iterator.next(); assertFalse(iterator.hasNext()); assertStateEquals(getFirstItemState(), actual1.getState()); assertTrue(actual1.getTimestamp().before(afterStore1)); assertTrue(actual1.getTimestamp().after(beforeStore)); } @Test public void testQueryUsingNameAndStartAndEndWithEQOperator() { FilterCriteria criteria = new FilterCriteria(); criteria.setOperator(Operator.EQ); criteria.setState(getFirstItemState()); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); criteria.setEndDate(afterStore2); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); Iterator<HistoricItem> iterator = iterable.iterator(); HistoricItem actual1 = iterator.next(); assertFalse(iterator.hasNext()); assertStateEquals(getFirstItemState(), actual1.getState()); assertTrue(actual1.getTimestamp().before(afterStore1)); assertTrue(actual1.getTimestamp().after(beforeStore)); } @Test public void testQueryUsingNameAndStartAndEndWithLTOperator() { FilterCriteria criteria = new FilterCriteria(); criteria.setOperator(Operator.LT); criteria.setState(getSecondItemState()); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); criteria.setEndDate(afterStore2); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); Iterator<HistoricItem> iterator = iterable.iterator(); HistoricItem actual1 = iterator.next(); assertFalse(iterator.hasNext()); assertStateEquals(getFirstItemState(), actual1.getState()); assertTrue(actual1.getTimestamp().before(afterStore1)); assertTrue(actual1.getTimestamp().after(beforeStore)); } @Test public void testQueryUsingNameAndStartAndEndWithLTOperatorNoMatch() { FilterCriteria criteria = new FilterCriteria(); criteria.setOperator(Operator.LT); criteria.setState(getFirstItemState()); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); criteria.setEndDate(afterStore2); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); Iterator<HistoricItem> iterator = iterable.iterator(); assertFalse(iterator.hasNext()); } @Test public void testQueryUsingNameAndStartAndEndWithLTEOperator() { FilterCriteria criteria = new FilterCriteria(); criteria.setOperator(Operator.LTE); criteria.setState(getFirstItemState()); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); criteria.setEndDate(afterStore2); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); Iterator<HistoricItem> iterator = iterable.iterator(); HistoricItem actual1 = iterator.next(); assertFalse(iterator.hasNext()); assertStateEquals(getFirstItemState(), actual1.getState()); assertTrue(actual1.getTimestamp().before(afterStore1)); assertTrue(actual1.getTimestamp().after(beforeStore)); } @Test public void testQueryUsingNameAndStartAndEndWithGTOperator() { // Skip for subclasses which have null "state between" Assume.assumeTrue(getQueryItemStateBetween() != null); FilterCriteria criteria = new FilterCriteria(); criteria.setOperator(Operator.GT); criteria.setState(getQueryItemStateBetween()); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); criteria.setEndDate(afterStore2); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); Iterator<HistoricItem> iterator = iterable.iterator(); HistoricItem actual1 = iterator.next(); assertFalse(iterator.hasNext()); assertStateEquals(getSecondItemState(), actual1.getState()); assertTrue(actual1.getTimestamp().before(afterStore2)); assertTrue(actual1.getTimestamp().after(afterStore1)); } @Test public void testQueryUsingNameAndStartAndEndWithGTOperatorNoMatch() { FilterCriteria criteria = new FilterCriteria(); criteria.setOperator(Operator.GT); criteria.setState(getSecondItemState()); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); criteria.setEndDate(afterStore2); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); Iterator<HistoricItem> iterator = iterable.iterator(); assertFalse(iterator.hasNext()); } @Test public void testQueryUsingNameAndStartAndEndWithGTEOperator() { FilterCriteria criteria = new FilterCriteria(); criteria.setOperator(Operator.GTE); criteria.setState(getSecondItemState()); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); criteria.setEndDate(afterStore2); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); Iterator<HistoricItem> iterator = iterable.iterator(); HistoricItem actual1 = iterator.next(); assertFalse(iterator.hasNext()); assertStateEquals(getSecondItemState(), actual1.getState()); assertTrue(actual1.getTimestamp().before(afterStore2)); assertTrue(actual1.getTimestamp().after(afterStore1)); } @Test public void testQueryUsingNameAndStartAndEndFirst() { FilterCriteria criteria = new FilterCriteria(); criteria.setOrdering(Ordering.ASCENDING); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); criteria.setEndDate(afterStore1); Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); Iterator<HistoricItem> iterator = iterable.iterator(); HistoricItem actual1 = iterator.next(); assertFalse(iterator.hasNext()); assertStateEquals(getFirstItemState(), actual1.getState()); assertTrue(actual1.getTimestamp().before(afterStore1)); assertTrue(actual1.getTimestamp().after(beforeStore)); } @Test public void testQueryUsingNameAndStartAndEndNoMatch() { FilterCriteria criteria = new FilterCriteria(); criteria.setItemName(getItemName()); criteria.setBeginDate(beforeStore); criteria.setEndDate(beforeStore); // sic Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria); assertFalse(iterable.iterator().hasNext()); } }