/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2007-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.support; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import junit.framework.TestCase; import org.apache.commons.io.IOUtils; import org.apache.log4j.Level; import org.apache.log4j.spi.LoggingEvent; import org.junit.Assert; import org.opennms.core.test.MockLogAppender; import org.opennms.netmgt.dao.support.PropertiesGraphDao.PrefabGraphTypeDao; import org.opennms.netmgt.model.AdhocGraphType; import org.opennms.netmgt.model.ExternalValueAttribute; import org.opennms.netmgt.model.OnmsAttribute; import org.opennms.netmgt.model.OnmsResource; import org.opennms.netmgt.model.PrefabGraph; import org.opennms.netmgt.model.RrdGraphAttribute; import org.opennms.test.ConfigurationTestUtils; import org.opennms.test.FileAnticipator; import org.springframework.core.io.FileSystemResource; import org.springframework.core.io.Resource; import org.springframework.orm.ObjectRetrievalFailureException; public class PropertiesGraphDaoTest extends TestCase { private static final Map<String, Resource> s_emptyMap = new HashMap<String, Resource>(); final static String s_prefab = "command.prefix=foo\n" + "output.mime=foo\n" + "\n" + "reports=mib2.HCbits, mib2.bits, mib2.discards\n" + "\n" + "report.mib2.HCbits.name=Bits In/Out\n" + "report.mib2.HCbits.columns=ifHCInOctets,ifHCOutOctets\n" + "report.mib2.HCbits.type=interface\n" + "report.mib2.HCbits.externalValues=ifSpeed\n" + "report.mib2.HCbits.suppress=mib2.bits\n" + "report.mib2.HCbits.command=--title=\"Bits In/Out (High Speed)\" \\\n" + " DEF:octIn={rrd1}:ifHCInOctets:AVERAGE \\\n" + " DEF:octOut={rrd2}:ifHCOutOctets:AVERAGE \\\n" + " CDEF:bitsIn=octIn,8,* \\\n" + " CDEF:bitsOut=octOut,8,* \\\n" + " CDEF:totBits=octIn,octOut,+,8,* \\\n" + " AREA:totBits#00ff00:\"Total\" \\\n" + " GPRINT:totBits:AVERAGE:\" Avg \\\\: %8.2lf %s\\\\n\" \\\n" + " LINE2:bitsIn#0000ff:\"Bits In\" \\\n" + " GPRINT:bitsIn:AVERAGE:\" Avg \\\\: %8.2lf %s\" \\\n" + " GPRINT:bitsIn:MIN:\"Min \\\\: %8.2lf %s\" \\\n" + " GPRINT:bitsIn:MAX:\"Max \\\\: %8.2lf %s\\\\n\" \\\n" + " LINE2:bitsOut#ff0000:\"Bits Out\" \\\n" + " GPRINT:bitsOut:AVERAGE:\"Avg \\\\: %8.2lf %s\" \\\n" + " GPRINT:bitsOut:MIN:\"Min \\\\: %8.2lf %s\" \\\n" + " GPRINT:bitsOut:MAX:\"Max \\\\: %8.2lf %s\\\\n\"\n" + "\n" + "report.mib2.bits.name=Bits In/Out\n" + "report.mib2.bits.columns=ifInOctets,ifOutOctets\n" + "report.mib2.bits.type=interface\n" + "report.mib2.bits.externalValues=ifSpeed\n" + "report.mib2.bits.command=--title=\"Bits In/Out\" \\\n" + " DEF:octIn={rrd1}:ifInOctets:AVERAGE \\\n" + " DEF:octOut={rrd2}:ifOutOctets:AVERAGE \\\n" + " CDEF:bitsIn=octIn,8,* \\\n" + " CDEF:bitsOut=octOut,8,* \\\n" + " CDEF:totBits=octIn,octOut,+,8,* \\\n" + " AREA:totBits#00ff00:\"Total\" \\\n" + " GPRINT:totBits:AVERAGE:\" Avg \\\\: %8.2lf %s\\\\n\" \\\n" + " LINE2:bitsIn#0000ff:\"Bits In\" \\\n" + " GPRINT:bitsIn:AVERAGE:\" Avg \\\\: %8.2lf %s\" \\\n" + " GPRINT:bitsIn:MIN:\"Min \\\\: %8.2lf %s\" \\\n" + " GPRINT:bitsIn:MAX:\"Max \\\\: %8.2lf %s\\\\n\" \\\n" + " LINE2:bitsOut#ff0000:\"Bits Out\" \\\n" + " GPRINT:bitsOut:AVERAGE:\"Avg \\\\: %8.2lf %s\" \\\n" + " GPRINT:bitsOut:MIN:\"Min \\\\: %8.2lf %s\" \\\n" + " GPRINT:bitsOut:MAX:\"Max \\\\: %8.2lf %s\\\\n\"\n" + "\n" + "report.mib2.discards.name=Discards In/Out\n" + "report.mib2.discards.columns=ifInDiscards,ifOutDiscards\n" + "report.mib2.discards.type=interface\n" + "report.mib2.discards.propertiesValues=ifSpeed\n" + "report.mib2.discards.command=--title=\"Discards In/Out\" \\\n" + " DEF:octIn={rrd1}:ifInDiscards:AVERAGE \\\n" + " DEF:octOut={rrd2}:ifOutDiscards:AVERAGE \\\n" + " LINE2:octIn#0000ff:\"Discards In\" \\\n" + " GPRINT:octIn:AVERAGE:\" Avg \\\\: %8.2lf %s\" \\\n" + " GPRINT:octIn:MIN:\"Min \\\\: %8.2lf %s\" \\\n" + " GPRINT:octIn:MAX:\"Max \\\\: %8.2lf %s\\\\n\" \\\n" + " LINE2:octOut#ff0000:\"Discards Out\" \\\n" + " GPRINT:octOut:AVERAGE:\"Avg \\\\: %8.2lf %s\" \\\n" + " GPRINT:octOut:MIN:\"Min \\\\: %8.2lf %s\" \\\n" + " GPRINT:octOut:MAX:\"Max \\\\: %8.2lf %s\\\\n\"\n"; private static final String s_adhoc = "command.prefix=${install.rrdtool.bin} graph - --imgformat PNG --start {1} --end {2}\n" + "output.mime=image/png\n" + "adhoc.command.title=--title=\"{3}\"\n" + "adhoc.command.ds=DEF:{4}={0}:{5}:{6}\n" + "adhoc.command.graphline={7}:{4}#{8}:\"{9}\"\n"; private static final String s_responsePrefab = "command.prefix=foo\n" + "output.mime=foo\n" + "\n" + "reports=icmp\n" + "\n" + "report.icmp.name=ICMP\n" + "report.icmp.columns=icmp\n" + "report.icmp.type=responseTime\n" + "report.icmp.command=--title=\"ICMP Response Time\" \\\n" + " --vertical-label=\"Seconds\" \\\n" + " DEF:rtMicro={rrd1}:icmp:AVERAGE \\\n" + " CDEF:rt=rtMicro,1000000,/ \\\n" + " LINE1:rt#0000ff:\"Response Time\" \\\n" + " GPRINT:rt:AVERAGE:\" Avg \\: %8.2lf %s\" \\\n" + " GPRINT:rt:MIN:\"Min \\\\: %8.2lf %s\" \\\n" + " GPRINT:rt:MAX:\"Max \\\\: %8.2lf %s\\\\n\""; private static final String s_baseIncludePrefab = "command.prefix=foo\n" + "output.mime=image/png\n" + "reports=\n" + //Empty for a simple base prefab, with only graphs included from the sub directory "include.directory=snmp-graph.properties.d\n" + "include.directory.rescan=1000\n"; //1 second rescan time, for efficient testing private static final String s_separateBitsGraph = "report.id=mib2.bits\n" + "report.name=Bits In/Out\n" + "report.columns=ifInOctets,ifOutOctets\n" + "report.type=interface\n" + "report.externalValues=ifSpeed\n" + "report.command=--title=\"Bits In/Out\"\n"; //Just a title is enough for testing private static final String s_separateHCBitsGraph = "report.id=mib2.HCbits\n" + "report.name=Bits In/Out\n" + "report.columns=ifHCInOctets,ifHCOutOctets\n" + "report.type=interface\n" + "report.externalValues=ifSpeed\n" + "report.suppress=mib2.bits\n" + "report.command=--title=\"Bits In/Out (High Speed)\"\n"; //Just a title is enough for testing private static final String s_separateErrorsGraph = "report.id=mib2.errors\n" +"report.name=Errors In/Out\n" + "report.columns=ifIfErrors,ifOutErrors\n" + "report.type=interface\n" + "report.propertiesValues=ifSpeed\n" + "report.command=--title=\"Erros In/Out\"\n"; private static final String s_includedMultiGraph1 = "reports=mib2.discards,mib2.errors\n" +"report.mib2.discards.name=Discards In/Out\n" + "report.mib2.discards.columns=ifInDiscards,ifOutDiscards\n" + "report.mib2.discards.type=interface\n" + "report.mib2.discards.propertiesValues=ifSpeed\n" + "report.mib2.discards.command=--title=\"Discards In/Out\"\n" + "\n" + "report.mib2.errors.name=Errors In/Out\n" + "report.mib2.errors.columns=ifInErrors,ifOutErrors\n" + "report.mib2.errors.type=interface\n" + "report.mib2.errors.propertiesValues=ifSpeed\n" + "report.mib2.errors.command=--title=\"Discards In/Out\"\n"; private static final String s_includedMultiGraph2 = "reports=mib2.bits,mib2.HCbits\n" + "report.mib2.bits.name=Bits In/Out\n" + "report.mib2.bits.columns=ifInOctets,ifOutOctets\n" + "report.mib2.bits.type=interface\n" + "report.mib2.bits.externalValues=ifSpeed\n" + "report.mib2.bits.command=--title=\"Bits In/Out\"\n" + "\n" + "report.mib2.HCbits.name=Bits In/Out\n" + "report.mib2.HCbits.columns=ifHCInOctets,ifHCOutOctets\n" + "report.mib2.HCbits.type=interface\n" + "report.mib2.HCbits.externalValues=ifSpeed\n" + "report.mib2.HCbits.suppress=mib2.bits\n" + "report.mib2.HCbits.command=--title=\"Bits In/Out (High Speed)\"\n"; //Just a title is enough for testing //A base file, with an include, that defines a single graph, with some unusual and incorrect details // that will be overridden by the included graph private static final String s_mib2bitsBasePrefab = "command.prefix=foo\n" + "output.mime=image/png\n" + "include.directory=snmp-graph.properties.d\n" + "reports=mib2.bits\n" + "report.mib2.bits.name=Wrong Name\n" + "report.mib2.bits.columns=wrongColumn1,wrongColumn2\n" + "report.mib2.bits.type=node\n" + "report.mib2.bits.externalValues=fooBar\n" + "report.mib2.bits.command=--title=\"Wrong Title\"\n"; /** * A prefab graphs config with just one of the reports broken in a subtle way (mib2.bits, with it's "name" property spelled "nmae" * Used to test that the rest of the reports load as expected * (Actual report details trimmed for space */ final static String s_partlyBorkedPrefab = "command.prefix=foo\n" + "output.mime=foo\n" + "\n" + "reports=mib2.HCbits, mib2.bits, mib2.discards\n" + "\n" + "report.mib2.HCbits.name=Bits In/Out\n" + "report.mib2.HCbits.columns=ifHCInOctets,ifHCOutOctets\n" + "report.mib2.HCbits.type=interface\n" + "report.mib2.HCbits.externalValues=ifSpeed\n" + "report.mib2.HCbits.suppress=mib2.bits\n" + "report.mib2.HCbits.command=--title=\"Bits In/Out (High Speed)\" \n" + "\n" + "report.mib2.bits.nmae=Bits In/Out\n" + "report.mib2.bits.columns=ifInOctets,ifOutOctets\n" + "report.mib2.bits.type=interface\n" + "report.mib2.bits.externalValues=ifSpeed\n" + "report.mib2.bits.command=--title=\"Bits In/Out\" \n" + "\n" + "report.mib2.discards.name=Discards In/Out\n" + "report.mib2.discards.columns=ifInDiscards,ifOutDiscards\n" + "report.mib2.discards.type=interface\n" + "report.mib2.discards.propertiesValues=ifSpeed\n" + "report.mib2.discards.command=--title=\"Discards In/Out\" \n"; private Map<String, FileReloadContainer<PrefabGraph>> m_graphs; private PropertiesGraphDao m_dao; private boolean testSpecificLoggingTest = false; private FileAnticipator m_fileAnticipator = null; private FileOutputStream m_outputStream = null; private Writer m_writer = null; @Override protected void setUp() throws Exception { super.setUp(); MockLogAppender.setupLogging(true); m_dao = createPropertiesGraphDao(s_emptyMap, s_emptyMap); ByteArrayInputStream in = new ByteArrayInputStream(s_prefab.getBytes()); m_dao.loadProperties("performance", in); PrefabGraphTypeDao type = m_dao.findPrefabGraphTypeDaoByName("performance"); assertNotNull("could not get performance prefab graph type", type); m_graphs = type.getReportMap(); assertNotNull("report map shouldn't be null", m_graphs); m_fileAnticipator = new FileAnticipator(); } @Override protected void runTest() throws Throwable { super.runTest(); //Allow an individual test to tell us to ignore the logging assertion // e.g. if they're testing with assertLogAtLevel if(!testSpecificLoggingTest) { MockLogAppender.assertNoWarningsOrGreater(); } } @Override protected void tearDown() throws Exception { IOUtils.closeQuietly(m_writer); IOUtils.closeQuietly(m_outputStream); // For Windows, see // http://stackoverflow.com/a/4213208/149820 for details m_writer = null; m_outputStream = null; System.gc(); m_fileAnticipator.deleteExpected(); m_fileAnticipator.tearDown(); MockLogAppender.resetEvents(); } public void testCompareToLessThan() { PrefabGraph bits = m_graphs.get("mib2.bits").getObject(); PrefabGraph discards = m_graphs.get("mib2.discards").getObject();; assertEquals("compareTo", -1, bits.compareTo(discards)); } public void testCompareToGreaterThan() { PrefabGraph bits = m_graphs.get("mib2.bits").getObject();; PrefabGraph discards = m_graphs.get("mib2.discards").getObject();; assertEquals("compareTo", 1, discards.compareTo(bits)); } public void testCompareToEquals() { PrefabGraph bits = m_graphs.get("mib2.bits").getObject();; PrefabGraph bits2 = m_graphs.get("mib2.bits").getObject();; assertEquals("compareTo", 0, bits.compareTo(bits2)); } public void testGetName() { PrefabGraph bits = m_graphs.get("mib2.bits").getObject();; assertEquals("getName", "mib2.bits", bits.getName()); } public void testGetTitle() { PrefabGraph bits = m_graphs.get("mib2.bits").getObject();; assertEquals("getTitle", "Bits In/Out", bits.getTitle()); } public void testGetOrder() { PrefabGraph bits = m_graphs.get("mib2.HCbits").getObject();; assertEquals("getOrder", 0, bits.getOrder()); } public void testGetColumns() { PrefabGraph bits = m_graphs.get("mib2.bits").getObject();; String[] columns = bits.getColumns(); assertEquals("getColumns().length", 2, columns.length); assertEquals("getColumns()[0]", "ifInOctets", columns[0]); assertEquals("getColumns()[1]", "ifOutOctets", columns[1]); } public void testGetCommand() { String expectedCommand = "--title=\"Bits In/Out\" " + "DEF:octIn={rrd1}:ifInOctets:AVERAGE " + "DEF:octOut={rrd2}:ifOutOctets:AVERAGE " + "CDEF:bitsIn=octIn,8,* " + "CDEF:bitsOut=octOut,8,* " + "CDEF:totBits=octIn,octOut,+,8,* " + "AREA:totBits#00ff00:\"Total\" " + "GPRINT:totBits:AVERAGE:\" Avg \\: %8.2lf %s\\n\" " + "LINE2:bitsIn#0000ff:\"Bits In\" " + "GPRINT:bitsIn:AVERAGE:\" Avg \\: %8.2lf %s\" " + "GPRINT:bitsIn:MIN:\"Min \\: %8.2lf %s\" " + "GPRINT:bitsIn:MAX:\"Max \\: %8.2lf %s\\n\" " + "LINE2:bitsOut#ff0000:\"Bits Out\" " + "GPRINT:bitsOut:AVERAGE:\"Avg \\: %8.2lf %s\" " + "GPRINT:bitsOut:MIN:\"Min \\: %8.2lf %s\" " + "GPRINT:bitsOut:MAX:\"Max \\: %8.2lf %s\\n\""; PrefabGraph bits = m_graphs.get("mib2.bits").getObject();; assertEquals("getCommand", expectedCommand, bits.getCommand()); } public void testGetExternalValues() { PrefabGraph bits = m_graphs.get("mib2.bits").getObject();; String[] values = bits.getExternalValues(); assertEquals("getExternalValues().length", 1, values.length); assertEquals("getExternalValues()[0]", "ifSpeed", values[0]); } public void testGetExternalValuesEmpty() { PrefabGraph discards = m_graphs.get("mib2.discards").getObject();; assertEquals("getExternalValues().length", 0, discards.getExternalValues().length); } public void testGetPropertiesValues() { PrefabGraph discards = m_graphs.get("mib2.discards").getObject();; String[] values = discards.getPropertiesValues(); assertEquals("getPropertiesValues().length", 1, values.length); assertEquals("getPropertiesValues()[0]", "ifSpeed", values[0]); } public void testGetPropertiesValuesEmpty() { PrefabGraph bits = m_graphs.get("mib2.bits").getObject();; assertEquals("getPropertiesValues().length", 0, bits.getPropertiesValues().length); } public void testGetTypes() { PrefabGraph bits = m_graphs.get("mib2.bits").getObject();; assertNotNull("getTypes", bits.getTypes()); assertEquals("getTypes count", 1, bits.getTypes().length); assertEquals("getTypes 1", "interface", bits.getTypes()[0]); } public void testGetDescription() { PrefabGraph bits = m_graphs.get("mib2.bits").getObject();; assertEquals("getDescription", null, bits.getDescription()); } public void testLoadSnmpGraphProperties() throws Exception { PropertiesGraphDao dao = createPropertiesGraphDao(s_emptyMap, s_emptyMap); dao.loadProperties("foo", new FileSystemResource(ConfigurationTestUtils.getFileForConfigFile("snmp-graph.properties"))); } public void testLoadSnmpAdhocGraphProperties() throws Exception { PropertiesGraphDao dao = createPropertiesGraphDao(s_emptyMap, s_emptyMap); dao.loadAdhocProperties("foo", ConfigurationTestUtils.getInputStreamForConfigFile("snmp-adhoc-graph.properties")); } public void testLoadResponseTimeGraphProperties() throws Exception { PropertiesGraphDao dao = createPropertiesGraphDao(s_emptyMap, s_emptyMap); dao.loadProperties("foo", ConfigurationTestUtils.getInputStreamForConfigFile("response-graph.properties")); } public void testLoadResponseTimeAdhocGraphProperties() throws Exception { PropertiesGraphDao dao = createPropertiesGraphDao(s_emptyMap, s_emptyMap); dao.loadAdhocProperties("foo", ConfigurationTestUtils.getInputStreamForConfigFile("response-adhoc-graph.properties")); } public void testPrefabPropertiesReload() throws Exception { File f = m_fileAnticipator.tempFile("snmp-graph.properties"); m_outputStream = new FileOutputStream(f); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); // Don't include mib2.discards in the reports line String noDiscards = s_prefab.replace(", mib2.discards", ""); m_writer.write(noDiscards); m_writer.close(); m_outputStream.close(); HashMap<String, Resource> perfConfig = new HashMap<String, Resource>(); perfConfig.put("performance", new FileSystemResource(f)); PropertiesGraphDao dao = createPropertiesGraphDao(perfConfig, s_emptyMap); PrefabGraphTypeDao type = dao.findPrefabGraphTypeDaoByName("performance"); assertNotNull("could not get performance prefab graph type", type); assertNotNull("could not get mib2.bits report", type.getQuery("mib2.bits")); assertNull("could get mib2.discards report, but shouldn't have been able to", type.getQuery("mib2.discards")); /* * On UNIX, the resolution of the last modified time is 1 second, * so we need to wait at least that long before rewriting the * file to ensure that we have crossed over into the next second. * At least we're not crossing over with John Edward. * * This also happens to be long enough for * FileReloadContainer.DEFAULT_RELOAD_CHECK_INTERVAL * to pass by. */ Thread.sleep(1100); m_outputStream = new FileOutputStream(f); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_prefab); m_writer.close(); m_outputStream.close(); type = dao.findPrefabGraphTypeDaoByName("performance"); assertNotNull("could not get performance prefab graph type after rewriting config file", type); assertNotNull("could not get mib2.bits report after rewriting config file", type.getQuery("mib2.bits")); assertNotNull("could not get mib2.discards report after rewriting config file", type.getQuery("mib2.discards")); } public void testPrefabPropertiesReloadBad() throws Exception { MockLogAppender.setupLogging(false, "DEBUG"); File f = m_fileAnticipator.tempFile("snmp-graph.properties"); m_outputStream = new FileOutputStream(f); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_prefab); m_writer.close(); m_outputStream.close(); HashMap<String, Resource> perfConfig = new HashMap<String, Resource>(); perfConfig.put("performance", new FileSystemResource(f)); PropertiesGraphDao dao = createPropertiesGraphDao(perfConfig, s_emptyMap); PrefabGraphTypeDao type = dao.findPrefabGraphTypeDaoByName("performance"); assertNotNull("could not get performance prefab graph type", type); assertNotNull("could not get mib2.bits report", type.getQuery("mib2.bits")); assertNotNull("could not get mib2.discards report", type.getQuery("mib2.discards")); Thread.sleep(1100); m_outputStream = new FileOutputStream(f); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); // Don't include the reports line at all so we get an error String noReports = s_prefab.replace("reports=mib2.HCbits, mib2.bits, mib2.discards", ""); m_writer.write(noReports); m_writer.close(); m_outputStream.close(); type = dao.findPrefabGraphTypeDaoByName("performance"); LoggingEvent[] events = MockLogAppender.getEvents(); assertNotNull("logged event list was null", events); assertEquals("should only have received two logged events", 2, events.length); assertEquals("should have received an ERROR event" + events[0], Level.ERROR, events[0].getLevel()); assertEquals("should have received an INFO event" + events[1], Level.INFO, events[1].getLevel()); MockLogAppender.resetEvents(); assertNotNull("could not get performance prefab graph type after rewriting config file", type); assertNotNull("could not get mib2.bits report after rewriting config file", type.getQuery("mib2.bits")); //Expecting the same events again, as the individual graph reload attempts to re-read the config file events = MockLogAppender.getEvents(); assertNotNull("logged event list was null", events); assertEquals("should only have received two logged events", 2, events.length); assertEquals("should have received an ERROR event" + events[0], Level.ERROR, events[0].getLevel()); assertEquals("should have received an INFO event" + events[1], Level.INFO, events[1].getLevel()); MockLogAppender.resetEvents(); assertNotNull("could not get mib2.discards report after rewriting config file", type.getQuery("mib2.discards")); //And again, same events events = MockLogAppender.getEvents(); assertNotNull("logged event list was null", events); assertEquals("should only have received two logged events", 2, events.length); assertEquals("should have received an ERROR event" + events[0], Level.ERROR, events[0].getLevel()); assertEquals("should have received an INFO event" + events[1], Level.INFO, events[1].getLevel()); MockLogAppender.resetEvents(); } public void testAdhocPropertiesReload() throws Exception { File f = m_fileAnticipator.tempFile("snmp-adhoc-graph.properties"); m_outputStream = new FileOutputStream(f); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); // Set the image type to image/cheeesy String cheesy = s_adhoc.replace("image/png", "image/cheesy"); m_writer.write(cheesy); m_writer.close(); m_outputStream.close(); HashMap<String, Resource> adhocConfig = new HashMap<String, Resource>(); adhocConfig.put("performance", new FileSystemResource(f)); PropertiesGraphDao dao = createPropertiesGraphDao(s_emptyMap, adhocConfig); AdhocGraphType type = dao.findAdhocGraphTypeByName("performance"); assertNotNull("could not get performance adhoc graph type", type); assertEquals("image type isn't correct", "image/cheesy", type.getOutputMimeType()); Thread.sleep(1100); m_outputStream = new FileOutputStream(f); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_adhoc); m_writer.close(); m_outputStream.close(); type = dao.findAdhocGraphTypeByName("performance"); assertNotNull("could not get performance adhoc graph type", type); assertEquals("image type isn't correct", "image/png", type.getOutputMimeType()); } public void testNoType() throws Exception { PropertiesGraphDao dao = createPropertiesGraphDao(s_emptyMap, s_emptyMap); String ourConfig = s_responsePrefab.replaceAll("report.icmp.type=responseTime", ""); ByteArrayInputStream in = new ByteArrayInputStream(ourConfig.getBytes()); dao.loadProperties("response", in); PrefabGraphTypeDao type = dao.findPrefabGraphTypeDaoByName("response"); assertNotNull("could not get response prefab graph type", type); PrefabGraph graph = type.getQuery("icmp"); assertNotNull("could not get icmp response prefab graph type", graph); assertNotNull("graph type list should not be null", graph.getTypes()); assertEquals("graph type was not specified the list should be empty", 0, graph.getTypes().length); assertFalse("should not have responseTime type", graph.hasMatchingType("responseTime")); } public void testOneType() throws Exception { PropertiesGraphDao dao = createPropertiesGraphDao(s_emptyMap, s_emptyMap); ByteArrayInputStream in = new ByteArrayInputStream(s_responsePrefab.getBytes()); dao.loadProperties("response", in); PrefabGraphTypeDao type = dao.findPrefabGraphTypeDaoByName("response"); assertNotNull("could not get response prefab graph type", type); PrefabGraph graph = type.getQuery("icmp"); assertNotNull("could not get icmp response prefab graph type", graph); assertNotNull("graph type list should not be null", graph.getTypes()); assertEquals("graph type was not specified the list should be empty", 1, graph.getTypes().length); assertEquals("graph type 1", "responseTime", graph.getTypes()[0]); assertTrue("should have responseTime type", graph.hasMatchingType("responseTime")); assertFalse("should not have distributedStatus type", graph.hasMatchingType("distributedStatus")); assertTrue("should have responseTime or distributedStatus type", graph.hasMatchingType("responseTime", "distributedStatus")); } public void testTwoTypes() throws Exception { PropertiesGraphDao dao = createPropertiesGraphDao(s_emptyMap, s_emptyMap); String ourConfig = s_responsePrefab.replaceAll("report.icmp.type=responseTime", "report.icmp.type=responseTime, distributedStatus"); ByteArrayInputStream in = new ByteArrayInputStream(ourConfig.getBytes()); dao.loadProperties("response", in); PrefabGraphTypeDao type = dao.findPrefabGraphTypeDaoByName("response"); assertNotNull("could not get response prefab graph type", type); PrefabGraph graph = type.getQuery("icmp"); assertNotNull("could not get icmp response prefab graph type", graph); assertNotNull("graph type should not be null", graph.getTypes()); assertEquals("graph type count", 2, graph.getTypes().length); assertEquals("graph type 1", "responseTime", graph.getTypes()[0]); assertEquals("graph type 2", "distributedStatus", graph.getTypes()[1]); assertTrue("should have responseTime type", graph.hasMatchingType("responseTime")); assertTrue("should have distributedStatus type", graph.hasMatchingType("distributedStatus")); } public void testGetPrefabGraphsForResource() { MockResourceType resourceType = new MockResourceType(); resourceType.setName("interface"); HashSet<OnmsAttribute> attributes = new HashSet<OnmsAttribute>(0); attributes.add(new RrdGraphAttribute("ifInOctets", "", "")); attributes.add(new RrdGraphAttribute("ifOutOctets", "", "")); attributes.add(new ExternalValueAttribute("ifSpeed", "")); OnmsResource resource = new OnmsResource("node", "1", resourceType, attributes); PrefabGraph[] graphs = m_dao.getPrefabGraphsForResource(resource); assertEquals("prefab graph array size", 1, graphs.length); assertEquals("prefab graph[0] name", "mib2.bits", graphs[0].getName()); } public void testGetPrefabGraphsForResourceWithSuppress() { MockResourceType resourceType = new MockResourceType(); resourceType.setName("interface"); HashSet<OnmsAttribute> attributes = new HashSet<OnmsAttribute>(0); attributes.add(new RrdGraphAttribute("ifInOctets", "", "")); attributes.add(new RrdGraphAttribute("ifOutOctets", "", "")); attributes.add(new RrdGraphAttribute("ifHCInOctets", "", "")); attributes.add(new RrdGraphAttribute("ifHCOutOctets", "", "")); attributes.add(new ExternalValueAttribute("ifSpeed", "")); OnmsResource resource = new OnmsResource("node", "1", resourceType, attributes); PrefabGraph[] graphs = m_dao.getPrefabGraphsForResource(resource); assertEquals("prefab graph array size", 1, graphs.length); assertEquals("prefab graph[0] name", "mib2.HCbits", graphs[0].getName()); } public void testGetPrefabGraphsForResourceWithSuppressUnused() { MockResourceType resourceType = new MockResourceType(); resourceType.setName("interface"); HashSet<OnmsAttribute> attributes = new HashSet<OnmsAttribute>(0); attributes.add(new RrdGraphAttribute("ifHCInOctets", "", "")); attributes.add(new RrdGraphAttribute("ifHCOutOctets", "", "")); attributes.add(new ExternalValueAttribute("ifSpeed", "")); OnmsResource resource = new OnmsResource("node", "1", resourceType, attributes); PrefabGraph[] graphs = m_dao.getPrefabGraphsForResource(resource); assertEquals("prefab graph array size", 1, graphs.length); assertEquals("prefab graph[0] name", "mib2.HCbits", graphs[0].getName()); } public PropertiesGraphDao createPropertiesGraphDao(Map<String, Resource> prefabConfigs, Map<String, Resource> adhocConfigs) throws IOException { PropertiesGraphDao dao = new PropertiesGraphDao(); dao.setPrefabConfigs(prefabConfigs); dao.setAdhocConfigs(adhocConfigs); dao.afterPropertiesSet(); return dao; } /** * Test that individual graph files in an include directory are loaded as expected */ public void testBasicPrefabConfigDirectorySingleReports() throws IOException { File rootFile = m_fileAnticipator.tempFile("snmp-graph.properties"); File graphDirectory = m_fileAnticipator.tempDir("snmp-graph.properties.d"); File graphBits = m_fileAnticipator.tempFile(graphDirectory, "mib2.bits.properties"); File graphHCbits = m_fileAnticipator.tempFile(graphDirectory, "mib2.HCbits.properties"); m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_baseIncludePrefab); m_writer.close(); m_outputStream.close(); graphDirectory.mkdir(); m_outputStream = new FileOutputStream(graphBits); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateBitsGraph); m_writer.close(); m_outputStream.close(); m_outputStream = new FileOutputStream(graphHCbits); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateHCBitsGraph); m_writer.close(); m_outputStream.close(); HashMap<String, Resource> prefabConfigs = new HashMap<String, Resource>(); prefabConfigs.put("performance", new FileSystemResource(rootFile)); PropertiesGraphDao dao = createPropertiesGraphDao(prefabConfigs, s_emptyMap); PrefabGraph mib2Bits = dao.getPrefabGraph("mib2.bits"); assertNotNull(mib2Bits); assertEquals("mib2.bits", mib2Bits.getName()); assertEquals("Bits In/Out", mib2Bits.getTitle()); String columns1[] = {"ifInOctets","ifOutOctets"}; Assert.assertArrayEquals(columns1, mib2Bits.getColumns()); PrefabGraph mib2HCBits = dao.getPrefabGraph("mib2.HCbits"); assertNotNull(mib2HCBits); assertEquals("mib2.HCbits", mib2HCBits.getName()); assertEquals("Bits In/Out", mib2HCBits.getTitle()); String columns2[] = {"ifHCInOctets","ifHCOutOctets"}; Assert.assertArrayEquals(columns2, mib2HCBits.getColumns()); } /** * Test that properties files in an included directory with * multiple graphs defined in them are loaded correctly */ public void testPrefabConfigDirectoryMultiReports() throws IOException { File rootFile = m_fileAnticipator.tempFile("snmp-graph.properties"); File graphDirectory = m_fileAnticipator.tempDir("snmp-graph.properties.d"); File multiFile1 = m_fileAnticipator.tempFile(graphDirectory, "mib2.bits1.properties"); File multiFile2 = m_fileAnticipator.tempFile(graphDirectory, "mib2.bits2.properties"); m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_baseIncludePrefab); m_writer.close(); m_outputStream.close(); graphDirectory.mkdir(); m_outputStream = new FileOutputStream(multiFile1); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_includedMultiGraph1); m_writer.close(); m_outputStream.close(); m_outputStream = new FileOutputStream(multiFile2); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_includedMultiGraph2); m_writer.close(); m_outputStream.close(); HashMap<String, Resource> prefabConfigs = new HashMap<String, Resource>(); prefabConfigs.put("performance", new FileSystemResource(rootFile)); PropertiesGraphDao dao = createPropertiesGraphDao(prefabConfigs, s_emptyMap); //Check the graphs, basically ensuring that a handful of unique but easily checkable // bits are uniquely what they should be. //We check all 4 graphs PrefabGraph mib2Bits = dao.getPrefabGraph("mib2.bits"); assertNotNull(mib2Bits); assertEquals("mib2.bits", mib2Bits.getName()); assertEquals("Bits In/Out", mib2Bits.getTitle()); String columns1[] = {"ifInOctets","ifOutOctets"}; Assert.assertArrayEquals(columns1, mib2Bits.getColumns()); PrefabGraph mib2HCBits = dao.getPrefabGraph("mib2.HCbits"); assertNotNull(mib2HCBits); assertEquals("mib2.HCbits", mib2HCBits.getName()); assertEquals("Bits In/Out", mib2HCBits.getTitle()); String columns2[] = {"ifHCInOctets","ifHCOutOctets"}; Assert.assertArrayEquals(columns2, mib2HCBits.getColumns()); PrefabGraph mib2Discards = dao.getPrefabGraph("mib2.discards"); assertNotNull(mib2Discards); assertEquals("mib2.discards", mib2Discards.getName()); assertEquals("Discards In/Out", mib2Discards.getTitle()); String columns3[] = {"ifInDiscards","ifOutDiscards"}; Assert.assertArrayEquals(columns3, mib2Discards.getColumns()); PrefabGraph mib2Errors = dao.getPrefabGraph("mib2.errors"); assertNotNull(mib2Errors); assertEquals("mib2.errors", mib2Errors.getName()); assertEquals("Errors In/Out", mib2Errors.getTitle()); String columns4[] = {"ifInErrors","ifOutErrors"}; Assert.assertArrayEquals(columns4, mib2Errors.getColumns()); } /** * Test that properties files in an included directory with * multiple graphs defined in some, and single graphs in others, are loaded correctly */ public void testPrefabConfigDirectoryMixedSingleAndMultiReports() throws IOException { File rootFile = m_fileAnticipator.tempFile("snmp-graph.properties"); File graphDirectory = m_fileAnticipator.tempDir("snmp-graph.properties.d"); File multiFile = m_fileAnticipator.tempFile(graphDirectory, "mib2-1.properties"); File graphBits = m_fileAnticipator.tempFile(graphDirectory, "mib2.bits.properties"); File graphHCbits = m_fileAnticipator.tempFile(graphDirectory, "mib2.HCbits.properties"); m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_baseIncludePrefab); m_writer.close(); m_outputStream.close(); graphDirectory.mkdir(); m_outputStream = new FileOutputStream(graphBits); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateBitsGraph); m_writer.close(); m_outputStream.close(); m_outputStream = new FileOutputStream(graphHCbits); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateHCBitsGraph); m_writer.close(); m_outputStream.close(); graphDirectory.mkdir(); m_outputStream = new FileOutputStream(multiFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_includedMultiGraph1); m_writer.close(); m_outputStream.close(); HashMap<String, Resource> prefabConfigs = new HashMap<String, Resource>(); prefabConfigs.put("performance", new FileSystemResource(rootFile)); PropertiesGraphDao dao = createPropertiesGraphDao(prefabConfigs, s_emptyMap); //Check the graphs, basically ensuring that a handful of unique but easily checkable // bits are uniquely what they should be. //We check all 4 graphs PrefabGraph mib2Bits = dao.getPrefabGraph("mib2.bits"); assertNotNull(mib2Bits); assertEquals("mib2.bits", mib2Bits.getName()); assertEquals("Bits In/Out", mib2Bits.getTitle()); String columns1[] = {"ifInOctets","ifOutOctets"}; Assert.assertArrayEquals(columns1, mib2Bits.getColumns()); PrefabGraph mib2HCBits = dao.getPrefabGraph("mib2.HCbits"); assertNotNull(mib2HCBits); assertEquals("mib2.HCbits", mib2HCBits.getName()); assertEquals("Bits In/Out", mib2HCBits.getTitle()); String columns2[] = {"ifHCInOctets","ifHCOutOctets"}; Assert.assertArrayEquals(columns2, mib2HCBits.getColumns()); PrefabGraph mib2Discards = dao.getPrefabGraph("mib2.discards"); assertNotNull(mib2Discards); assertEquals("mib2.discards", mib2Discards.getName()); assertEquals("Discards In/Out", mib2Discards.getTitle()); String columns3[] = {"ifInDiscards","ifOutDiscards"}; Assert.assertArrayEquals(columns3, mib2Discards.getColumns()); PrefabGraph mib2Errors = dao.getPrefabGraph("mib2.errors"); assertNotNull(mib2Errors); assertEquals("mib2.errors", mib2Errors.getName()); assertEquals("Errors In/Out", mib2Errors.getTitle()); String columns4[] = {"ifInErrors","ifOutErrors"}; Assert.assertArrayEquals(columns4, mib2Errors.getColumns()); } /** * Test that an included single report per file properties config can override * a report in the main properties file. * @throws IOException */ public void testPrefabConfigDirectorySingleReportOverride() throws Exception { File rootFile = m_fileAnticipator.tempFile("snmp-graph.properties"); File graphDirectory = m_fileAnticipator.tempDir("snmp-graph.properties.d"); File graphBits = m_fileAnticipator.tempFile(graphDirectory, "mib2.bits.properties"); File graphHCbits = m_fileAnticipator.tempFile(graphDirectory, "mib2.HCbits.properties"); m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_mib2bitsBasePrefab); m_writer.close(); m_outputStream.close(); graphDirectory.mkdir(); m_outputStream = new FileOutputStream(graphBits); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateBitsGraph); m_writer.close(); m_outputStream.close(); m_outputStream = new FileOutputStream(graphHCbits); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateHCBitsGraph); m_writer.close(); m_outputStream.close(); HashMap<String, Resource> prefabConfigs = new HashMap<String, Resource>(); prefabConfigs.put("performance", new FileSystemResource(rootFile)); PropertiesGraphDao dao = createPropertiesGraphDao(prefabConfigs, s_emptyMap); PrefabGraph mib2Bits = dao.getPrefabGraph("mib2.bits"); assertNotNull(mib2Bits); //The base properties file (s_mib2bitsBasePrefab) has the name=Wrong Name, and columns=wrongColumn1,wrongColumn2. // We check that the overridden graph has the correct details in it assertEquals("mib2.bits", mib2Bits.getName()); assertEquals("Bits In/Out", mib2Bits.getTitle()); String columns1[] = {"ifInOctets","ifOutOctets"}; Assert.assertArrayEquals(columns1, mib2Bits.getColumns()); PrefabGraph mib2HCBits = dao.getPrefabGraph("mib2.HCbits"); assertNotNull(mib2HCBits); assertEquals("mib2.HCbits", mib2HCBits.getName()); assertEquals("Bits In/Out", mib2HCBits.getTitle()); String columns2[] = {"ifHCInOctets","ifHCOutOctets"}; Assert.assertArrayEquals(columns2, mib2HCBits.getColumns()); //Now, having proven that the override works, rewrite the base file with the same data, thus updating the timestamp // and forcing a reload. The mib2.bits graph should still be the correct overridden one. m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_mib2bitsBasePrefab); m_writer.close(); m_outputStream.close(); //Wait long enough to make the FileReloadContainers do their thing reliably Thread.sleep(1100); //Ensure that the override still applies and hasn't been "underridden" by the rewrite of the base file. mib2Bits = dao.getPrefabGraph("mib2.bits"); assertNotNull(mib2Bits); assertEquals("mib2.bits", mib2Bits.getName()); assertEquals("Bits In/Out", mib2Bits.getTitle()); String columns3[] = {"ifInOctets","ifOutOctets"}; Assert.assertArrayEquals(columns3, mib2Bits.getColumns()); } public void testPrefabPropertiesIncludeDirectoryReloadSingleReports() throws Exception { File rootFile = m_fileAnticipator.tempFile("snmp-graph.properties"); File graphDirectory = m_fileAnticipator.tempDir("snmp-graph.properties.d"); File graphBits = m_fileAnticipator.tempFile(graphDirectory, "mib2.bits.properties"); m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_baseIncludePrefab); m_writer.close(); m_outputStream.close(); graphDirectory.mkdir(); m_outputStream = new FileOutputStream(graphBits); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateBitsGraph); m_writer.close(); m_outputStream.close(); HashMap<String, Resource> perfConfig = new HashMap<String, Resource>(); perfConfig.put("performance", new FileSystemResource(rootFile)); PropertiesGraphDao dao = createPropertiesGraphDao(perfConfig, s_emptyMap); PrefabGraph graph = dao.getPrefabGraph("mib2.bits"); assertNotNull("could not get mib2.bits report", graph); assertEquals("ifSpeed", graph.getExternalValues()[0]); Thread.sleep(1100); m_outputStream = new FileOutputStream(graphBits); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateBitsGraph.replace("ifSpeed", "anotherExternalValue")); m_writer.close(); m_outputStream.close(); graph = dao.getPrefabGraph("mib2.bits"); assertNotNull("could not get mib2.bits report after rewriting config file", graph); assertEquals("anotherExternalValue", graph.getExternalValues()[0]); } /** * Test that reloading a badly formatted single report doens't overwrite a previously functioning * report. * * NB: It should still complain with an Error log. Should there be an event as well? * @throws Exception */ public void testPrefabPropertiesIncludeDirectoryBadReloadSingleReport() throws Exception { //We're expecting an ERROR log, and will be most disappointed if // we don't get it. Turn off the default check in runTest testSpecificLoggingTest = true; File rootFile = m_fileAnticipator.tempFile("snmp-graph.properties"); File graphDirectory = m_fileAnticipator.tempDir("snmp-graph.properties.d"); File graphBits = m_fileAnticipator.tempFile(graphDirectory, "mib2.bits.properties"); m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_baseIncludePrefab); m_writer.close(); m_outputStream.close(); graphDirectory.mkdir(); m_outputStream = new FileOutputStream(graphBits); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateBitsGraph); m_writer.close(); m_outputStream.close(); HashMap<String, Resource> perfConfig = new HashMap<String, Resource>(); perfConfig.put("performance", new FileSystemResource(rootFile)); PropertiesGraphDao dao = createPropertiesGraphDao(perfConfig, s_emptyMap); PrefabGraph graph = dao.getPrefabGraph("mib2.bits"); assertNotNull("could not get mib2.bits report", graph); assertEquals("ifSpeed", graph.getExternalValues()[0]); Thread.sleep(1100); m_outputStream = new FileOutputStream(graphBits); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); //Two changes: // 1) Remove a required property; this should break the reading of the new file // 2) Change the externalvalues attribute name; we shouldn't see that new name after the reload m_writer.write(s_separateBitsGraph.replace("report.name", "report.fluggle").replace("ifSpeed", "anotherExternalValue")); m_writer.close(); m_outputStream.close(); graph = dao.getPrefabGraph("mib2.bits"); assertNotNull("could not get mib2.bits report after rewriting config file", graph); assertEquals("ifSpeed", graph.getExternalValues()[0]); //There should have been an error log about the reload failure MockLogAppender.assertLogAtLevel(Level.ERROR); } /** * Test that we can load a partly borked config file (i.e. if one graph is incorrectly specified, * we load as many of the rest as we can). * The borked'ness we can tolerate does not include poor double quoting which confuses the underlying * Java properties parser, but misspelled property names should only affect the graph in question. * * NB: It should still complain with an Error log. Should there be an event as well? * @throws Exception */ public void testPrefabGraphPartlyBorkedConfig() throws Exception { //We're expecting an ERROR log, and will be most disappointed if // we don't get it. Turn off the default check in runTest testSpecificLoggingTest = true; PropertiesGraphDao dao = createPropertiesGraphDao(s_emptyMap, s_emptyMap); dao.loadProperties("foo", new ByteArrayInputStream(s_partlyBorkedPrefab.getBytes("UTF-8"))); //We expect to be able to get a mib2.HCbits, and a mib2.discards, but no mib2.bits try { PrefabGraph mib2bits = dao.getPrefabGraph("mib2.bits"); fail("Should have thrown an ObjectRetrievalFailureException retrieving graph "+mib2bits); } catch (ObjectRetrievalFailureException e) { } PrefabGraph mib2HCbits = dao.getPrefabGraph("mib2.HCbits"); assertNotNull(mib2HCbits); PrefabGraph mib2Discards = dao.getPrefabGraph("mib2.discards"); assertNotNull(mib2Discards); //There should have been an error log about the failure MockLogAppender.assertLogAtLevel(Level.ERROR); } /** * Test that adding a "include.directory" property to the main graph config file * will cause included files to be read on reload of the main config file * (early code didn't do this right) * @throws Exception */ public void testAddingIncludeDirectory() throws Exception { File rootFile = m_fileAnticipator.tempFile("snmp-graph.properties"); m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_prefab); m_writer.close(); m_outputStream.close(); HashMap<String, Resource> perfConfig = new HashMap<String, Resource>(); perfConfig.put("performance", new FileSystemResource(rootFile)); PropertiesGraphDao dao = createPropertiesGraphDao(perfConfig, s_emptyMap); assertNotNull(dao.getPrefabGraph("mib2.bits")); try { PrefabGraph mib2errors = dao.getPrefabGraph("mib2.errors"); fail("Should have thrown an ObjectRetrievalFailureException retrieving graph " + mib2errors); } catch (ObjectRetrievalFailureException e) { } //Wait long enough to make the FileReloadContainers do their thing reliably Thread.sleep(1100); //Now create the new graph in a sub-directory, and rewrite the rootFile with an include.directory property File graphDirectory = m_fileAnticipator.tempDir("snmp-graph.properties.d"); File graphErrors = m_fileAnticipator.tempFile(graphDirectory, "mib2.errors.properties"); graphDirectory.mkdir(); m_outputStream = new FileOutputStream(graphErrors); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateErrorsGraph); m_writer.close(); m_outputStream.close(); m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_prefab.replace("output.mime", "include.directory=snmp-graph.properties.d\n" + "output.mime")); m_writer.close(); m_outputStream.close(); assertNotNull(dao.getPrefabGraph("mib2.bits")); //Just checking the reload didn't lose existing graphs assertNotNull(dao.getPrefabGraph("mib2.errors")); //This is the core: this graph should have been picked up } /** * Test that adding a new properties file into an included directory * will be picked up. Requires the include.directory.rescan to be set low * @throws Exception */ public void testIncludeDirectoryNewFile() throws Exception { File rootFile = m_fileAnticipator.tempFile("snmp-graph.properties"); m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_baseIncludePrefab); m_writer.close(); m_outputStream.close(); File graphDirectory = m_fileAnticipator.tempDir("snmp-graph.properties.d"); graphDirectory.mkdir(); HashMap<String, Resource> perfConfig = new HashMap<String, Resource>(); perfConfig.put("performance", new FileSystemResource(rootFile)); PropertiesGraphDao dao = createPropertiesGraphDao(perfConfig, s_emptyMap); try { PrefabGraph mib2errors = dao.getPrefabGraph("mib2.errors"); fail("Should have thrown an ObjectRetrievalFailureException retrieving graph " + mib2errors); } catch (ObjectRetrievalFailureException e) { } //Now create the new graph in a sub-directory; see if it gets read File graphErrors = m_fileAnticipator.tempFile(graphDirectory, "mib2.errors.properties"); m_outputStream = new FileOutputStream(graphErrors); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateErrorsGraph); m_writer.close(); m_outputStream.close(); //Wait longer than the rescan timeout on the include directory Thread.sleep(1100); assertNotNull(dao.getPrefabGraph("mib2.errors")); //This is the core: this graph should have been picked up } public void testIncludeDirectoryIncludeMissingReportId() throws Exception { //We're expecting an ERROR log, and will be most disappointed if // we don't get it. Turn off the default check in runTest testSpecificLoggingTest = true; File rootFile = m_fileAnticipator.tempFile("snmp-graph.properties"); File graphDirectory = m_fileAnticipator.tempDir("snmp-graph.properties.d"); File graphBits = m_fileAnticipator.tempFile(graphDirectory, "mib2.bits.properties"); m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_baseIncludePrefab); m_writer.close(); m_outputStream.close(); graphDirectory.mkdir(); m_outputStream = new FileOutputStream(graphBits); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateBitsGraph.replace("report.id", "report.noid")); m_writer.close(); m_outputStream.close(); HashMap<String, Resource> perfConfig = new HashMap<String, Resource>(); perfConfig.put("performance", new FileSystemResource(rootFile)); PropertiesGraphDao dao = createPropertiesGraphDao(perfConfig,s_emptyMap); try { PrefabGraph graph = dao.getPrefabGraph("mib2.bits"); fail("Shouldn't have gotten here; expecting an exception fetching "+graph); } catch (ObjectRetrievalFailureException e) { //Expected; no such graph } //There should have been an error log about the reload failure (but no exception) MockLogAppender.assertLogAtLevel(Level.ERROR); } /** * It would be nice if having found a new file in the include directory that was malformed, that * when it is fixed, it is picked up immediately, rather than having to wait for the next rescan interval */ public void testIncludeNewFileMalformedContentThenFixed() throws Exception { //Don't do the normal checking of logging for worse than warning; we expect an error or two to be logged, and that's fine testSpecificLoggingTest = true; File rootFile = m_fileAnticipator.tempFile("snmp-graph.properties"); m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_baseIncludePrefab); m_writer.close(); m_outputStream.close(); File graphDirectory = m_fileAnticipator.tempDir("snmp-graph.properties.d"); graphDirectory.mkdir(); HashMap<String, Resource> perfConfig = new HashMap<String, Resource>(); perfConfig.put("performance", new FileSystemResource(rootFile)); PropertiesGraphDao dao = createPropertiesGraphDao(perfConfig, s_emptyMap); try { PrefabGraph mib2errors = dao.getPrefabGraph("mib2.errors"); fail("Should have thrown an ObjectRetrievalFailureException retrieving graph " + mib2errors); } catch (ObjectRetrievalFailureException e) { } //Now create the new graph in a sub-directory but make it malformed; make sure it isn't loaded File graphErrors = m_fileAnticipator.tempFile(graphDirectory, "mib2.errors.properties"); m_outputStream = new FileOutputStream(graphErrors); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateErrorsGraph.replace("report.id", "report.noid")); m_writer.close(); m_outputStream.close(); //Wait longer than the rescan timeout on the include directory Thread.sleep(1100); //Confirm that the graph still hasn't been loaded (because it was munted) try { PrefabGraph mib2errors = dao.getPrefabGraph("mib2.errors"); fail("Should have thrown an ObjectRetrievalFailureException retrieving graph " + mib2errors); } catch (ObjectRetrievalFailureException e) { } //Now set the include rescan interval to a large number, rewrite the graph correctly, and check // that the file is loaded (and we don't have to wait for the rescan interval) dao.findPrefabGraphTypeByName("performance").setIncludeDirectoryRescanInterval(300000); //5 minutes m_outputStream = new FileOutputStream(graphErrors); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_separateErrorsGraph); m_writer.close(); m_outputStream.close(); //Just make sure any timestamps will be at least 1 second old, just to be sure Thread.sleep(1100); //And now the graph should have loaded try { assertNotNull(dao.getPrefabGraph("mib2.errors")); //This is the core: this graph should have been picked up } catch (Exception e) { //Catch exceptions and fail explicitly, because that's a failure, not an "error" fail("Should not have gotten an exception fetching the graph"); } } /** * Test that when loading graphs from files in the include directory, that if one of * the graphs defined in one of the multi-graph files is borked, the rest load correctly * * Then also check that on setting the reload interval high, that the borked graph is * noticed immediately when we fix it * @throws IOException */ public void testPrefabConfigDirectoryPartlyBorkedMultiReports() throws Exception { //Don't do the normal checking of logging for worse than warning; we expect an error or two to be logged, and that's fine testSpecificLoggingTest = true; File rootFile = m_fileAnticipator.tempFile("snmp-graph.properties"); File graphDirectory = m_fileAnticipator.tempDir("snmp-graph.properties.d"); File multiFile1 = m_fileAnticipator.tempFile(graphDirectory, "mib2.bits1.properties"); File multiFile2 = m_fileAnticipator.tempFile(graphDirectory, "mib2.bits2.properties"); m_outputStream = new FileOutputStream(rootFile); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_baseIncludePrefab); m_writer.close(); m_outputStream.close(); graphDirectory.mkdir(); m_outputStream = new FileOutputStream(multiFile1); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); //Make mib2.errors incorrectly specified m_writer.write(s_includedMultiGraph1.replace("report.mib2.errors.name", "report.mib2.errors.nmae")); m_writer.close(); m_outputStream.close(); m_outputStream = new FileOutputStream(multiFile2); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); m_writer.write(s_includedMultiGraph2); m_writer.close(); m_outputStream.close(); HashMap<String, Resource> prefabConfigs = new HashMap<String, Resource>(); prefabConfigs.put("performance", new FileSystemResource(rootFile)); PropertiesGraphDao dao = createPropertiesGraphDao(prefabConfigs, s_emptyMap); //Check the graphs, basically ensuring that a handful of unique but easily checkable // bits are uniquely what they should be. //We check all 4 graphs PrefabGraph mib2Bits = dao.getPrefabGraph("mib2.bits"); assertNotNull(mib2Bits); assertEquals("mib2.bits", mib2Bits.getName()); assertEquals("Bits In/Out", mib2Bits.getTitle()); String columns1[] = { "ifInOctets", "ifOutOctets" }; Assert.assertArrayEquals(columns1, mib2Bits.getColumns()); PrefabGraph mib2HCBits = dao.getPrefabGraph("mib2.HCbits"); assertNotNull(mib2HCBits); assertEquals("mib2.HCbits", mib2HCBits.getName()); assertEquals("Bits In/Out", mib2HCBits.getTitle()); String columns2[] = { "ifHCInOctets", "ifHCOutOctets" }; Assert.assertArrayEquals(columns2, mib2HCBits.getColumns()); PrefabGraph mib2Discards = dao.getPrefabGraph("mib2.discards"); assertNotNull(mib2Discards); assertEquals("mib2.discards", mib2Discards.getName()); assertEquals("Discards In/Out", mib2Discards.getTitle()); String columns3[] = { "ifInDiscards", "ifOutDiscards" }; Assert.assertArrayEquals(columns3, mib2Discards.getColumns()); try { PrefabGraph mib2Errors = dao.getPrefabGraph("mib2.errors"); fail("Should have thrown an ObjectRetrievalFailureException retrieving graph " + mib2Errors); } catch (ObjectRetrievalFailureException e) { //This is ok, and what should have happened } //Now set the include rescan interval to a large number, rewrite the multigraph file correctly, and check // that the file is loaded (and we don't have to wait for the rescan interval) dao.findPrefabGraphTypeByName("performance").setIncludeDirectoryRescanInterval(300000); //5 minutes //Just make sure any timestamps will be at least 1 second old, just to be sure that the file timestamp // will be 1 second in the past Thread.sleep(1100); m_outputStream = new FileOutputStream(multiFile1); m_writer = new OutputStreamWriter(m_outputStream, "UTF-8"); //Correctly specified graph file now (error corrected) m_writer.write(s_includedMultiGraph1); m_writer.close(); m_outputStream.close(); //And now the graph should have loaded correctly try { assertNotNull(dao.getPrefabGraph("mib2.errors")); } catch (Exception e) { //Catch exceptions and fail explicitly, because that's a failure, not an "error" fail("Should not have gotten an exception fetching the graph"); } } }