]> git.basschouten.com Git - openhab-addons.git/blob
e6de64a6318874da758fb658bccd5c4a822012cb
[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.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;
50
51 /**
52  * Tests cases for {@link SnmpTargetHandler}.
53  *
54  * @author Jan N. Klug - Initial contribution
55  */
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.";
62
63     protected @Mock SnmpServiceImpl snmpService;
64     protected @Mock ThingHandlerCallback thingHandlerCallback;
65
66     protected Thing thing;
67     protected SnmpTargetHandler thingHandler;
68     private AutoCloseable mocks;
69
70     @AfterEach
71     public void after() throws Exception {
72         mocks.close();
73     }
74
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);
79
80         if (refresh) {
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);
84         } else {
85             verify(snmpService, never()).send(any(), any(), eq(null), eq(thingHandler));
86             return null;
87         }
88     }
89
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);
94
95         if (refresh) {
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);
99         } else {
100             verify(snmpService, never()).send(any(), any(), eq(null), eq(thingHandler));
101             return null;
102         }
103     }
104
105     protected void onResponseNumberStringChannel(SnmpChannelMode channelMode, boolean refresh) {
106         setup(SnmpBindingConstants.CHANNEL_TYPE_UID_STRING, channelMode);
107
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);
111
112         thingHandler.onResponse(event);
113
114         if (refresh) {
115             verify(thingHandlerCallback, atLeast(1)).stateUpdated(eq(CHANNEL_UID), eq(new StringType(TEST_STRING)));
116         } else {
117             verify(thingHandlerCallback, never()).stateUpdated(any(), any());
118         }
119     }
120
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);
124
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);
128
129         thingHandler.onResponse(event);
130
131         if (refresh) {
132             ArgumentCaptor<State> stateCaptor = ArgumentCaptor.forClass(State.class);
133             verify(thingHandlerCallback, atLeast(1)).stateUpdated(eq(CHANNEL_UID), stateCaptor.capture());
134             return stateCaptor.getValue();
135         } else {
136             verify(thingHandlerCallback, never()).stateUpdated(any(), any());
137             return null;
138         }
139     }
140
141     protected void refresh(SnmpChannelMode channelMode, boolean refresh) throws IOException {
142         setup(SnmpBindingConstants.CHANNEL_TYPE_UID_STRING, channelMode);
143
144         verifyStatus(ThingStatus.UNKNOWN);
145         verify(snmpService).addCommandResponder(any());
146
147         if (refresh) {
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()
152                     .isPresent());
153         } else {
154             verify(snmpService, never()).send(any(), any(), eq(null), eq(thingHandler));
155         }
156     }
157
158     protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode) {
159         setup(channelTypeUID, channelMode, null);
160     }
161
162     protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode, SnmpDatatype datatype) {
163         setup(channelTypeUID, channelMode, datatype, null, null);
164     }
165
166     protected void setup(ChannelTypeUID channelTypeUID, SnmpChannelMode channelMode, SnmpDatatype datatype,
167             String onValue, String offValue) {
168         setup(channelTypeUID, channelMode, datatype, onValue, offValue, null);
169     }
170
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);
174     }
175
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);
181
182         thingConfig.put("hostname", "localhost");
183
184         ThingBuilder thingBuilder = ThingBuilder.create(THING_TYPE_TARGET, THING_UID).withLabel("Test thing")
185                 .withConfiguration(new Configuration(thingConfig));
186
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());
193             }
194             if (onValue != null) {
195                 channelConfig.put("onvalue", onValue);
196             }
197             if (offValue != null) {
198                 channelConfig.put("offvalue", offValue);
199             }
200             if (exceptionValue != null) {
201                 channelConfig.put("exceptionValue", exceptionValue);
202             }
203             if (unit != null) {
204                 channelConfig.put("unit", unit);
205             }
206             Channel channel = ChannelBuilder.create(CHANNEL_UID, itemType).withType(channelTypeUID)
207                     .withConfiguration(new Configuration(channelConfig)).build();
208             thingBuilder.withChannel(channel);
209         }
210
211         thing = thingBuilder.build();
212         thingHandler = new SnmpTargetHandler(thing, snmpService);
213
214         thingHandler.getThing().setHandler(thingHandler);
215         thingHandler.setCallback(thingHandlerCallback);
216
217         doAnswer(answer -> {
218             ((Thing) answer.getArgument(0)).setStatusInfo(answer.getArgument(1));
219             return null;
220         }).when(thingHandlerCallback).statusUpdated(any(), any());
221
222         thingHandler.initialize();
223
224         verifyStatus(ThingStatus.UNKNOWN);
225     }
226
227     protected void verifyStatus(ThingStatus status) {
228         waitForAssert(() -> assertEquals(status, thingHandler.getThing().getStatusInfo().getStatus()));
229     }
230 }