/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.netmgt.snmp; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.opennms.core.test.MockLogAppender; import org.opennms.core.test.OpenNMSJUnit4ClassRunner; import org.opennms.core.test.snmp.annotations.JUnitSnmpAgent; import org.opennms.core.utils.BeanUtils; import org.opennms.core.utils.InetAddressUtils; import org.opennms.core.utils.LogUtils; import org.opennms.netmgt.config.SnmpPeerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; @RunWith(OpenNMSJUnit4ClassRunner.class) @ContextConfiguration(locations={ "classpath:/META-INF/opennms/applicationContext-proxy-snmp.xml" }) @JUnitSnmpAgent(host="172.20.1.205", resource="classpath:snmpTestData1.properties") public class SnmpTrackerTest implements InitializingBean { @Autowired private SnmpPeerFactory m_snmpPeerFactory; public static final class SnmpTableConstants { static final SnmpObjId ifTable = SnmpObjId.get(".1.3.6.1.2.1.2.2.1"); static final SnmpObjId ifIndex = SnmpObjId.get(ifTable, "1"); static final SnmpObjId ifDescr = SnmpObjId.get(ifTable, "2"); static final SnmpObjId ifType = SnmpObjId.get(ifTable, "3"); static final SnmpObjId ifMtu = SnmpObjId.get(ifTable, "4"); static final SnmpObjId ifSpeed = SnmpObjId.get(ifTable, "5"); static final SnmpObjId ifPhysAddress = SnmpObjId.get(ifTable, "6"); static final SnmpObjId ifAdminStatus = SnmpObjId.get(ifTable, "7"); static final SnmpObjId ifOperStatus = SnmpObjId.get(ifTable, "8"); static final SnmpObjId ifLastChange = SnmpObjId.get(ifTable, "9"); static final SnmpObjId ifInOctets = SnmpObjId.get(ifTable, "10"); static final SnmpObjId ifInUcastPkts = SnmpObjId.get(ifTable, "11"); static final SnmpObjId ifInNUcastPkts = SnmpObjId.get(ifTable, "12"); static final SnmpObjId ifInDiscards = SnmpObjId.get(ifTable, "13"); static final SnmpObjId ifInErrors = SnmpObjId.get(ifTable, "14"); static final SnmpObjId ifUnknownProtos = SnmpObjId.get(ifTable, "15"); static final SnmpObjId ifOutOctets = SnmpObjId.get(ifTable, "16"); static final SnmpObjId ifOutUcastPkts = SnmpObjId.get(ifTable, "17"); static final SnmpObjId ifOutNUcastPkts = SnmpObjId.get(ifTable, "18"); static final SnmpObjId ifOutDiscards = SnmpObjId.get(ifTable, "19"); static final SnmpObjId ifOutErrors = SnmpObjId.get(ifTable, "20"); static final SnmpObjId ifOutQLen = SnmpObjId.get(ifTable, "21"); static final SnmpObjId ifSpecific = SnmpObjId.get(ifTable, "22"); } static private class CountingColumnTracker extends ColumnTracker { private long m_count = 0; public CountingColumnTracker(final SnmpObjId base) { super(base); } public CountingColumnTracker(final SnmpObjId base, final int maxRepetitions) { super(base, maxRepetitions); } public long getCount() { return m_count; } @Override protected void storeResult(final SnmpResult res) { LogUtils.debugf(this, "storing result: %s", res); m_count++; } } static private final class ResultTable { private int m_rowsAdded = 0; private Map<SnmpInstId, SnmpRowResult> m_results = new HashMap<SnmpInstId, SnmpRowResult>(); SnmpValue getResult(final SnmpObjId base, final SnmpInstId inst) { final SnmpRowResult row = m_results.get(inst); if (row == null) { return null; } return row.getValue(base); } SnmpValue getResult(final SnmpObjId base, final String inst) { return getResult(base, new SnmpInstId(inst)); } int getRowsAdded() { return m_rowsAdded; } void addSnmpRowResult(final SnmpRowResult row) { m_rowsAdded++; m_results.put(row.getInstance(), row); } public int getRowCount() { return m_results.size(); } public int getColumnCount() { int maxColumns = Integer.MIN_VALUE; for(final SnmpRowResult row : m_results.values()) { maxColumns = Math.max(maxColumns, row.getColumnCount()); } return maxColumns; } } static private class TestRowCallback implements RowCallback { private final List<SnmpRowResult> m_responses = new ArrayList<SnmpRowResult>(); private final ResultTable m_results = new ResultTable(); public void rowCompleted(final SnmpRowResult row) { m_responses.add(row); m_results.addSnmpRowResult(row); } public List<SnmpRowResult> getResponses() { return m_responses; } public ResultTable getResults() { return m_results; } } private void walk(final CollectionTracker c, final int maxVarsPerPdu, final int maxRepetitions) throws Exception { final SnmpAgentConfig config = m_snmpPeerFactory.getAgentConfig(InetAddressUtils.addr("172.20.1.205")); config.setVersion(SnmpAgentConfig.VERSION2C); config.setMaxVarsPerPdu(maxVarsPerPdu); config.setMaxRepetitions(maxRepetitions); final SnmpWalker walker = SnmpUtils.createWalker(config, "test", c); assertNotNull(walker); walker.start(); walker.waitFor(); } @Override public void afterPropertiesSet() throws Exception { BeanUtils.assertAutowiring(this); } @Before public void setUp() { MockLogAppender.setupLogging(); SnmpPeerFactory.setInstance(m_snmpPeerFactory); } @Test public void testColumnTracker() throws Exception { final CountingColumnTracker ct = new CountingColumnTracker(SnmpObjId.get(".1.3.6.1.2.1.2.2.1.1")); walk(ct, 10, 3); assertEquals("number of columns returned must match test data", Long.valueOf(6).longValue(), ct.getCount()); } @Test public void testTableTrackerWithFullTable() throws Exception { final TestRowCallback rc = new TestRowCallback(); final TableTracker tt = new TableTracker(rc, SnmpTableConstants.ifIndex, SnmpTableConstants.ifDescr, SnmpTableConstants.ifSpeed); walk(tt, 3, 10); final ResultTable results = rc.getResults(); assertTrue("tracker must be finished", tt.isFinished()); assertEquals("number of rows added must match test data", 6, results.getRowsAdded()); assertEquals("number of rows must match test data", 6, results.getRowCount()); assertEquals("number of columns must match test data", 3, results.getColumnCount()); assertEquals("ifIndex.5 must be 5", 5, results.getResult(SnmpTableConstants.ifIndex, "5").toInt()); assertEquals("ifName.2 must be gif0", "gif0", results.getResult(SnmpTableConstants.ifDescr, "2").toString()); assertEquals("ifSpeed.3 must be 0", 0, results.getResult(SnmpTableConstants.ifSpeed, "3").toLong()); assertEquals("ifSpeed.4 must be 10000000", 10000000, results.getResult(SnmpTableConstants.ifSpeed, "4").toLong()); } @Test @JUnitSnmpAgent(host="172.20.1.205", resource="classpath:snmpTestDataIncompleteTable.properties") public void testIncompleteTableData() throws Exception { final TestRowCallback rc = new TestRowCallback(); final TableTracker tt = new TableTracker(rc, SnmpTableConstants.ifIndex, SnmpTableConstants.ifDescr, SnmpTableConstants.ifMtu, SnmpTableConstants.ifLastChange, SnmpTableConstants.ifInUcastPkts, SnmpTableConstants.ifInErrors, SnmpTableConstants.ifOutUcastPkts, SnmpTableConstants.ifOutNUcastPkts, SnmpTableConstants.ifOutErrors ); walk(tt, 4, 3); printResponses(rc); final ResultTable results = rc.getResults(); assertTrue("tracker must be finished", tt.isFinished()); assertEquals("number of rows added must match test data", 6, results.getRowsAdded()); assertEquals("number of rows must match test data", 6, results.getRowCount()); assertEquals("number of columns must match test data", 9, results.getColumnCount()); assertNull("ifMtu.4 should be null", results.getResult(SnmpTableConstants.ifMtu, "4")); assertEquals("ifDescr.5 should be en1", "en1", results.getResult(SnmpTableConstants.ifDescr, "5").toString()); assertEquals("ifMtu.6 should be 4078", 4078, results.getResult(SnmpTableConstants.ifMtu, "6").toInt()); } @Test @Ignore("Hmm, what *should* this do? When using a callback, we don't pass storeResult() up-stream...") public void testAggregateTable() throws Exception { final TestRowCallback rc = new TestRowCallback(); final TableTracker[] tt = new TableTracker[2]; tt[0] = new TableTracker(rc, SnmpTableConstants.ifIndex, SnmpTableConstants.ifDescr); tt[1] = new TableTracker(rc, SnmpTableConstants.ifMtu, SnmpTableConstants.ifLastChange); final AggregateTracker at = new AggregateTracker(tt); walk(at, 4, 10); printResponses(rc); } private void printResponses(final TestRowCallback rc) { final List<SnmpRowResult> responses = rc.getResponses(); for (int i = 0; i < responses.size(); i++) { final SnmpRowResult row = responses.get(i); LogUtils.debugf(this, "%d: instance=%s", i, row.getInstance()); for (final SnmpResult res : row.getResults()) { LogUtils.debugf(this, " %s=%s", res.getBase(), res.getValue()); } } } }