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 public void generateUniqueItemId() {
58 uniqueId = testCounter.getAndIncrement();
62 public void tearDownLocalItems() {
63 ITEMS.remove(getItemName());
66 @SuppressWarnings("null")
67 public void storeItemWithDifferentTypes() {
69 // First writing two values with string item
71 StringItem item = new StringItem(getItemName());
72 ITEMS.put(getItemName(), item);
73 item.setState(StringType.valueOf("a1"));
77 item.setState(StringType.valueOf("b1"));
81 // then writing with same item but numbers
83 NumberItem item = new NumberItem(getItemName());
85 ITEMS.put(getItemName(), item);
86 item.setState(DecimalType.valueOf("33.14"));
89 item.setState(DecimalType.valueOf("66.28"));
93 // finally some switch values
95 SwitchItem item = new SwitchItem(getItemName());
97 ITEMS.put(getItemName(), item);
98 item.setState(OnOffType.ON);
101 item.setState(OnOffType.OFF);
107 PlayerItem item = new PlayerItem(getItemName());
109 ITEMS.put(getItemName(), item);
110 item.setState(PlayPauseType.PAUSE);
114 } catch (InterruptedException e) {
120 * Test where first data is stored with various item types, some serialized as numbers and some as strings.
122 * - Querying with NumberItem returns data that have been persisted using DynamoDBBigDecimalItem DTO, that is,
123 * NumberItem and SwitchItem data
124 * - Querying with StringItem returns data that have been persisted using DynamoDBStringItem DTO (StringItem and
126 * - Querying with SwitchItem returns data that have been persisted using DynamoDBBigDecimalItem DTO. All numbers
127 * are converted to OnOff (ON if nonzero)
128 * - Querying with PlayerItem returns data that have been persisted using DynamoDBStringItem DTO. However, some
129 * values are not convertible to PlayPauseType are ignored (warning logged).
133 public void testQueryAllItemTypeChanged() {
134 storeItemWithDifferentTypes();
136 NumberItem item = new NumberItem(getItemName());
137 ITEMS.put(getItemName(), item);
138 waitForAssert(() -> {
139 assertQueryAll(getItemName(), expectedNumberItem());
143 SwitchItem item = new SwitchItem(getItemName());
144 ITEMS.put(getItemName(), item);
145 waitForAssert(() -> {
146 assertQueryAll(getItemName(), expectedSwitchItem());
150 StringItem item = new StringItem(getItemName());
151 ITEMS.put(getItemName(), item);
152 waitForAssert(() -> {
153 assertQueryAll(getItemName(), expectedStringItem());
157 PlayerItem item = new PlayerItem(getItemName());
159 ITEMS.put(getItemName(), item);
160 waitForAssert(() -> {
161 assertQueryAll(getItemName(), expectedPlayerItem());
166 protected PlayPauseType[] expectedPlayerItem() {
167 return new PlayPauseType[] { /* ON=1=PLAY */PlayPauseType.PLAY, /* OFF=0=PAUSE */PlayPauseType.PAUSE,
168 PlayPauseType.PAUSE };
171 protected StringType[] expectedStringItem() {
172 return new StringType[] { StringType.valueOf("a1"), StringType.valueOf("b1") };
175 protected OnOffType[] expectedSwitchItem() {
176 return new OnOffType[] { /* 33.14 */OnOffType.ON, /* 66.28 */ OnOffType.ON, OnOffType.ON, OnOffType.OFF,
177 /* pause */ OnOffType.OFF };
180 protected DecimalType[] expectedNumberItem() {
181 return new DecimalType[] { DecimalType.valueOf("33.14"), DecimalType.valueOf("66.28"),
182 /* on */DecimalType.valueOf("1"), /* off */DecimalType.valueOf("0"),
183 /* pause */DecimalType.valueOf("0") };
186 private void assertQueryAll(String item, State[] expectedStates) {
187 FilterCriteria criteria = new FilterCriteria();
188 criteria.setOrdering(Ordering.ASCENDING);
189 criteria.setItemName(item);
190 @SuppressWarnings("null")
191 Iterable<HistoricItem> iterable = BaseIntegrationTest.service.query(criteria);
192 List<State> actualStatesList = new ArrayList<>();
193 iterable.forEach(i -> actualStatesList.add(i.getState()));
194 State[] actualStates = actualStatesList.toArray(new State[0]);
195 assertArrayEquals(expectedStates, actualStates, Arrays.toString(actualStates));