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.transform.basicprofiles.internal.profiles;
15 import static org.junit.jupiter.api.Assertions.assertEquals;
16 import static org.mockito.ArgumentMatchers.any;
17 import static org.mockito.ArgumentMatchers.eq;
18 import static org.mockito.Mockito.reset;
19 import static org.mockito.Mockito.times;
20 import static org.mockito.Mockito.verify;
21 import static org.mockito.Mockito.when;
23 import java.util.List;
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.junit.jupiter.api.BeforeEach;
28 import org.junit.jupiter.api.Test;
29 import org.junit.jupiter.api.extension.ExtendWith;
30 import org.mockito.Mock;
31 import org.mockito.junit.jupiter.MockitoExtension;
32 import org.mockito.junit.jupiter.MockitoSettings;
33 import org.mockito.quality.Strictness;
34 import org.openhab.core.config.core.Configuration;
35 import org.openhab.core.items.Item;
36 import org.openhab.core.items.ItemNotFoundException;
37 import org.openhab.core.items.ItemRegistry;
38 import org.openhab.core.library.items.StringItem;
39 import org.openhab.core.library.types.OnOffType;
40 import org.openhab.core.library.types.StringType;
41 import org.openhab.core.thing.profiles.ProfileCallback;
42 import org.openhab.core.thing.profiles.ProfileContext;
43 import org.openhab.core.types.State;
44 import org.openhab.core.types.UnDefType;
47 * Basic unit tests for {@link StateFilterProfile}.
49 * @author Arne Seime - Initial contribution
51 @ExtendWith(MockitoExtension.class)
52 @MockitoSettings(strictness = Strictness.WARN)
54 public class StateFilterProfileTest {
56 private @Mock @NonNullByDefault({}) ProfileCallback mockCallback;
57 private @Mock @NonNullByDefault({}) ProfileContext mockContext;
58 private @Mock @NonNullByDefault({}) ItemRegistry mockItemRegistry;
67 public void testNoConditions() {
68 when(mockContext.getConfiguration()).thenReturn(new Configuration(Map.of("conditions", "")));
69 StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);
71 State expectation = OnOffType.ON;
72 profile.onStateUpdateFromHandler(expectation);
73 verify(mockCallback, times(0)).sendUpdate(eq(expectation));
77 public void testMalformedConditions() {
78 when(mockContext.getConfiguration()).thenReturn(new Configuration(Map.of("conditions", "ItemName invalid")));
79 StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);
81 State expectation = OnOffType.ON;
82 profile.onStateUpdateFromHandler(expectation);
83 verify(mockCallback, times(0)).sendUpdate(eq(expectation));
87 public void testInvalidComparatorConditions() throws ItemNotFoundException {
88 when(mockContext.getConfiguration()).thenReturn(new Configuration(Map.of("conditions", "ItemName lt Value")));
89 StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);
90 when(mockItemRegistry.getItem(any())).thenThrow(ItemNotFoundException.class);
92 State expectation = OnOffType.ON;
93 profile.onStateUpdateFromHandler(expectation);
94 verify(mockCallback, times(0)).sendUpdate(eq(expectation));
98 public void testInvalidItemConditions() throws ItemNotFoundException {
99 when(mockContext.getConfiguration()).thenReturn(new Configuration(Map.of("conditions", "ItemName eq Value")));
100 StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);
102 when(mockItemRegistry.getItem(any())).thenThrow(ItemNotFoundException.class);
103 State expectation = OnOffType.ON;
104 profile.onStateUpdateFromHandler(expectation);
105 verify(mockCallback, times(0)).sendUpdate(eq(expectation));
109 public void testInvalidMultipleConditions() throws ItemNotFoundException {
110 when(mockContext.getConfiguration())
111 .thenReturn(new Configuration(Map.of("conditions", "ItemName eq Value,itemname invalid")));
112 StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);
113 when(mockItemRegistry.getItem(any())).thenThrow(ItemNotFoundException.class);
115 State expectation = OnOffType.ON;
116 profile.onStateUpdateFromHandler(expectation);
117 verify(mockCallback, times(0)).sendUpdate(eq(expectation));
121 public void testSingleConditionMatch() throws ItemNotFoundException {
122 when(mockContext.getConfiguration()).thenReturn(new Configuration(Map.of("conditions", "ItemName eq Value")));
123 when(mockItemRegistry.getItem("ItemName")).thenReturn(stringItemWithState("ItemName", "Value"));
125 StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);
127 State expectation = new StringType("NewValue");
128 profile.onStateUpdateFromHandler(expectation);
129 verify(mockCallback, times(1)).sendUpdate(eq(expectation));
133 public void testSingleConditionMatchQuoted() throws ItemNotFoundException {
134 when(mockContext.getConfiguration()).thenReturn(new Configuration(Map.of("conditions", "ItemName eq 'Value'")));
135 when(mockItemRegistry.getItem("ItemName")).thenReturn(stringItemWithState("ItemName", "Value"));
137 StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);
139 State expectation = new StringType("NewValue");
140 profile.onStateUpdateFromHandler(expectation);
141 verify(mockCallback, times(1)).sendUpdate(eq(expectation));
144 private Item stringItemWithState(String itemName, String value) {
145 StringItem item = new StringItem(itemName);
146 item.setState(new StringType(value));
151 public void testMultipleCondition_AllMatch() throws ItemNotFoundException {
152 when(mockContext.getConfiguration())
153 .thenReturn(new Configuration(Map.of("conditions", "ItemName eq Value, ItemName2 eq Value2")));
154 when(mockItemRegistry.getItem("ItemName")).thenReturn(stringItemWithState("ItemName", "Value"));
155 when(mockItemRegistry.getItem("ItemName2")).thenReturn(stringItemWithState("ItemName2", "Value2"));
157 StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);
159 State expectation = new StringType("NewValue");
160 profile.onStateUpdateFromHandler(expectation);
161 verify(mockCallback, times(1)).sendUpdate(eq(expectation));
165 public void testMultipleCondition_SingleMatch() throws ItemNotFoundException {
166 when(mockContext.getConfiguration())
167 .thenReturn(new Configuration(Map.of("conditions", "ItemName eq Value, ItemName2 eq Value2")));
168 when(mockItemRegistry.getItem("ItemName")).thenReturn(stringItemWithState("ItemName", "Value"));
169 when(mockItemRegistry.getItem("ItemName2")).thenThrow(ItemNotFoundException.class);
171 StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);
173 State expectation = new StringType("NewValue");
174 profile.onStateUpdateFromHandler(expectation);
175 verify(mockCallback, times(0)).sendUpdate(eq(expectation));
179 public void testFailingConditionWithMismatchState() throws ItemNotFoundException {
180 when(mockContext.getConfiguration())
181 .thenReturn(new Configuration(Map.of("conditions", "ItemName eq Value", "mismatchState", "UNDEF")));
182 when(mockContext.getAcceptedDataTypes()).thenReturn(List.of(UnDefType.class, StringType.class));
183 when(mockItemRegistry.getItem("ItemName")).thenReturn(stringItemWithState("ItemName", "Mismatch"));
185 StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);
187 profile.onStateUpdateFromHandler(new StringType("ToBeDiscarded"));
188 verify(mockCallback, times(1)).sendUpdate(eq(UnDefType.UNDEF));
192 public void testFailingConditionWithMismatchStateQuoted() throws ItemNotFoundException {
193 when(mockContext.getConfiguration())
194 .thenReturn(new Configuration(Map.of("conditions", "ItemName eq Value", "mismatchState", "'UNDEF'")));
195 when(mockContext.getAcceptedDataTypes()).thenReturn(List.of(UnDefType.class, StringType.class));
196 when(mockItemRegistry.getItem("ItemName")).thenReturn(stringItemWithState("ItemName", "Mismatch"));
198 StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);
200 profile.onStateUpdateFromHandler(new StringType("ToBeDiscarded"));
201 verify(mockCallback, times(1)).sendUpdate(eq(new StringType("UNDEF")));
205 void testParseStateNonQuotes() {
206 when(mockContext.getAcceptedDataTypes())
207 .thenReturn(List.of(UnDefType.class, OnOffType.class, StringType.class));
208 when(mockContext.getConfiguration()).thenReturn(new Configuration(Map.of("conditions", "")));
210 StateFilterProfile profile = new StateFilterProfile(mockCallback, mockContext, mockItemRegistry);
211 assertEquals(UnDefType.UNDEF, profile.parseState("UNDEF"));
212 assertEquals(new StringType("UNDEF"), profile.parseState("'UNDEF'"));
213 assertEquals(OnOffType.ON, profile.parseState("ON"));
214 assertEquals(new StringType("ON"), profile.parseState("'ON'"));