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.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.List;
20 import java.util.concurrent.atomic.AtomicInteger;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.junit.jupiter.api.AfterEach;
24 import org.junit.jupiter.api.BeforeEach;
25 import org.junit.jupiter.api.Test;
26 import org.openhab.core.library.items.NumberItem;
27 import org.openhab.core.library.items.PlayerItem;
28 import org.openhab.core.library.items.StringItem;
29 import org.openhab.core.library.items.SwitchItem;
30 import org.openhab.core.library.types.DecimalType;
31 import org.openhab.core.library.types.OnOffType;
32 import org.openhab.core.library.types.PlayPauseType;
33 import org.openhab.core.library.types.StringType;
34 import org.openhab.core.persistence.FilterCriteria;
35 import org.openhab.core.persistence.FilterCriteria.Ordering;
36 import org.openhab.core.persistence.HistoricItem;
37 import org.openhab.core.types.State;
41 * @author Sami Salonen - Initial contribution
45 public class TestStoreMixedTypesTest extends BaseIntegrationTest {
47 public static final boolean LEGACY_MODE = false;
49 private static final AtomicInteger testCounter = new AtomicInteger();
52 private String getItemName() {
53 return "localItem" + uniqueId;
57 private void generateUniqueItemId() {
58 uniqueId = testCounter.getAndIncrement();
62 private void tearDownLocalItems() {
63 ITEMS.remove(getItemName());
66 @SuppressWarnings("null")
67 public void storeItemWithDifferentTypes() {
70 // First writing two values with string item
72 StringItem item = new StringItem(getItemName());
73 ITEMS.put(getItemName(), item);
74 item.setState(StringType.valueOf("a1"));
78 item.setState(StringType.valueOf("b1"));
82 // then writing with same item but numbers
84 NumberItem item = new NumberItem(getItemName());
86 ITEMS.put(getItemName(), item);
87 item.setState(DecimalType.valueOf("33.14"));
90 item.setState(DecimalType.valueOf("66.28"));
94 // finally some switch values
96 SwitchItem item = new SwitchItem(getItemName());
98 ITEMS.put(getItemName(), item);
99 item.setState(OnOffType.ON);
102 item.setState(OnOffType.OFF);
108 PlayerItem item = new PlayerItem(getItemName());
110 ITEMS.put(getItemName(), item);
111 item.setState(PlayPauseType.PAUSE);
115 } catch (InterruptedException e) {
121 * Test where first data is stored with various item types, some serialized as numbers and some as strings.
123 * - Querying with NumberItem returns data that have been persisted using DynamoDBBigDecimalItem DTO, that is,
124 * NumberItem and SwitchItem data
125 * - Querying with StringItem returns data that have been persisted using DynamoDBStringItem DTO (StringItem and
127 * - Querying with SwitchItem returns data that have been persisted using DynamoDBBigDecimalItem DTO. All numbers
128 * are converted to OnOff (ON if nonzero)
129 * - Querying with PlayerItem returns data that have been persisted using DynamoDBStringItem DTO. However, some
130 * values are not convertible to PlayPauseType are ignored (warning logged).
134 public void testQueryAllItemTypeChanged() {
135 storeItemWithDifferentTypes();
137 NumberItem item = new NumberItem(getItemName());
138 ITEMS.put(getItemName(), item);
139 waitForAssert(() -> {
140 assertQueryAll(getItemName(), expectedNumberItem());
144 SwitchItem item = new SwitchItem(getItemName());
145 ITEMS.put(getItemName(), item);
146 waitForAssert(() -> {
147 assertQueryAll(getItemName(), expectedSwitchItem());
151 StringItem item = new StringItem(getItemName());
152 ITEMS.put(getItemName(), item);
153 waitForAssert(() -> {
154 assertQueryAll(getItemName(), expectedStringItem());
158 PlayerItem item = new PlayerItem(getItemName());
160 ITEMS.put(getItemName(), item);
161 waitForAssert(() -> {
162 assertQueryAll(getItemName(), expectedPlayerItem());
167 protected PlayPauseType[] expectedPlayerItem() {
168 return new PlayPauseType[] { /* ON=1=PLAY */PlayPauseType.PLAY, /* OFF=0=PAUSE */PlayPauseType.PAUSE,
169 PlayPauseType.PAUSE };
172 protected StringType[] expectedStringItem() {
173 return new StringType[] { StringType.valueOf("a1"), StringType.valueOf("b1") };
176 protected OnOffType[] expectedSwitchItem() {
177 return new OnOffType[] { /* 33.14 */OnOffType.ON, /* 66.28 */ OnOffType.ON, OnOffType.ON, OnOffType.OFF,
178 /* pause */ OnOffType.OFF };
181 protected DecimalType[] expectedNumberItem() {
182 return new DecimalType[] { DecimalType.valueOf("33.14"), DecimalType.valueOf("66.28"),
183 /* on */DecimalType.valueOf("1"), /* off */DecimalType.valueOf("0"),
184 /* pause */DecimalType.valueOf("0") };
187 private void assertQueryAll(String item, State[] expectedStates) {
188 FilterCriteria criteria = new FilterCriteria();
189 criteria.setOrdering(Ordering.ASCENDING);
190 criteria.setItemName(item);
191 @SuppressWarnings("null")
192 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
193 List<State> actualStatesList = new ArrayList<>();
194 iterable.forEach(i -> actualStatesList.add(i.getState()));
195 State[] actualStates = actualStatesList.toArray(new State[0]);
196 assertArrayEquals(expectedStates, actualStates, Arrays.toString(actualStates));