2 * Copyright (c) 2010-2023 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.math.BigDecimal;
18 import java.time.ZonedDateTime;
19 import java.util.ArrayList;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.Objects;
24 import org.eclipse.jdt.annotation.NonNullByDefault;
25 import org.eclipse.jdt.annotation.Nullable;
26 import org.junit.jupiter.api.BeforeAll;
27 import org.junit.jupiter.api.Test;
28 import org.openhab.core.library.items.NumberItem;
29 import org.openhab.core.library.types.DecimalType;
30 import org.openhab.core.persistence.FilterCriteria;
31 import org.openhab.core.persistence.FilterCriteria.Operator;
32 import org.openhab.core.persistence.FilterCriteria.Ordering;
33 import org.openhab.core.persistence.HistoricItem;
37 * @author Sami Salonen - Initial contribution
41 public class PagingIntegrationTest extends BaseIntegrationTest {
43 public static final boolean LEGACY_MODE = false;
44 private static final String NAME = "number";
45 private static final int STATE_COUNT = 10;
47 private static @Nullable ZonedDateTime storeStart;
49 @SuppressWarnings("null")
51 public static void populateData() {
52 storeStart = ZonedDateTime.now();
54 NumberItem item = (NumberItem) ITEMS.get(NAME);
55 for (int i = 0; i < STATE_COUNT; i++) {
56 item.setState(new DecimalType(i));
58 // Add some delay to enforce different timestamps in ms accuracy
60 } catch (InterruptedException e) {
68 @SuppressWarnings("null")
70 public void testPagingFirstPage() {
72 FilterCriteria criteria = new FilterCriteria();
73 criteria.setItemName(NAME);
74 criteria.setBeginDate(Objects.requireNonNull(storeStart));
75 criteria.setOrdering(Ordering.ASCENDING);
76 criteria.setPageNumber(0);
77 criteria.setPageSize(3);
78 assertItemStates(BaseIntegrationTest.service.query(criteria), 0, 1, 2);
82 @SuppressWarnings("null")
84 public void testPagingSecondPage() {
86 FilterCriteria criteria = new FilterCriteria();
87 criteria.setItemName(NAME);
88 criteria.setBeginDate(Objects.requireNonNull(storeStart));
89 criteria.setOrdering(Ordering.ASCENDING);
90 criteria.setPageNumber(1);
91 criteria.setPageSize(3);
92 assertItemStates(BaseIntegrationTest.service.query(criteria), 3, 4, 5);
96 @SuppressWarnings("null")
98 public void testPagingPagePartialPage() {
100 FilterCriteria criteria = new FilterCriteria();
101 criteria.setItemName(NAME);
102 criteria.setBeginDate(Objects.requireNonNull(storeStart));
103 criteria.setOrdering(Ordering.ASCENDING);
104 criteria.setPageNumber(3);
105 criteria.setPageSize(3);
106 assertItemStates(BaseIntegrationTest.service.query(criteria), 9);
110 @SuppressWarnings("null")
112 public void testPagingPageOutOfBounds() {
113 waitForAssert(() -> {
114 FilterCriteria criteria = new FilterCriteria();
115 criteria.setItemName(NAME);
116 criteria.setBeginDate(Objects.requireNonNull(storeStart));
117 criteria.setOrdering(Ordering.ASCENDING);
118 criteria.setPageNumber(4);
119 criteria.setPageSize(3);
120 assertItemStates(BaseIntegrationTest.service.query(criteria)); // no results
124 @SuppressWarnings("null")
126 public void testPagingPage0Descending() {
127 waitForAssert(() -> {
128 FilterCriteria criteria = new FilterCriteria();
129 criteria.setItemName(NAME);
130 criteria.setBeginDate(Objects.requireNonNull(storeStart));
131 criteria.setOrdering(Ordering.DESCENDING);
132 criteria.setPageNumber(0);
133 criteria.setPageSize(3);
134 assertItemStates(BaseIntegrationTest.service.query(criteria), 9, 8, 7);
138 @SuppressWarnings("null")
140 public void testPagingPage0HugePageSize() {
141 waitForAssert(() -> {
142 FilterCriteria criteria = new FilterCriteria();
143 criteria.setItemName(NAME);
144 criteria.setBeginDate(Objects.requireNonNull(storeStart));
145 criteria.setOrdering(Ordering.ASCENDING);
146 criteria.setPageNumber(0);
147 criteria.setPageSize(900);
148 assertItemStates(BaseIntegrationTest.service.query(criteria), 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
152 @SuppressWarnings("null")
154 public void testPagingFirstPageWithFilter() {
155 waitForAssert(() -> {
156 FilterCriteria criteria = new FilterCriteria();
157 criteria.setItemName(NAME);
158 criteria.setBeginDate(Objects.requireNonNull(storeStart));
159 criteria.setOrdering(Ordering.ASCENDING);
160 criteria.setPageNumber(0);
161 criteria.setPageSize(3);
162 criteria.setOperator(Operator.GT);
163 criteria.setState(new DecimalType(new BigDecimal(3)));
164 assertItemStates(BaseIntegrationTest.service.query(criteria), 4, 5, 6);
168 private void assertItemStates(Iterable<HistoricItem> actualIterable, int... expected) {
169 Iterator<HistoricItem> actualIterator = actualIterable.iterator();
170 List<DecimalType> expectedStates = new ArrayList<>();
171 List<DecimalType> actualStates = new ArrayList<>();
172 for (int expectedState : expected) {
173 assertTrue(actualIterator.hasNext());
174 HistoricItem actual = actualIterator.next();
175 expectedStates.add(new DecimalType(expectedState));
176 actualStates.add((DecimalType) actual.getState());
178 assertEquals(expectedStates, actualStates);
179 assertFalse(actualIterator.hasNext());