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.binding.snmp.internal;
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;
20 import java.io.IOException;
21 import java.util.Collections;
22 import java.util.HashMap;
24 import java.util.Vector;
26 import org.junit.jupiter.api.AfterEach;
27 import org.mockito.ArgumentCaptor;
28 import org.mockito.Mock;
29 import org.mockito.MockitoAnnotations;
30 import org.openhab.core.config.core.Configuration;
31 import org.openhab.core.library.types.StringType;
32 import org.openhab.core.test.java.JavaTest;
33 import org.openhab.core.thing.Channel;
34 import org.openhab.core.thing.ChannelUID;
35 import org.openhab.core.thing.Thing;
36 import org.openhab.core.thing.ThingStatus;
37 import org.openhab.core.thing.ThingUID;
38 import org.openhab.core.thing.binding.ThingHandlerCallback;
39 import org.openhab.core.thing.binding.builder.ChannelBuilder;
40 import org.openhab.core.thing.binding.builder.ThingBuilder;
41 import org.openhab.core.thing.type.ChannelTypeUID;
42 import org.openhab.core.types.Command;
43 import org.openhab.core.types.State;
44 import org.snmp4j.PDU;
45 import org.snmp4j.event.ResponseEvent;
46 import org.snmp4j.smi.OID;
47 import org.snmp4j.smi.OctetString;
48 import org.snmp4j.smi.Variable;
49 import org.snmp4j.smi.VariableBinding;
52 * Tests cases for {@link SnmpTargetHandler}.
54 * @author Jan N. Klug - Initial contribution
56 public abstract class AbstractSnmpTargetHandlerTest extends JavaTest {
57 protected static final ThingUID THING_UID = new ThingUID(THING_TYPE_TARGET, "testthing");
58 protected static final ChannelUID CHANNEL_UID = new ChannelUID(THING_UID, "testchannel");
59 protected static final String TEST_OID = "1.2.3.4";
60 protected static final String TEST_ADDRESS = "192.168.0.1";
61 protected static final String TEST_STRING = "foo.";
63 protected @Mock SnmpServiceImpl snmpService;
64 protected @Mock ThingHandlerCallback thingHandlerCallback;
66 protected Thing thing;
67 protected SnmpTargetHandler thingHandler;
68 private AutoCloseable mocks;
71 public void after() throws Exception {
75 protected VariableBinding handleCommandSwitchChannel(SnmpDatatype datatype, Command command, String onValue,
76 String offValue, boolean refresh) throws IOException {
77 setup(SnmpBindingConstants.CHANNEL_TYPE_UID_SWITCH, SnmpChannelMode.WRITE, datatype, onValue, offValue);
78 thingHandler.handleCommand(CHANNEL_UID, command);
81 ArgumentCaptor<PDU> pduCaptor = ArgumentCaptor.forClass(PDU.class);
82 verify(snmpService, times(1)).send(pduCaptor.capture(), any(), eq(null), eq(thingHandler));
83 return pduCaptor.getValue().getVariableBindings().stream().findFirst().orElse(null);
85 verify(snmpService, never()).send(any(), any(), eq(null), eq(thingHandler));
90 protected VariableBinding handleCommandNumberStringChannel(ChannelTypeUID channelTypeUID, SnmpDatatype datatype,
91 Command command, boolean refresh) throws IOException {
92 setup(channelTypeUID, SnmpChannelMode.WRITE, datatype);
93 thingHandler.handleCommand(CHANNEL_UID, command);
96 ArgumentCaptor<PDU> pduCaptor = ArgumentCaptor.forClass(PDU.class);
97 verify(snmpService, times(1)).send(pduCaptor.capture(), any(), eq(null), eq(thingHandler));
98 return pduCaptor.getValue().getVariableBindings().stream().findFirst().orElse(null);
100 verify(snmpService, never()).send(any(), any(), eq(null), eq(thingHandler));
105 protected void onResponseNumberStringChannel(SnmpChannelMode channelMode, boolean refresh) {
106 setup(SnmpBindingConstants.CHANNEL_TYPE_UID_STRING, channelMode);
108 PDU responsePDU = new PDU(PDU.RESPONSE,
109 Collections.singletonList(new VariableBinding(new OID(TEST_OID), new OctetString(TEST_STRING))));
110 ResponseEvent event = new ResponseEvent("test", null, null, responsePDU, null);
112 thingHandler.onResponse(event);
115 verify(thingHandlerCallback, atLeast(1)).stateUpdated(eq(CHANNEL_UID), eq(new StringType(TEST_STRING)));
117 verify(thingHandlerCallback, never()).stateUpdated(any(), any());
121 protected State onResponseSwitchChannel(SnmpChannelMode channelMode, SnmpDatatype datatype, String onValue,
122 String offValue, Variable value, boolean refresh) {
123 setup(SnmpBindingConstants.CHANNEL_TYPE_UID_SWITCH, channelMode, datatype, onValue, offValue);
125 PDU responsePDU = new PDU(PDU.RESPONSE,
126 Collections.singletonList(new VariableBinding(new OID(TEST_OID), value)));
127 ResponseEvent event = new ResponseEvent("test", null, null, responsePDU, null);
129 thingHandler.onResponse(event);
132 ArgumentCaptor<State> stateCaptor = ArgumentCaptor.forClass(State.class);
133 verify(thingHandlerCallback, atLeast(1)).stateUpdated(eq(CHANNEL_UID), stateCaptor.capture());
134 return stateCaptor.getValue();
136 verify(thingHandlerCallback, never()).stateUpdated(any(), any());
141 protected void refresh(SnmpChannelMode channelMode, boolean refresh) throws IOException {
142 setup(SnmpBindingConstants.CHANNEL_TYPE_UID_STRING, channelMode);
144 verifyStatus(ThingStatus.UNKNOWN);
145 verify(snmpService).addCommandResponder(any());
148 ArgumentCaptor<PDU> pduCaptor = ArgumentCaptor.forClass(PDU.class);
149 verify(snmpService, timeout(500).atLeast(1)).send(pduCaptor.capture(), any(), eq(null), eq(thingHandler));
150 Vector<? extends VariableBinding> variables = pduCaptor.getValue().getVariableBindings();
151 assertTrue(variables.stream().filter(v -> v.getOid().toDottedString().equals(TEST_OID)).findFirst()
154 verify(snmpService, never()).send(any(), any(), eq(null), eq(thingHandler));
158 protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode) {
159 setup(channelTypeUID, channelMode, null);
162 protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode, SnmpDatatype datatype) {
163 setup(channelTypeUID, channelMode, datatype, null, null);
166 protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode, SnmpDatatype datatype,
167 String onValue, String offValue) {
168 setup(channelTypeUID, channelMode, datatype, onValue, offValue, null);
171 protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode, SnmpDatatype datatype,
172 String onValue, String offValue, String exceptionValue) {
173 setup(channelTypeUID, channelMode, datatype, onValue, offValue, exceptionValue, null);
176 protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode, SnmpDatatype datatype,
177 String onValue, String offValue, String exceptionValue, String unit) {
178 Map<String, Object> channelConfig = new HashMap<>();
179 Map<String, Object> thingConfig = new HashMap<>();
180 mocks = MockitoAnnotations.openMocks(this);
182 thingConfig.put("hostname", "localhost");
184 ThingBuilder thingBuilder = ThingBuilder.create(THING_TYPE_TARGET, THING_UID).withLabel("Test thing")
185 .withConfiguration(new Configuration(thingConfig));
187 if (channelTypeUID != null && channelMode != null) {
188 String itemType = SnmpBindingConstants.CHANNEL_TYPE_UID_NUMBER.equals(channelTypeUID) ? "Number" : "String";
189 channelConfig.put("oid", TEST_OID);
190 channelConfig.put("mode", channelMode.name());
191 if (datatype != null) {
192 channelConfig.put("datatype", datatype.name());
194 if (onValue != null) {
195 channelConfig.put("onvalue", onValue);
197 if (offValue != null) {
198 channelConfig.put("offvalue", offValue);
200 if (exceptionValue != null) {
201 channelConfig.put("exceptionValue", exceptionValue);
204 channelConfig.put("unit", unit);
206 Channel channel = ChannelBuilder.create(CHANNEL_UID, itemType).withType(channelTypeUID)
207 .withConfiguration(new Configuration(channelConfig)).build();
208 thingBuilder.withChannel(channel);
211 thing = thingBuilder.build();
212 thingHandler = new SnmpTargetHandler(thing, snmpService);
214 thingHandler.getThing().setHandler(thingHandler);
215 thingHandler.setCallback(thingHandlerCallback);
218 ((Thing) answer.getArgument(0)).setStatusInfo(answer.getArgument(1));
220 }).when(thingHandlerCallback).statusUpdated(any(), any());
222 thingHandler.initialize();
224 verifyStatus(ThingStatus.UNKNOWN);
227 protected void verifyStatus(ThingStatus status) {
228 waitForAssert(() -> assertEquals(status, thingHandler.getThing().getStatusInfo().getStatus()));