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.*;
16 import static org.junit.jupiter.api.Assumptions.assumeTrue;
18 import java.time.ZonedDateTime;
19 import java.util.Iterator;
21 import org.eclipse.jdt.annotation.NonNullByDefault;
22 import org.eclipse.jdt.annotation.Nullable;
23 import org.junit.jupiter.api.BeforeAll;
24 import org.junit.jupiter.api.Test;
25 import org.openhab.core.persistence.FilterCriteria;
26 import org.openhab.core.persistence.FilterCriteria.Operator;
27 import org.openhab.core.persistence.FilterCriteria.Ordering;
28 import org.openhab.core.persistence.HistoricItem;
29 import org.openhab.core.types.State;
32 * This is abstract class helping with integration testing the persistence service. Different kind of queries are tested
33 * against actual dynamo db database.
36 * Inheritor of this base class needs to store two states of one item in a static method annotated with @BeforeAll.
39 * class should update the private static fields
40 * beforeStore (date before storing anything), afterStore1 (after storing first item, but before storing second item),
41 * afterStore2 (after storing second item). The item name must correspond to getItemName. The first state needs to be
42 * smaller than the second state.
44 * To have more comprehensive tests, the inheritor class can define getQueryItemStateBetween to provide a value between
45 * the two states. Null can be used to omit the additional tests.
48 * See DimmerItemIntegrationTest for example how to use this base class.
50 * @author Sami Salonen - Initial contribution
54 public abstract class AbstractTwoItemIntegrationTest extends BaseIntegrationTest {
56 protected static @Nullable ZonedDateTime beforeStore;
57 protected static @Nullable ZonedDateTime afterStore1;
58 protected static @Nullable ZonedDateTime afterStore2;
60 protected abstract String getItemName();
63 * State of the time item stored first, should be smaller than the second value
67 protected abstract State getFirstItemState();
70 * State of the time item stored second, should be larger than the first value
74 protected abstract State getSecondItemState();
77 * State that is between the first and second. Use null to omit extended tests using this value.
81 protected abstract @Nullable State getQueryItemStateBetween();
83 protected void assertStateEquals(State expected, State actual) {
84 assertEquals(expected, actual);
88 public static void checkService() throws InterruptedException {
89 String msg = "DynamoDB integration tests will be skipped. Did you specify AWS credentials for testing? "
90 + "See BaseIntegrationTest for more details";
91 if (service == null) {
92 System.out.println(msg);
94 assumeTrue(service != null, msg);
98 * Asserts that iterable contains correct items and nothing else
101 private void assertIterableContainsItems(Iterable<HistoricItem> iterable, boolean ascending) {
102 Iterator<HistoricItem> iterator = iterable.iterator();
103 HistoricItem actual1 = iterator.next();
104 HistoricItem actual2 = iterator.next();
105 assertFalse(iterator.hasNext());
107 for (HistoricItem actual : new HistoricItem[] { actual1, actual2 }) {
108 assertEquals(getItemName(), actual.getName());
110 HistoricItem storedFirst;
111 HistoricItem storedSecond;
113 storedFirst = actual1;
114 storedSecond = actual2;
116 storedFirst = actual2;
117 storedSecond = actual1;
120 assertStateEquals(getFirstItemState(), storedFirst.getState());
121 assertTrue(storedFirst.getTimestamp().toInstant().isBefore(afterStore1.toInstant()));
122 assertTrue(storedFirst.getTimestamp().toInstant().isAfter(beforeStore.toInstant()));
124 assertStateEquals(getSecondItemState(), storedSecond.getState());
125 assertTrue(storedSecond.getTimestamp().toInstant().isBefore(afterStore2.toInstant()));
126 assertTrue(storedSecond.getTimestamp().toInstant().isAfter(afterStore1.toInstant()));
130 public void testQueryUsingName() {
131 FilterCriteria criteria = new FilterCriteria();
132 criteria.setOrdering(Ordering.ASCENDING);
133 criteria.setItemName(getItemName());
134 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
135 assertIterableContainsItems(iterable, true);
139 public void testQueryUsingNameAndStart() {
140 FilterCriteria criteria = new FilterCriteria();
141 criteria.setOrdering(Ordering.ASCENDING);
142 criteria.setItemName(getItemName());
143 criteria.setBeginDate(beforeStore);
144 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
145 assertIterableContainsItems(iterable, true);
149 public void testQueryUsingNameAndStartNoMatch() {
150 FilterCriteria criteria = new FilterCriteria();
151 criteria.setItemName(getItemName());
152 criteria.setBeginDate(afterStore2);
153 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
154 assertFalse(iterable.iterator().hasNext());
158 public void testQueryUsingNameAndEnd() {
159 FilterCriteria criteria = new FilterCriteria();
160 criteria.setOrdering(Ordering.ASCENDING);
161 criteria.setItemName(getItemName());
162 criteria.setEndDate(afterStore2);
163 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
164 assertIterableContainsItems(iterable, true);
168 public void testQueryUsingNameAndEndNoMatch() {
169 FilterCriteria criteria = new FilterCriteria();
170 criteria.setItemName(getItemName());
171 criteria.setEndDate(beforeStore);
172 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
173 assertFalse(iterable.iterator().hasNext());
177 public void testQueryUsingNameAndStartAndEnd() {
178 FilterCriteria criteria = new FilterCriteria();
179 criteria.setOrdering(Ordering.ASCENDING);
180 criteria.setItemName(getItemName());
181 criteria.setBeginDate(beforeStore);
182 criteria.setEndDate(afterStore2);
183 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
184 assertIterableContainsItems(iterable, true);
188 public void testQueryUsingNameAndStartAndEndDesc() {
189 FilterCriteria criteria = new FilterCriteria();
190 criteria.setOrdering(Ordering.DESCENDING);
191 criteria.setItemName(getItemName());
192 criteria.setBeginDate(beforeStore);
193 criteria.setEndDate(afterStore2);
194 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
195 assertIterableContainsItems(iterable, false);
199 public void testQueryUsingNameAndStartAndEndWithNEQOperator() {
200 FilterCriteria criteria = new FilterCriteria();
201 criteria.setOperator(Operator.NEQ);
202 criteria.setState(getSecondItemState());
203 criteria.setItemName(getItemName());
204 criteria.setBeginDate(beforeStore);
205 criteria.setEndDate(afterStore2);
206 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
207 Iterator<HistoricItem> iterator = iterable.iterator();
208 HistoricItem actual1 = iterator.next();
209 assertFalse(iterator.hasNext());
210 assertStateEquals(getFirstItemState(), actual1.getState());
211 assertTrue(actual1.getTimestamp().toInstant().isBefore(afterStore1.toInstant()));
212 assertTrue(actual1.getTimestamp().toInstant().isAfter(beforeStore.toInstant()));
216 public void testQueryUsingNameAndStartAndEndWithEQOperator() {
217 FilterCriteria criteria = new FilterCriteria();
218 criteria.setOperator(Operator.EQ);
219 criteria.setState(getFirstItemState());
220 criteria.setItemName(getItemName());
221 criteria.setBeginDate(beforeStore);
222 criteria.setEndDate(afterStore2);
223 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
224 Iterator<HistoricItem> iterator = iterable.iterator();
225 HistoricItem actual1 = iterator.next();
226 assertFalse(iterator.hasNext());
227 assertStateEquals(getFirstItemState(), actual1.getState());
228 assertTrue(actual1.getTimestamp().toInstant().isBefore(afterStore1.toInstant()));
229 assertTrue(actual1.getTimestamp().toInstant().isAfter(beforeStore.toInstant()));
233 public void testQueryUsingNameAndStartAndEndWithLTOperator() {
234 FilterCriteria criteria = new FilterCriteria();
235 criteria.setOperator(Operator.LT);
236 criteria.setState(getSecondItemState());
237 criteria.setItemName(getItemName());
238 criteria.setBeginDate(beforeStore);
239 criteria.setEndDate(afterStore2);
240 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
241 Iterator<HistoricItem> iterator = iterable.iterator();
242 HistoricItem actual1 = iterator.next();
243 assertFalse(iterator.hasNext());
244 assertStateEquals(getFirstItemState(), actual1.getState());
245 assertTrue(actual1.getTimestamp().toInstant().isBefore(afterStore1.toInstant()));
246 assertTrue(actual1.getTimestamp().toInstant().isAfter(beforeStore.toInstant()));
250 public void testQueryUsingNameAndStartAndEndWithLTOperatorNoMatch() {
251 FilterCriteria criteria = new FilterCriteria();
252 criteria.setOperator(Operator.LT);
253 criteria.setState(getFirstItemState());
254 criteria.setItemName(getItemName());
255 criteria.setBeginDate(beforeStore);
256 criteria.setEndDate(afterStore2);
257 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
258 Iterator<HistoricItem> iterator = iterable.iterator();
259 assertFalse(iterator.hasNext());
263 public void testQueryUsingNameAndStartAndEndWithLTEOperator() {
264 FilterCriteria criteria = new FilterCriteria();
265 criteria.setOperator(Operator.LTE);
266 criteria.setState(getFirstItemState());
267 criteria.setItemName(getItemName());
268 criteria.setBeginDate(beforeStore);
269 criteria.setEndDate(afterStore2);
270 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
271 Iterator<HistoricItem> iterator = iterable.iterator();
272 HistoricItem actual1 = iterator.next();
273 assertFalse(iterator.hasNext());
274 assertStateEquals(getFirstItemState(), actual1.getState());
275 assertTrue(actual1.getTimestamp().toInstant().isBefore(afterStore1.toInstant()));
276 assertTrue(actual1.getTimestamp().toInstant().isAfter(beforeStore.toInstant()));
280 public void testQueryUsingNameAndStartAndEndWithGTOperator() {
281 // Skip for subclasses which have null "state between"
282 assumeTrue(getQueryItemStateBetween() != null);
284 FilterCriteria criteria = new FilterCriteria();
285 criteria.setOperator(Operator.GT);
286 criteria.setState(getQueryItemStateBetween());
287 criteria.setItemName(getItemName());
288 criteria.setBeginDate(beforeStore);
289 criteria.setEndDate(afterStore2);
290 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
291 Iterator<HistoricItem> iterator = iterable.iterator();
292 HistoricItem actual1 = iterator.next();
293 assertFalse(iterator.hasNext());
294 assertStateEquals(getSecondItemState(), actual1.getState());
295 assertTrue(actual1.getTimestamp().toInstant().isBefore(afterStore2.toInstant()));
296 assertTrue(actual1.getTimestamp().toInstant().isAfter(afterStore1.toInstant()));
300 public void testQueryUsingNameAndStartAndEndWithGTOperatorNoMatch() {
301 FilterCriteria criteria = new FilterCriteria();
302 criteria.setOperator(Operator.GT);
303 criteria.setState(getSecondItemState());
304 criteria.setItemName(getItemName());
305 criteria.setBeginDate(beforeStore);
306 criteria.setEndDate(afterStore2);
307 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
308 Iterator<HistoricItem> iterator = iterable.iterator();
309 assertFalse(iterator.hasNext());
313 public void testQueryUsingNameAndStartAndEndWithGTEOperator() {
314 FilterCriteria criteria = new FilterCriteria();
315 criteria.setOperator(Operator.GTE);
316 criteria.setState(getSecondItemState());
317 criteria.setItemName(getItemName());
318 criteria.setBeginDate(beforeStore);
319 criteria.setEndDate(afterStore2);
320 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
321 Iterator<HistoricItem> iterator = iterable.iterator();
322 HistoricItem actual1 = iterator.next();
323 assertFalse(iterator.hasNext());
324 assertStateEquals(getSecondItemState(), actual1.getState());
325 assertTrue(actual1.getTimestamp().toInstant().isBefore(afterStore2.toInstant()));
326 assertTrue(actual1.getTimestamp().toInstant().isAfter(afterStore1.toInstant()));
330 public void testQueryUsingNameAndStartAndEndFirst() {
331 FilterCriteria criteria = new FilterCriteria();
332 criteria.setOrdering(Ordering.ASCENDING);
333 criteria.setItemName(getItemName());
334 criteria.setBeginDate(beforeStore);
335 criteria.setEndDate(afterStore1);
336 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
338 Iterator<HistoricItem> iterator = iterable.iterator();
339 HistoricItem actual1 = iterator.next();
340 assertFalse(iterator.hasNext());
341 assertStateEquals(getFirstItemState(), actual1.getState());
342 assertTrue(actual1.getTimestamp().toInstant().isBefore(afterStore1.toInstant()));
343 assertTrue(actual1.getTimestamp().toInstant().isAfter(beforeStore.toInstant()));
347 public void testQueryUsingNameAndStartAndEndNoMatch() {
348 FilterCriteria criteria = new FilterCriteria();
349 criteria.setItemName(getItemName());
350 criteria.setBeginDate(beforeStore);
351 criteria.setEndDate(beforeStore); // sic
352 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
353 assertFalse(iterable.iterator().hasNext());