]> git.basschouten.com Git - openhab-addons.git/blob
e0198a3f8d9ef395cb255ef09841f39411ac0a01
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.modbus.tests;
14
15 import static org.hamcrest.CoreMatchers.*;
16 import static org.hamcrest.MatcherAssert.assertThat;
17 import static org.hamcrest.core.Is.is;
18 import static org.hamcrest.core.IsInstanceOf.instanceOf;
19 import static org.junit.jupiter.api.Assertions.*;
20 import static org.mockito.ArgumentMatchers.any;
21 import static org.mockito.Mockito.*;
22
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.Dictionary;
26 import java.util.HashMap;
27 import java.util.HashSet;
28 import java.util.Hashtable;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32
33 import org.eclipse.jdt.annotation.NonNull;
34 import org.eclipse.jdt.annotation.NonNullByDefault;
35 import org.eclipse.jdt.annotation.Nullable;
36 import org.junit.jupiter.api.AfterEach;
37 import org.junit.jupiter.api.BeforeEach;
38 import org.junit.jupiter.api.extension.ExtendWith;
39 import org.mockito.Mock;
40 import org.mockito.Mockito;
41 import org.mockito.junit.jupiter.MockitoExtension;
42 import org.mockito.junit.jupiter.MockitoSettings;
43 import org.mockito.quality.Strictness;
44 import org.openhab.binding.modbus.internal.ModbusHandlerFactory;
45 import org.openhab.core.events.Event;
46 import org.openhab.core.events.EventFilter;
47 import org.openhab.core.events.EventSubscriber;
48 import org.openhab.core.io.transport.modbus.ModbusCommunicationInterface;
49 import org.openhab.core.io.transport.modbus.ModbusManager;
50 import org.openhab.core.items.Item;
51 import org.openhab.core.items.ItemProvider;
52 import org.openhab.core.items.ItemRegistry;
53 import org.openhab.core.items.ManagedItemProvider;
54 import org.openhab.core.items.events.ItemStateEvent;
55 import org.openhab.core.library.CoreItemFactory;
56 import org.openhab.core.test.java.JavaOSGiTest;
57 import org.openhab.core.thing.ChannelUID;
58 import org.openhab.core.thing.ManagedThingProvider;
59 import org.openhab.core.thing.Thing;
60 import org.openhab.core.thing.ThingProvider;
61 import org.openhab.core.thing.binding.ThingHandler;
62 import org.openhab.core.thing.binding.ThingHandlerFactory;
63 import org.openhab.core.thing.link.ItemChannelLink;
64 import org.openhab.core.thing.link.ItemChannelLinkProvider;
65 import org.openhab.core.thing.link.ManagedItemChannelLinkProvider;
66 import org.openhab.core.transform.TransformationService;
67 import org.openhab.core.types.State;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71 /**
72  * @author Sami Salonen - Initial contribution
73  */
74 @ExtendWith(MockitoExtension.class)
75 @MockitoSettings(strictness = Strictness.WARN)
76 @NonNullByDefault
77 public abstract class AbstractModbusOSGiTest extends JavaOSGiTest {
78
79     private static class StateSubscriber implements EventSubscriber {
80
81         private final Logger logger = LoggerFactory.getLogger(StateSubscriber.class);
82
83         public Map<String, List<State>> stateUpdates = new HashMap<>();
84
85         @Override
86         public Set<@NonNull String> getSubscribedEventTypes() {
87             return Collections.singleton(ItemStateEvent.TYPE);
88         }
89
90         @Override
91         public @Nullable EventFilter getEventFilter() {
92             return null;
93         }
94
95         @Override
96         public void receive(Event event) {
97             // Expecting only state updates in the tests
98             assertThat(event, is(instanceOf(ItemStateEvent.class)));
99             ItemStateEvent stateEvent = (ItemStateEvent) event;
100             logger.trace("Captured event: {} of type {}. Payload: {}", event,
101                     stateEvent.getItemState().getClass().getSimpleName(), event.getPayload());
102             stateUpdates.computeIfAbsent(stateEvent.getItemName(), (item) -> new ArrayList<>())
103                     .add(stateEvent.getItemState());
104         }
105     }
106
107     private final Logger logger = LoggerFactory.getLogger(AbstractModbusOSGiTest.class);
108
109     protected @Mock @NonNullByDefault({}) ModbusManager mockedModbusManager;
110     protected @NonNullByDefault({}) ModbusManager realModbusManager;
111     protected @NonNullByDefault({}) ManagedThingProvider thingProvider;
112     protected @NonNullByDefault({}) ManagedItemProvider itemProvider;
113     protected @NonNullByDefault({}) ManagedItemChannelLinkProvider itemChannelLinkProvider;
114     protected @NonNullByDefault({}) ItemRegistry itemRegistry;
115     protected @NonNullByDefault({}) CoreItemFactory coreItemFactory;
116
117     private Set<Item> addedItems = new HashSet<>();
118     private Set<Thing> addedThings = new HashSet<>();
119     private Set<ItemChannelLink> addedLinks = new HashSet<>();
120     private StateSubscriber stateSubscriber = new StateSubscriber();
121
122     protected @Mock @NonNullByDefault({}) ModbusCommunicationInterface comms;
123
124     public AbstractModbusOSGiTest() {
125         super();
126     }
127
128     /**
129      * Before each test, configure mocked services
130      */
131     @BeforeEach
132     public void setUpAbstractModbusOSGiTest() {
133         logger.debug("setUpAbstractModbusOSGiTest BEGIN");
134         registerVolatileStorageService();
135         registerService(mockedModbusManager);
136         registerService(stateSubscriber);
137
138         swapModbusManagerToMocked();
139
140         thingProvider = getService(ThingProvider.class, ManagedThingProvider.class);
141         assertThat("Could not get ManagedThingProvider", thingProvider, is(notNullValue()));
142         itemProvider = getService(ItemProvider.class, ManagedItemProvider.class);
143         assertThat("Could not get ManagedItemProvider", itemProvider, is(notNullValue()));
144         itemChannelLinkProvider = getService(ItemChannelLinkProvider.class, ManagedItemChannelLinkProvider.class);
145         assertThat("Could not get ManagedItemChannelLinkProvider", itemChannelLinkProvider, is(notNullValue()));
146         itemRegistry = getService(ItemRegistry.class);
147         assertThat("Could not get ItemRegistry", itemRegistry, is(notNullValue()));
148
149         coreItemFactory = new CoreItemFactory();
150
151         // Clean slate for all tests
152         reset(mockedModbusManager);
153
154         stateSubscriber.stateUpdates.clear();
155         logger.debug("setUpAbstractModbusOSGiTest END");
156     }
157
158     @AfterEach
159     public void tearDownAbstractModbusOSGiTest() throws Exception {
160         logger.debug("tearDownAbstractModbusOSGiTest BEGIN");
161         swapModbusManagerToReal();
162         for (Item item : addedItems) {
163             assertNotNull(itemProvider.remove(item.getName()));
164         }
165         for (Thing thing : addedThings) {
166             disposeThing(thing);
167         }
168         for (ItemChannelLink link : addedLinks) {
169             logger.debug("Unlinking {} <-> {}", link.getItemName(), link.getLinkedUID());
170             assertNotNull(itemChannelLinkProvider.remove(link.getUID()));
171         }
172         logger.debug("tearDownAbstractModbusOSGiTest END");
173     }
174
175     protected void addThing(Thing thing) {
176         assertThat(addedThings.contains(thing), not(equalTo(true)));
177         ThingHandler mockHandler = thing.getHandler();
178         if (mockHandler != null) {
179             // If there is a handler attached to fresh thing, it should be mocked (this pattern is used with some tests)
180             assertThat(Mockito.mockingDetails(thing.getHandler()).isMock(), is(equalTo(true)));
181         }
182
183         thingProvider.add(thing);
184         waitForAssert(() -> assertThat(thing.getHandler(), notNullValue()));
185         assertThat(thing.getConfiguration(), is(notNullValue()));
186         addedThings.add(thing);
187         if (mockHandler != null) {
188             // Re-attach mock handler
189             ThingHandler realHandlerInitedByCore = thing.getHandler();
190             assertNotNull(realHandlerInitedByCore);
191             assertNotSame(realHandlerInitedByCore, mockHandler);
192             realHandlerInitedByCore.dispose();
193             thing.setHandler(mockHandler);
194         }
195     }
196
197     protected void disposeThing(Thing thing) {
198         thingProvider.remove(thing.getUID());
199     }
200
201     protected void addItem(Item item) {
202         assertThat(addedItems.contains(item), not(equalTo(true)));
203         itemProvider.add(item);
204         addedItems.add(item);
205     }
206
207     protected void linkItem(String itemName, ChannelUID channelUID) {
208         logger.debug("Linking {} <-> {}", itemName, channelUID);
209         ItemChannelLink link = new ItemChannelLink(itemName, channelUID);
210         assertThat(addedLinks.contains(link), not(equalTo(true)));
211         itemChannelLinkProvider.add(link);
212         addedLinks.add(link);
213     }
214
215     protected @Nullable List<State> getStateUpdates(String itemName) {
216         return stateSubscriber.stateUpdates.get(itemName);
217     }
218
219     protected void mockTransformation(String name, TransformationService service) {
220         Dictionary<String, Object> params = new Hashtable<>();
221         params.put("openhab.transform", name);
222         registerService(service, params);
223     }
224
225     protected void mockCommsToModbusManager() {
226         assert comms != null;
227         doReturn(comms).when(mockedModbusManager).newModbusCommunicationInterface(any(), any());
228     }
229
230     protected void swapModbusManagerToMocked() {
231         assertNull(realModbusManager);
232         realModbusManager = getService(ModbusManager.class);
233         assertThat("Could not get ModbusManager", realModbusManager, is(notNullValue()));
234         assertThat("Could not get ModbusManagerImpl", realModbusManager.getClass().getSimpleName(),
235                 is(equalTo("ModbusManagerImpl")));
236         assertNotNull(realModbusManager);
237
238         ModbusHandlerFactory modbusHandlerFactory = getService(ThingHandlerFactory.class, ModbusHandlerFactory.class);
239         assertThat("Could not get ModbusHandlerFactory", modbusHandlerFactory, is(notNullValue()));
240         assertNotNull(modbusHandlerFactory);
241         modbusHandlerFactory.unsetModbusManager(realModbusManager);
242         modbusHandlerFactory.setModbusManager(mockedModbusManager);
243     }
244
245     protected void swapModbusManagerToReal() {
246         assertNotNull(realModbusManager);
247         ModbusHandlerFactory modbusHandlerFactory = getService(ThingHandlerFactory.class, ModbusHandlerFactory.class);
248         assertThat("Could not get ModbusHandlerFactory", modbusHandlerFactory, is(notNullValue()));
249         assertNotNull(modbusHandlerFactory);
250         modbusHandlerFactory.unsetModbusManager(mockedModbusManager);
251         modbusHandlerFactory.setModbusManager(realModbusManager);
252     }
253 }