]> git.basschouten.com Git - openhab-addons.git/blob
ac46fd4320309d36cefdf6efce719c1b76d04eac
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.snmp.internal;
14
15 import static org.junit.jupiter.api.Assertions.*;
16 import static org.mockito.ArgumentMatchers.*;
17 import static org.mockito.Mockito.*;
18 import static org.openhab.binding.snmp.internal.SnmpBindingConstants.THING_TYPE_TARGET;
19
20 import java.io.IOException;
21 import java.util.Collections;
22 import java.util.HashMap;
23 import java.util.Map;
24 import java.util.Vector;
25
26 import org.eclipse.jdt.annotation.NonNullByDefault;
27 import org.eclipse.jdt.annotation.Nullable;
28 import org.junit.jupiter.api.AfterEach;
29 import org.mockito.ArgumentCaptor;
30 import org.mockito.Mock;
31 import org.mockito.MockitoAnnotations;
32 import org.openhab.binding.snmp.internal.types.SnmpChannelMode;
33 import org.openhab.binding.snmp.internal.types.SnmpDatatype;
34 import org.openhab.core.config.core.Configuration;
35 import org.openhab.core.library.types.StringType;
36 import org.openhab.core.test.java.JavaTest;
37 import org.openhab.core.thing.Channel;
38 import org.openhab.core.thing.ChannelUID;
39 import org.openhab.core.thing.Thing;
40 import org.openhab.core.thing.ThingStatus;
41 import org.openhab.core.thing.ThingUID;
42 import org.openhab.core.thing.binding.ThingHandlerCallback;
43 import org.openhab.core.thing.binding.builder.ChannelBuilder;
44 import org.openhab.core.thing.binding.builder.ThingBuilder;
45 import org.openhab.core.thing.type.ChannelTypeUID;
46 import org.openhab.core.types.Command;
47 import org.openhab.core.types.State;
48 import org.snmp4j.PDU;
49 import org.snmp4j.event.ResponseEvent;
50 import org.snmp4j.smi.OID;
51 import org.snmp4j.smi.OctetString;
52 import org.snmp4j.smi.Variable;
53 import org.snmp4j.smi.VariableBinding;
54
55 /**
56  * Tests cases for {@link SnmpTargetHandler}.
57  *
58  * @author Jan N. Klug - Initial contribution
59  */
60 @NonNullByDefault
61 public abstract class AbstractSnmpTargetHandlerTest extends JavaTest {
62     protected static final ThingUID THING_UID = new ThingUID(THING_TYPE_TARGET, "testthing");
63     protected static final ChannelUID CHANNEL_UID = new ChannelUID(THING_UID, "testchannel");
64     protected static final String TEST_OID = "1.2.3.4";
65     protected static final String TEST_ADDRESS = "192.168.0.1";
66     protected static final String TEST_STRING = "foo.";
67
68     protected @Mock @NonNullByDefault({}) SnmpServiceImpl snmpService;
69     protected @Mock @NonNullByDefault({}) ThingHandlerCallback thingHandlerCallback;
70
71     protected @NonNullByDefault({}) Thing thing;
72     protected @NonNullByDefault({}) SnmpTargetHandler thingHandler;
73     private @NonNullByDefault({}) AutoCloseable mocks;
74
75     @AfterEach
76     public void after() throws Exception {
77         mocks.close();
78     }
79
80     protected @Nullable VariableBinding handleCommandSwitchChannel(SnmpDatatype datatype, Command command,
81             String onValue, @Nullable String offValue, boolean refresh) throws IOException {
82         setup(SnmpBindingConstants.CHANNEL_TYPE_UID_SWITCH, SnmpChannelMode.WRITE, datatype, onValue, offValue);
83         thingHandler.handleCommand(CHANNEL_UID, command);
84
85         if (refresh) {
86             ArgumentCaptor<PDU> pduCaptor = ArgumentCaptor.forClass(PDU.class);
87             verify(snmpService, times(1)).send(pduCaptor.capture(), any(), eq(null), eq(thingHandler));
88             return pduCaptor.getValue().getVariableBindings().stream().findFirst().orElse(null);
89         } else {
90             verify(snmpService, never()).send(any(), any(), eq(null), eq(thingHandler));
91             return null;
92         }
93     }
94
95     protected @Nullable VariableBinding handleCommandNumberStringChannel(ChannelTypeUID channelTypeUID,
96             SnmpDatatype datatype, Command command, boolean refresh) throws IOException {
97         return handleCommandNumberStringChannel(channelTypeUID, datatype, null, command, refresh);
98     }
99
100     protected @Nullable VariableBinding handleCommandNumberStringChannel(ChannelTypeUID channelTypeUID,
101             SnmpDatatype datatype, @Nullable String unit, Command command, boolean refresh) throws IOException {
102         setup(channelTypeUID, SnmpChannelMode.WRITE, datatype, null, null, null, unit);
103         thingHandler.handleCommand(CHANNEL_UID, command);
104
105         if (refresh) {
106             ArgumentCaptor<PDU> pduCaptor = ArgumentCaptor.forClass(PDU.class);
107             verify(snmpService, times(1)).send(pduCaptor.capture(), any(), eq(null), eq(thingHandler));
108             return pduCaptor.getValue().getVariableBindings().stream().findFirst().orElse(null);
109         } else {
110             verify(snmpService, never()).send(any(), any(), eq(null), eq(thingHandler));
111             return null;
112         }
113     }
114
115     protected void onResponseNumberStringChannel(SnmpChannelMode channelMode, boolean refresh) {
116         setup(SnmpBindingConstants.CHANNEL_TYPE_UID_STRING, channelMode);
117
118         PDU responsePDU = new PDU(PDU.RESPONSE,
119                 Collections.singletonList(new VariableBinding(new OID(TEST_OID), new OctetString(TEST_STRING))));
120         ResponseEvent event = new ResponseEvent("test", null, null, responsePDU, null);
121
122         thingHandler.onResponse(event);
123
124         if (refresh) {
125             verify(thingHandlerCallback, atLeast(1)).stateUpdated(eq(CHANNEL_UID), eq(new StringType(TEST_STRING)));
126         } else {
127             verify(thingHandlerCallback, never()).stateUpdated(any(), any());
128         }
129     }
130
131     protected @Nullable State onResponseSwitchChannel(SnmpChannelMode channelMode, SnmpDatatype datatype,
132             String onValue, String offValue, Variable value, boolean refresh) {
133         setup(SnmpBindingConstants.CHANNEL_TYPE_UID_SWITCH, channelMode, datatype, onValue, offValue);
134
135         PDU responsePDU = new PDU(PDU.RESPONSE,
136                 Collections.singletonList(new VariableBinding(new OID(TEST_OID), value)));
137         ResponseEvent event = new ResponseEvent("test", null, null, responsePDU, null);
138
139         thingHandler.onResponse(event);
140
141         if (refresh) {
142             ArgumentCaptor<State> stateCaptor = ArgumentCaptor.forClass(State.class);
143             verify(thingHandlerCallback, atLeast(1)).stateUpdated(eq(CHANNEL_UID), stateCaptor.capture());
144             return stateCaptor.getValue();
145         } else {
146             verify(thingHandlerCallback, never()).stateUpdated(any(), any());
147             return null;
148         }
149     }
150
151     protected void refresh(SnmpChannelMode channelMode, boolean refresh) throws IOException {
152         setup(SnmpBindingConstants.CHANNEL_TYPE_UID_STRING, channelMode);
153
154         verifyStatus(ThingStatus.UNKNOWN);
155         verify(snmpService).addCommandResponder(any());
156
157         if (refresh) {
158             ArgumentCaptor<PDU> pduCaptor = ArgumentCaptor.forClass(PDU.class);
159             verify(snmpService, timeout(500).atLeast(1)).send(pduCaptor.capture(), any(), eq(null), eq(thingHandler));
160             Vector<? extends VariableBinding> variables = pduCaptor.getValue().getVariableBindings();
161             assertTrue(variables.stream().filter(v -> v.getOid().toDottedString().equals(TEST_OID)).findFirst()
162                     .isPresent());
163         } else {
164             verify(snmpService, never()).send(any(), any(), eq(null), eq(thingHandler));
165         }
166     }
167
168     protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode) {
169         setup(channelTypeUID, channelMode, null);
170     }
171
172     protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode, @Nullable SnmpDatatype datatype) {
173         setup(channelTypeUID, channelMode, datatype, null, null);
174     }
175
176     protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode, @Nullable SnmpDatatype datatype,
177             @Nullable String onValue, @Nullable String offValue) {
178         setup(channelTypeUID, channelMode, datatype, onValue, offValue, null);
179     }
180
181     protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode, @Nullable SnmpDatatype datatype,
182             @Nullable String onValue, @Nullable String offValue, @Nullable String exceptionValue) {
183         setup(channelTypeUID, channelMode, datatype, onValue, offValue, exceptionValue, null);
184     }
185
186     protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode, @Nullable SnmpDatatype datatype,
187             @Nullable String onValue, @Nullable String offValue, @Nullable String exceptionValue,
188             @Nullable String unit) {
189         Map<String, Object> channelConfig = new HashMap<>();
190         Map<String, Object> thingConfig = new HashMap<>();
191         mocks = MockitoAnnotations.openMocks(this);
192
193         thingConfig.put("hostname", "localhost");
194
195         ThingBuilder thingBuilder = ThingBuilder.create(THING_TYPE_TARGET, THING_UID).withLabel("Test thing")
196                 .withConfiguration(new Configuration(thingConfig));
197
198         String itemType = SnmpBindingConstants.CHANNEL_TYPE_UID_NUMBER.equals(channelTypeUID) ? "Number" : "String";
199         channelConfig.put("oid", TEST_OID);
200         channelConfig.put("mode", channelMode.name());
201         if (datatype != null) {
202             channelConfig.put("datatype", datatype.name());
203         }
204         if (onValue != null) {
205             channelConfig.put("onvalue", onValue);
206         }
207         if (offValue != null) {
208             channelConfig.put("offvalue", offValue);
209         }
210         if (exceptionValue != null) {
211             channelConfig.put("exceptionValue", exceptionValue);
212         }
213         if (unit != null) {
214             channelConfig.put("unit", unit);
215         }
216         Channel channel = ChannelBuilder.create(CHANNEL_UID, itemType).withType(channelTypeUID)
217                 .withConfiguration(new Configuration(channelConfig)).build();
218         thingBuilder.withChannel(channel);
219
220         thing = thingBuilder.build();
221         thingHandler = new SnmpTargetHandler(thing, snmpService);
222
223         thingHandler.getThing().setHandler(thingHandler);
224         thingHandler.setCallback(thingHandlerCallback);
225
226         doAnswer(answer -> {
227             ((Thing) answer.getArgument(0)).setStatusInfo(answer.getArgument(1));
228             return null;
229         }).when(thingHandlerCallback).statusUpdated(any(), any());
230
231         thingHandler.initialize();
232
233         verifyStatus(ThingStatus.UNKNOWN);
234     }
235
236     protected void verifyStatus(ThingStatus status) {
237         waitForAssert(() -> assertEquals(status, thingHandler.getThing().getStatusInfo().getStatus()));
238     }
239 }