/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2006-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.dao; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Collection; import java.util.Comparator; import java.util.Date; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import org.apache.commons.beanutils.BeanUtils; import org.junit.Test; import org.junit.runner.RunWith; import org.opennms.core.test.OpenNMSJUnit4ClassRunner; import org.opennms.core.utils.InetAddressUtils; import org.opennms.netmgt.dao.db.JUnitConfigurationEnvironment; import org.opennms.netmgt.dao.db.JUnitTemporaryDatabase; import org.opennms.netmgt.model.OnmsDistPoller; import org.opennms.netmgt.model.OnmsIpInterface; import org.opennms.netmgt.model.OnmsMonitoredService; import org.opennms.netmgt.model.OnmsNode; import org.opennms.netmgt.model.OnmsSnmpInterface; import org.opennms.netmgt.model.PathElement; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.transaction.BeforeTransaction; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; @RunWith(OpenNMSJUnit4ClassRunner.class) @ContextConfiguration(locations={ "classpath:/META-INF/opennms/applicationContext-dao.xml", "classpath*:/META-INF/opennms/component-dao.xml", "classpath:/META-INF/opennms/applicationContext-databasePopulator.xml", "classpath:/META-INF/opennms/applicationContext-setupIpLike-enabled.xml" }) @JUnitConfigurationEnvironment @JUnitTemporaryDatabase(dirtiesContext=false) public class NodeDaoTest implements InitializingBean { @Autowired DistPollerDao m_distPollerDao; @Autowired NodeDao m_nodeDao; @Autowired JdbcTemplate m_jdbcTemplate; @Autowired DatabasePopulator m_populator; @Autowired TransactionTemplate m_transTemplate; private static boolean m_populated = false; private static DatabasePopulator m_lastPopulator; @Override public void afterPropertiesSet() throws Exception { org.opennms.core.utils.BeanUtils.assertAutowiring(this); } @BeforeTransaction public void setUp() { try { if (!m_populated) { m_populator.populateDatabase(); m_lastPopulator = m_populator; } } catch (Throwable e) { e.printStackTrace(System.err); } finally { m_populated = true; } } public OnmsNode getNode1() { return m_lastPopulator.getNode1(); } public JdbcTemplate getJdbcTemplate() { return m_jdbcTemplate; } public NodeDao getNodeDao() { return m_nodeDao; } public DistPollerDao getDistPollerDao() { return m_distPollerDao; } @Test @Transactional public void testSave() { OnmsDistPoller distPoller = getDistPollerDao().get("localhost"); OnmsNode node = new OnmsNode(distPoller); node.setLabel("MyFirstNode"); getNodeDao().save(node); getNodeDao().flush(); } @Test @Transactional public void testSaveWithPathElement() { OnmsDistPoller distPoller = getDistPollerDao().get("localhost"); OnmsNode node = new OnmsNode(distPoller); node.setLabel("MyFirstNode"); PathElement p = new PathElement("192.168.7.7", "ICMP"); node.setPathElement(p); getNodeDao().save(node); getNodeDao().flush(); } @Test @Transactional public void testSaveWithNullPathElement() { OnmsDistPoller distPoller = getDistPollerDao().get("localhost"); OnmsNode node = new OnmsNode(distPoller); node.setLabel("MyFirstNode"); PathElement p = new PathElement("192.168.7.7", "ICMP"); node.setPathElement(p); getNodeDao().save(node); OnmsNode myNode = getNodeDao().get(node.getId()); assertNotNull(myNode); myNode.setPathElement(null); getNodeDao().save(myNode); getNodeDao().flush(); } @Test @Transactional public void testCreate() throws InterruptedException { OnmsDistPoller distPoller = getDistPoller(); OnmsNode node = new OnmsNode(distPoller); node.setLabel("MyFirstNode"); node.getAssetRecord().setDisplayCategory("MyCategory"); PathElement p = new PathElement("192.168.7.7", "ICMP"); node.setPathElement(p); getNodeDao().save(node); System.out.println("BEFORE GET"); OnmsDistPoller dp = getDistPoller(); assertSame(distPoller, dp); System.out.println("AFTER GET"); Collection<OnmsNode> nodes = getNodeDao().findNodes(dp); assertEquals(7, nodes.size()); System.out.println("AFTER GETNODES"); for (OnmsNode retrieved : nodes) { System.out.println("category for "+retrieved.getId()+" = "+retrieved.getAssetRecord().getDisplayCategory()); if (node.getId().intValue() == 5) { assertEquals("MyFirstNode", retrieved.getLabel()); assertEquals("MyCategory", retrieved.getAssetRecord().getDisplayCategory()); assertEquals("192.168.7.7", retrieved.getPathElement().getIpAddress()); } } System.out.println("AFTER Loop"); } @Test @Transactional public void testQuery() throws Exception { OnmsNode n = getNodeDao().get(getNode1().getId()); validateNode(n); } @Test @Transactional public void testDeleteOnOrphanIpInterface() { int preCount = getJdbcTemplate().queryForInt("select count(*) from ipinterface where ipinterface.nodeId = " + getNode1().getId()); OnmsNode n = getNodeDao().get(getNode1().getId()); Iterator<OnmsIpInterface> it = n.getIpInterfaces().iterator(); it.next(); it.remove(); getNodeDao().saveOrUpdate(n); getNodeDao().flush(); int postCount = getJdbcTemplate().queryForInt("select count(*) from ipinterface where ipinterface.nodeId = " + getNode1().getId()); assertEquals(preCount-1, postCount); } @Test @Transactional public void testDeleteNode() { int preCount = getJdbcTemplate().queryForInt("select count(*) from node"); OnmsNode n = getNodeDao().get(getNode1().getId()); getNodeDao().delete(n); getNodeDao().flush(); int postCount = getJdbcTemplate().queryForInt("select count(*) from node"); assertEquals(preCount-1, postCount); } @Test @Transactional public void testQueryWithHierarchy() throws Exception { OnmsNode n = getNodeDao().getHierarchy(getNode1().getId()); validateNode(n); } public OnmsNode getNodeHierarchy(final int nodeId) { return m_transTemplate.execute(new TransactionCallback<OnmsNode>() { public OnmsNode doInTransaction(TransactionStatus status) { return getNodeDao().getHierarchy(nodeId); } }); } /** Test for bug 1594 */ @Test @Transactional public void testQueryWithHierarchyCloseTransaction() throws Exception { OnmsNode n = getNodeHierarchy(getNode1().getId()); validateNode(n); for (OnmsIpInterface ip : n.getIpInterfaces()) { ip.getIpAddress(); for (OnmsMonitoredService service : ip.getMonitoredServices()) { service.getServiceName(); } } // Test for bug 1594 for (OnmsSnmpInterface snmp : n.getSnmpInterfaces()) { for (OnmsIpInterface ip : snmp.getIpInterfaces()) { ip.getIpAddress(); } } } @Test @Transactional public void testGetForeignIdToNodeIdMap() { Map<String, Integer> arMap = getNodeDao().getForeignIdToNodeIdMap("imported:"); assertTrue("Expected to find foriegnId 1", arMap.containsKey("1")); OnmsNode node1 = getNodeDao().get(arMap.get("1")); assertNotNull("Exepected foreignId to be mapped to a node", node1); assertEquals("Expected foreignId to be mapped to 'node1'", "node1", node1.getLabel()); } @Test @Transactional public void testUpdateNodeScanStamp() { Date timestamp = new Date(27); getNodeDao().updateNodeScanStamp(getNode1().getId(), timestamp); OnmsNode n = getNodeDao().get(getNode1().getId()); assertEquals(timestamp, n.getLastCapsdPoll()); } @Test @Transactional public void testFindByForeignSourceAndIpAddress() { assertEquals(0, getNodeDao().findByForeignSourceAndIpAddress("NoSuchForeignSource", "192.168.1.1").size()); assertEquals(0, getNodeDao().findByForeignSourceAndIpAddress("imported:", "192.167.7.7").size()); assertEquals(1, getNodeDao().findByForeignSourceAndIpAddress("imported:", "192.168.1.1").size()); assertEquals(1, getNodeDao().findByForeignSourceAndIpAddress(null, "10.1.1.1").size()); assertEquals(0, getNodeDao().findByForeignSourceAndIpAddress(null, "192.167.7.7").size()); } @Test @JUnitTemporaryDatabase // This test manages its own transactions so use a fresh database public void testDeleteObsoleteInterfaces() { m_populator.populateDatabase(); final Date timestamp = new Date(1234); m_transTemplate.execute(new TransactionCallback<Object>() { public Object doInTransaction(TransactionStatus status) { simulateScan(timestamp); return null; } }); m_transTemplate.execute(new TransactionCallback<Object>() { public Object doInTransaction(TransactionStatus status) { deleteObsoleteInterfaces(timestamp); return null; } }); m_transTemplate.execute(new TransactionCallback<Object>() { public Object doInTransaction(TransactionStatus status) { validateScan(); return null; } }); } private void validateScan() { OnmsNode after = getNodeDao().get(getNode1().getId()); assertEquals(1, after.getIpInterfaces().size()); assertEquals(1, after.getSnmpInterfaces().size()); } private void simulateScan(Date timestamp) { OnmsNode n = getNodeDao().get(getNode1().getId()); assertEquals(4, n.getIpInterfaces().size()); assertEquals(4, n.getSnmpInterfaces().size()); OnmsIpInterface iface = n.getIpInterfaceByIpAddress("192.168.1.1"); assertNotNull(iface); iface.setIpLastCapsdPoll(timestamp); OnmsSnmpInterface snmpIface = n.getSnmpInterfaceWithIfIndex(1); assertNotNull(snmpIface); snmpIface.setLastCapsdPoll(timestamp); getNodeDao().saveOrUpdate(n); getNodeDao().flush(); } private void deleteObsoleteInterfaces(Date timestamp) { getNodeDao().deleteObsoleteInterfaces(getNode1().getId(), timestamp); } private void validateNode(OnmsNode n) throws Exception { assertNotNull("Expected node to be non-null", n); assertNotNull("Expected node "+n.getId()+" to have interfaces", n.getIpInterfaces()); assertEquals("Unexpected number of interfaces for node "+n.getId(), 4, n.getIpInterfaces().size()); for (Object o : n.getIpInterfaces()) { OnmsIpInterface iface = (OnmsIpInterface)o; assertNotNull(iface); assertNotNull(InetAddressUtils.str(iface.getIpAddress())); } assertNodeEquals(getNode1(), n); } private static class PropertyComparator implements Comparator<Object> { String m_propertyName; public PropertyComparator(String propertyName) { m_propertyName = propertyName; } public int compare(Object o1, Object o2) { String expectedValue; try { expectedValue = ""+BeanUtils.getProperty(o1, m_propertyName); String actualValue = ""+BeanUtils.getProperty(o2, m_propertyName); return expectedValue.compareTo(actualValue); } catch (Throwable e) { throw new IllegalArgumentException("Unable to compare property "+m_propertyName, e); } } } private static void assertNodeEquals(OnmsNode expected, OnmsNode actual) throws Exception { assertEquals("Unexpected nodeId", expected.getId(), actual.getId()); String[] properties = { "id", "label", "labelSource", "assetRecord.assetNumber", "distPoller.name", "sysContact", "sysName", "sysObjectId" }; assertPropertiesEqual(properties, expected, actual); assertInterfaceSetsEqual(expected.getIpInterfaces(), actual.getIpInterfaces()); } private static interface AssertEquals<T> { public void assertEqual(T expected, T actual) throws Exception; } private static <T> void assertSetsEqual(Set<T> expectedSet, Set<T> actualSet, String orderProperty, AssertEquals<T> comparer) throws Exception { SortedSet<T> expectedSorted = new TreeSet<T>(new PropertyComparator(orderProperty)); expectedSorted.addAll(expectedSet); SortedSet<T> actualSorted = new TreeSet<T>(new PropertyComparator(orderProperty)); actualSorted.addAll(actualSet); Iterator<T> expected = expectedSorted.iterator(); Iterator<T> actual = actualSorted.iterator(); while(expected.hasNext() && actual.hasNext()) { comparer.assertEqual(expected.next(), actual.next()); } if (expected.hasNext()) fail("Missing item "+expected.next()+" in the actual list"); if (actual.hasNext()) fail("Unexpected item "+actual.next()+" in the actual list"); } private static void assertInterfaceSetsEqual(Set<OnmsIpInterface> expectedSet, Set<OnmsIpInterface> actualSet) throws Exception { assertSetsEqual(expectedSet, actualSet, "ipAddress" , new AssertEquals<OnmsIpInterface>() { public void assertEqual(OnmsIpInterface expected, OnmsIpInterface actual) throws Exception { assertInterfaceEquals(expected, actual); } }); } private static void assertInterfaceEquals(OnmsIpInterface expected, OnmsIpInterface actual) throws Exception { String[] properties = { "ipAddress", "ifIndex", "ipHostName", "isManaged", "node.id" }; assertPropertiesEqual(properties, expected, actual); assertServicesEquals(expected.getMonitoredServices(), actual.getMonitoredServices()); } private static void assertServicesEquals(Set<OnmsMonitoredService> expectedSet, Set<OnmsMonitoredService> actualSet) throws Exception { assertSetsEqual(expectedSet, actualSet, "serviceId" , new AssertEquals<OnmsMonitoredService>() { public void assertEqual(OnmsMonitoredService expected, OnmsMonitoredService actual) throws Exception { assertServiceEquals(expected, actual); } }); } protected static void assertServiceEquals(OnmsMonitoredService expected, OnmsMonitoredService actual) { assertEquals(expected.getServiceName(), actual.getServiceName()); } private static void assertPropertiesEqual(String[] properties, Object expected, Object actual) throws Exception { for (String property : properties) { assertPropertyEquals(property, expected, actual); } } private static void assertPropertyEquals(String name, Object expected, Object actual) throws Exception { Object expectedValue = BeanUtils.getProperty(expected, name); Object actualValue = BeanUtils.getProperty(actual, name); assertEquals("Unexpected value for property "+name+" on object "+expected, expectedValue, actualValue); } @Test @Transactional public void testQuery2() { assertNotNull(m_lastPopulator); assertNotNull(m_lastPopulator.getNode6()); OnmsNode n = getNodeDao().get(m_lastPopulator.getNode6().getId()); assertNotNull(n); assertEquals(3, n.getIpInterfaces().size()); assertNotNull(n.getAssetRecord()); assertEquals("category1", n.getAssetRecord().getDisplayCategory()); } private OnmsDistPoller getDistPoller() { OnmsDistPoller distPoller = getDistPollerDao().load("localhost"); assertNotNull(distPoller); return distPoller; } }