2 * Copyright (c) 2010-2024 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.inmemory.internal;
15 import static org.hamcrest.MatcherAssert.assertThat;
16 import static org.hamcrest.Matchers.closeTo;
17 import static org.hamcrest.Matchers.empty;
18 import static org.hamcrest.Matchers.hasSize;
19 import static org.hamcrest.Matchers.is;
20 import static org.mockito.Mockito.when;
22 import java.time.ZoneId;
23 import java.time.ZonedDateTime;
24 import java.util.Comparator;
25 import java.util.TreeSet;
27 import org.eclipse.jdt.annotation.NonNullByDefault;
28 import org.junit.jupiter.api.BeforeEach;
29 import org.junit.jupiter.api.Test;
30 import org.junit.jupiter.api.extension.ExtendWith;
31 import org.mockito.Mock;
32 import org.mockito.junit.jupiter.MockitoExtension;
33 import org.mockito.junit.jupiter.MockitoSettings;
34 import org.mockito.quality.Strictness;
35 import org.openhab.core.items.GenericItem;
36 import org.openhab.core.library.types.DecimalType;
37 import org.openhab.core.library.types.HSBType;
38 import org.openhab.core.library.types.PercentType;
39 import org.openhab.core.library.types.StringType;
40 import org.openhab.core.persistence.FilterCriteria;
41 import org.openhab.core.persistence.HistoricItem;
42 import org.openhab.core.types.State;
45 * The {@link InMemoryPersistenceTests} contains tests for the {@link InMemoryPersistenceService}
47 * @author Jan N. Klug - Initial contribution
49 @ExtendWith(MockitoExtension.class)
50 @MockitoSettings(strictness = Strictness.LENIENT)
52 public class InMemoryPersistenceTests {
53 private static final String ITEM_NAME = "testItem";
54 private static final String ALIAS = "alias";
56 private @NonNullByDefault({}) InMemoryPersistenceService service;
57 private @NonNullByDefault({}) @Mock GenericItem item;
59 private @NonNullByDefault({}) FilterCriteria filterCriteria;
63 when(item.getName()).thenReturn(ITEM_NAME);
65 filterCriteria = new FilterCriteria();
66 filterCriteria.setItemName(ITEM_NAME);
68 service = new InMemoryPersistenceService();
72 public void storeDirect() {
73 State state = new DecimalType(1);
74 when(item.getState()).thenReturn(state);
76 ZonedDateTime expectedTime = ZonedDateTime.now();
79 TreeSet<HistoricItem> storedStates = new TreeSet<>(Comparator.comparing(HistoricItem::getTimestamp));
80 service.query(filterCriteria).forEach(storedStates::add);
82 assertThat(storedStates, hasSize(1));
83 assertThat(storedStates.first().getName(), is(ITEM_NAME));
84 assertThat(storedStates.first().getState(), is(state));
85 assertThat((double) storedStates.first().getTimestamp().toEpochSecond(),
86 is(closeTo(expectedTime.toEpochSecond(), 2)));
90 public void storeAlias() {
91 State state = new PercentType(1);
92 when(item.getState()).thenReturn(state);
94 ZonedDateTime expectedTime = ZonedDateTime.now();
95 service.store(item, ALIAS);
97 TreeSet<HistoricItem> storedStates = new TreeSet<>(Comparator.comparing(HistoricItem::getTimestamp));
99 // query with item name should return nothing
100 service.query(filterCriteria).forEach(storedStates::add);
101 assertThat(storedStates, is(empty()));
103 filterCriteria.setItemName(ALIAS);
104 service.query(filterCriteria).forEach(storedStates::add);
106 assertThat(storedStates.size(), is(1));
107 assertThat(storedStates.first().getName(), is(ALIAS));
108 assertThat(storedStates.first().getState(), is(state));
109 assertThat((double) storedStates.first().getTimestamp().toEpochSecond(),
110 is(closeTo(expectedTime.toEpochSecond(), 2)));
114 public void storeHistoric() {
115 State state = new HSBType("120,100,100");
116 when(item.getState()).thenReturn(state);
118 State historicState = new HSBType("40,50,50");
119 ZonedDateTime expectedTime = ZonedDateTime.of(2022, 05, 31, 10, 0, 0, 0, ZoneId.systemDefault());
120 service.store(item, expectedTime, historicState);
122 TreeSet<HistoricItem> storedStates = new TreeSet<>(Comparator.comparing(HistoricItem::getTimestamp));
123 service.query(filterCriteria).forEach(storedStates::add);
125 assertThat(storedStates, hasSize(1));
126 assertThat(storedStates.first().getName(), is(ITEM_NAME));
127 assertThat(storedStates.first().getState(), is(historicState));
128 assertThat(storedStates.first().getTimestamp(), is(expectedTime));
132 public void queryWithoutItemNameReturnsEmptyList() {
133 TreeSet<HistoricItem> storedStates = new TreeSet<>(Comparator.comparing(HistoricItem::getTimestamp));
134 service.query(new FilterCriteria()).forEach(storedStates::add);
136 assertThat(storedStates, is(empty()));
140 public void queryUnknownItemReturnsEmptyList() {
141 TreeSet<HistoricItem> storedStates = new TreeSet<>(Comparator.comparing(HistoricItem::getTimestamp));
142 service.query(filterCriteria).forEach(storedStates::add);
144 assertThat(storedStates, is(empty()));
148 public void removeBetweenTimes() {
149 State historicState1 = new StringType("value1");
150 State historicState2 = new StringType("value2");
151 State historicState3 = new StringType("value3");
153 ZonedDateTime expectedTime = ZonedDateTime.of(2022, 05, 31, 10, 0, 0, 0, ZoneId.systemDefault());
154 service.store(item, expectedTime, historicState1);
155 service.store(item, expectedTime.plusHours(2), historicState2);
156 service.store(item, expectedTime.plusHours(4), historicState3);
158 // ensure both are stored
159 TreeSet<HistoricItem> storedStates = new TreeSet<>(Comparator.comparing(HistoricItem::getTimestamp));
160 service.query(filterCriteria).forEach(storedStates::add);
162 assertThat(storedStates, hasSize(3));
164 filterCriteria.setBeginDate(expectedTime.plusHours(1));
165 filterCriteria.setEndDate(expectedTime.plusHours(3));
166 service.remove(filterCriteria);
168 filterCriteria = new FilterCriteria();
169 filterCriteria.setItemName(ITEM_NAME);
170 storedStates.clear();
171 service.query(filterCriteria).forEach(storedStates::add);
173 assertThat(storedStates, hasSize(2));
175 assertThat(storedStates.first().getName(), is(ITEM_NAME));
176 assertThat(storedStates.first().getState(), is(historicState1));
177 assertThat(storedStates.first().getTimestamp(), is(expectedTime));
179 assertThat(storedStates.last().getName(), is(ITEM_NAME));
180 assertThat(storedStates.last().getState(), is(historicState3));
181 assertThat(storedStates.last().getTimestamp(), is(expectedTime.plusHours(4)));