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