Skip to content

Commit

Permalink
Snnmp: reworked tests to avoid flaky failures
Browse files Browse the repository at this point in the history
  • Loading branch information
JiriOndrusek committed May 3, 2023
1 parent 38f4e54 commit 2959806
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
Expand All @@ -47,8 +46,6 @@
@ApplicationScoped
public class SnmpResource {

public static OID TRAP_OID = new OID("1.2.3.4.5");

@ConfigProperty(name = SnmpRoute.TRAP_V0_PORT)
int trap0Port;

Expand All @@ -66,14 +63,13 @@ public class SnmpResource {
ProducerTemplate producerTemplate;

@Path("/producePDU/{version}")
@GET
@POST
@Produces(MediaType.TEXT_PLAIN)
public Response producePDU(@PathParam("version") int version) {
public Response producePDU(@PathParam("version") int version, String payload) {
String url = String.format("snmp://%s?retries=1&snmpVersion=%d", snmpListenAddress, version);
SnmpMessage pdu = producerTemplate.requestBody(url, version, SnmpMessage.class);

String response = pdu.getSnmpMessage().getVariableBindings().stream()
.filter(vb -> vb.getOid().equals(SnmpConstants.sysDescr))
.map(vb -> vb.getVariable().toString())
.collect(Collectors.joining());

Expand All @@ -85,12 +81,12 @@ public Response producePDU(@PathParam("version") int version) {
@Produces(MediaType.TEXT_PLAIN)
public Response getNext(String payload, @PathParam("version") int version) {
String url = String.format("snmp://%s?type=GET_NEXT&retries=1&protocol=udp&oids=%s&snmpVersion=%d", snmpListenAddress,
SnmpConstants.sysDescr, version);
payload, version);
@SuppressWarnings("unchecked")
List<SnmpMessage> pdu = producerTemplate.requestBody(url, "", List.class);

String response = pdu.stream()
.flatMap(m -> m.getSnmpMessage().getVariableBindings().stream())
.filter(vb -> vb.getOid().equals(SnmpConstants.sysDescr))
.map(vb -> vb.getVariable().toString())
.collect(Collectors.joining(","));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,16 @@ public void configure() {
from("snmp:0.0.0.0:" + trap1Port + "?protocol=udp&type=TRAP&snmpVersion=1")
.process(e -> snmpResults.get("v1_trap").add(e.getIn().getBody(SnmpMessage.class)));

//POLL consumer 2 oidps, snmpVersion=0
//POLL consumer 2 oids, snmpVersion=0
from("snmp://" + snmpListenAddress + "?protocol=udp&snmpVersion=0&type=POLL&oids=" +
SnmpConstants.sysName + "," + SnmpConstants.sysContact)
SnmpConstants.sysLocation + "," + SnmpConstants.sysContact)
.process(e -> snmpResults.get("v0_poll2oids").add(e.getIn().getBody(SnmpMessage.class)));
//POLL consumer 2 oidps, snmpVersion=1
//POLL consumer 2 oids, snmpVersion=1
from("snmp://" + snmpListenAddress + "?protocol=udp&snmpVersion=1&type=POLL&oids=" +
SnmpConstants.sysName + "," + SnmpConstants.sysContact)
SnmpConstants.sysLocation + "," + SnmpConstants.sysContact)
.process(e -> snmpResults.get("v1_poll2oids").add(e.getIn().getBody(SnmpMessage.class)));

//POLL consumer starting with dot snmpVersion=0
// POLL consumer starting with dot snmpVersion=0
from("snmp://" + snmpListenAddress
+ "?protocol=udp&snmpVersion=0&type=POLL&oids=.1.3.6.1.4.1.6527.3.1.2.21.2.1.50")
.process(e -> snmpResults.get("v0_pollStartingDot").add(e.getIn().getBody(SnmpMessage.class)));
Expand All @@ -79,11 +79,11 @@ public void configure() {

//POLL consumer snmpVersion=0
from("snmp://" + snmpListenAddress + "?protocol=udp&snmpVersion=0&type=POLL&oids="
+ SnmpConstants.sysName)
+ SnmpConstants.sysDescr)
.process(e -> snmpResults.get("v0_poll").add(e.getIn().getBody(SnmpMessage.class)));
//POLL consumer snmpVersion=1
from("snmp://" + snmpListenAddress + "?protocol=udp&snmpVersion=1&type=POLL&oids="
+ SnmpConstants.sysName)
+ SnmpConstants.sysDescr)
.process(e -> snmpResults.get("v1_poll").add(e.getIn().getBody(SnmpMessage.class)));
}

Expand All @@ -93,15 +93,15 @@ static class Producers {
@Named("snmpTrapResults")
Map<String, Deque<SnmpMessage>> snmpResults() {
Map<String, Deque<SnmpMessage>> map = new ConcurrentHashMap<>();
map.put("v0_trap", new ConcurrentLinkedDeque());
map.put("v1_trap", new ConcurrentLinkedDeque());
map.put("v0_poll", new ConcurrentLinkedDeque());
map.put("v1_poll", new ConcurrentLinkedDeque());
map.put("v3_poll", new ConcurrentLinkedDeque());
map.put("v0_pollStartingDot", new ConcurrentLinkedDeque());
map.put("v1_pollStartingDot", new ConcurrentLinkedDeque());
map.put("v0_poll2oids", new ConcurrentLinkedDeque());
map.put("v1_poll2oids", new ConcurrentLinkedDeque());
map.put("v0_trap", new ConcurrentLinkedDeque<>());
map.put("v1_trap", new ConcurrentLinkedDeque<>());
map.put("v0_poll", new ConcurrentLinkedDeque<>());
map.put("v1_poll", new ConcurrentLinkedDeque<>());
map.put("v3_poll", new ConcurrentLinkedDeque<>());
map.put("v0_pollStartingDot", new ConcurrentLinkedDeque<>());
map.put("v1_pollStartingDot", new ConcurrentLinkedDeque<>());
map.put("v0_poll2oids", new ConcurrentLinkedDeque<>());
map.put("v1_poll2oids", new ConcurrentLinkedDeque<>());
return map;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.OID;

import static org.awaitility.Awaitility.await;

Expand All @@ -40,6 +41,13 @@
@QuarkusTestResource(SnmpTestResource.class)
class SnmpTest {

public static final OID GET_NEXT_OID = new OID(new int[] { 1, 3, 6, 1, 2, 1, 25, 3, 2, 1, 5, 1 });
public static final OID POLL_OID = SnmpConstants.sysDescr;
public static final OID PRODUCE_PDU_OID = SnmpConstants.sysName;
public static final OID TWO_OIDS_A = SnmpConstants.sysLocation;
public static final OID TWO_OIDS_B = SnmpConstants.sysContact;
public static final OID DOT_OID = new OID(new int[] { 1, 3, 6, 1, 4, 1, 6527, 3, 1, 2, 21, 2, 1, 50 });

static Stream<Integer> supportedVersions() {
return Stream.of(0, 1/*, 3 not supported because of https://issues.apache.org/jira/browse/CAMEL-19298 */);
}
Expand Down Expand Up @@ -74,13 +82,14 @@ public void testPoll(int version) throws Exception {

await().atMost(20L, TimeUnit.SECONDS).pollDelay(100, TimeUnit.MILLISECONDS).until(() -> {
String result = RestAssured.given()
.body(SnmpConstants.sysName.toString())
.body(SnmpConstants.sysDescr.toString())
.post("/snmp/results/" + resultsName)
.then()
.statusCode(200)
.extract().body().asString();

return result.startsWith("Response from the test #1,Response from the test #2,Response from the test #3");
return result
.startsWith("My POLL Printer - response #1,My POLL Printer - response #2,My POLL Printer - response #3");
});
}

Expand All @@ -91,36 +100,37 @@ public void testPollStartingDot(int version) throws Exception {

await().atMost(20L, TimeUnit.SECONDS).pollDelay(100, TimeUnit.MILLISECONDS).until(() -> {
String result = RestAssured.given()
.body("1.3.6.1.4.1.6527.3.1.2.21.2.1.50")
.body(DOT_OID.toString())
.post("/snmp/results/" + resultsName)
.then()
.statusCode(200)
.extract().body().asString();

return result.startsWith("Response from the test #1,Response from the test #2,Response from the test #3");
return result.startsWith("My DOT Printer - response #1,My DOT Printer - response #2,My DOT Printer - response #3");
});
}

@ParameterizedTest
@MethodSource("supportedVersions")
public void testProducePDU(int version) {
RestAssured
.get("/snmp/producePDU/" + version)
RestAssured.given()
.body(PRODUCE_PDU_OID.toString())
.post("/snmp/producePDU/" + version)
.then()
.statusCode(200)
.body(Matchers.equalTo("Response from the test #1"));
.body(Matchers.startsWith("My PRODUCE_PDU Printer - response #"));
}

@ParameterizedTest
@MethodSource("supportedVersions")
public void testGetNext(int version) {

RestAssured.given()
.body("TEXT")
.body(GET_NEXT_OID.toString())
.post("/snmp/getNext/" + version)
.then()
.statusCode(200)
.body(Matchers.equalTo("Response from the test #1,Response from the test #2"));
.body(Matchers.equalTo("1,2,My GET_NEXT Printer - response #3"));
}

@ParameterizedTest
Expand All @@ -130,20 +140,22 @@ public void testPollWith2OIDs(int version) throws Exception {

await().atMost(20L, TimeUnit.SECONDS).pollDelay(100, TimeUnit.MILLISECONDS).until(() -> {
String resultOid1 = RestAssured.given()
.body(SnmpConstants.sysName.toString())
.body(TWO_OIDS_A.toString())
.post("/snmp/results/" + resultsName)
.then()
.statusCode(200)
.extract().body().asString();
String resultOid2 = RestAssured.given()
.body(SnmpConstants.sysContact.toString())
.body(TWO_OIDS_B.toString())
.post("/snmp/results/" + resultsName)
.then()
.statusCode(200)
.extract().body().asString();

return resultOid1.startsWith("Response from the test #1,Response from the test #2,Response from the test #3") &&
resultOid2.startsWith("Response from the test #1,Response from the test #2,Response from the test #3");
return resultOid1.startsWith(
"My 2 OIDs A Printer - response #1,My 2 OIDs A Printer - response #2,My 2 OIDs A Printer - response #3") &&
resultOid2.startsWith(
"My 2 OIDs B Printer - response #1,My 2 OIDs B Printer - response #2,My 2 OIDs B Printer - response #3");
});

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
Expand All @@ -33,6 +32,7 @@
import org.snmp4j.MessageException;
import org.snmp4j.PDU;
import org.snmp4j.PDUv1;
import org.snmp4j.ScopedPDU;
import org.snmp4j.Snmp;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.mp.StatusInformation;
Expand Down Expand Up @@ -96,38 +96,34 @@ public TestCommandResponder(Snmp commandResponder) {
@Override
public synchronized void processPdu(CommandResponderEvent event) {
PDU pdu = event.getPDU();
Vector<? extends VariableBinding> vbs = Optional.ofNullable(pdu.getVariableBindings()).orElse(new Vector<>(0));
Vector<? extends VariableBinding> vbs;
if (pdu.getVariableBindings() != null) {
vbs = new Vector<>(pdu.getVariableBindings());
} else {
vbs = new Vector<>(0);
}
String key = vbs.stream().sequential().map(vb -> vb.getOid().toString()).collect(Collectors.joining(","));

//differ snmp versions
if (pdu instanceof PDUv1) {
key = "v1" + key;
key = "v1_" + key;
} else if (pdu instanceof ScopedPDU) {
key = "v3_" + key;
} else {
key = "v2_" + key;
}
int numberOfSent = counts.getOrDefault(key, 0);

//if 3 responses were already sent for the OID, do not respond anymore
if (numberOfSent > 3) {
return;
}
//first 2 responses are quick, the third response takes 3000ms (so there is a timeout with default 1500ms) ->
// getNext producer will receive only 2 messages
// poll consumer should receive all of them
if (numberOfSent % 3 == 2) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
//nothing
}
}

try {
PDU response = makeResponse(++numberOfSent, SnmpConstants.version1, vbs);
response.setRequestID(pdu.getRequestID());
commandResponder.getMessageDispatcher().returnResponsePdu(
event.getMessageProcessingModel(), event.getSecurityModel(),
event.getSecurityName(), event.getSecurityLevel(),
response, event.getMaxSizeResponsePDU(),
event.getStateReference(), new StatusInformation());
if (response != null) {
response.setRequestID(pdu.getRequestID());
commandResponder.getMessageDispatcher().returnResponsePdu(
event.getMessageProcessingModel(), event.getSecurityModel(),
event.getSecurityName(), event.getSecurityLevel(),
response, event.getMaxSizeResponsePDU(),
event.getStateReference(), new StatusInformation());
}
} catch (MessageException e) {
Assertions.assertNull(e);
}
Expand All @@ -140,13 +136,72 @@ private PDU makeResponse(int counter, int version, Vector<? extends VariableBind
responsePDU.setErrorStatus(PDU.noError);
responsePDU.setErrorIndex(0);
if (vbs.isEmpty()) {
responsePDU.add(new VariableBinding(new OID(SnmpConstants.sysDescr),
new OctetString("Response from the test #" + counter)));
VariableBinding vb = generateResponseBinding(counter, SnmpTest.PRODUCE_PDU_OID);
if (vb != null) {
responsePDU.add(vb);
}
} else {
vbs.stream().forEach(vb -> responsePDU.add(new VariableBinding(vb.getOid(),
new OctetString("Response from the test #" + counter))));
vbs.stream().forEach(vb -> responsePDU.add(generateResponseBinding(counter, vb.getOid())));
}
if (responsePDU.getVariableBindings().isEmpty()) {
return null;
}
return responsePDU;
}

private VariableBinding generateResponseBinding(int counter, OID oid) {
//get next test
if (SnmpTest.GET_NEXT_OID.equals(oid)) {
//if counter < 2 return the same oid
if (counter < 3) {
return new VariableBinding(SnmpTest.GET_NEXT_OID, new OctetString("" + counter));
}
if (counter == 3) {
//else return sysDescr
return new VariableBinding(SnmpTest.GET_NEXT_OID,
new OctetString("My GET_NEXT Printer - response #" + counter));
}
//else do not send response
return null;
}

if (SnmpTest.POLL_OID.equals(oid)) {
if (counter < 4) {
return new VariableBinding(SnmpTest.POLL_OID,
new OctetString("My POLL Printer - response #" + counter));
}

}

if (SnmpTest.PRODUCE_PDU_OID.equals(oid)) {
if (counter < 4) {
return new VariableBinding(SnmpTest.PRODUCE_PDU_OID,
new OctetString("My PRODUCE_PDU Printer - response #" + counter));
}
}

if (SnmpTest.TWO_OIDS_A.equals(oid)) {
if (counter < 4) {
return new VariableBinding(SnmpTest.TWO_OIDS_A,
new OctetString("My 2 OIDs A Printer - response #" + counter));
}
}

if (SnmpTest.TWO_OIDS_B.equals(oid)) {
if (counter < 4) {
return new VariableBinding(SnmpTest.TWO_OIDS_B,
new OctetString("My 2 OIDs B Printer - response #" + counter));
}
}

if (SnmpTest.DOT_OID.equals(oid)) {
if (counter < 4) {
return new VariableBinding(SnmpTest.DOT_OID,
new OctetString("My DOT Printer - response #" + counter));
}
}

return null;
}
}
}

0 comments on commit 2959806

Please sign in to comment.