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