/******************************************************************************* * 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.syslogd; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.opennms.core.utils.InetAddressUtils.addr; import java.io.InputStream; import java.lang.reflect.UndeclaredThrowableException; import java.net.BindException; import java.net.DatagramPacket; import java.net.UnknownHostException; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.apache.commons.io.IOUtils; import org.apache.log4j.Level; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.opennms.core.concurrent.WaterfallExecutor; import org.opennms.core.test.MockLogAppender; import org.opennms.core.test.OpenNMSJUnit4ClassRunner; import org.opennms.core.utils.BeanUtils; import org.opennms.netmgt.config.SyslogdConfig; import org.opennms.netmgt.config.SyslogdConfigFactory; import org.opennms.netmgt.config.syslogd.UeiMatch; import org.opennms.netmgt.dao.db.JUnitConfigurationEnvironment; import org.opennms.netmgt.dao.db.JUnitTemporaryDatabase; import org.opennms.netmgt.mock.EventAnticipator; import org.opennms.netmgt.mock.MockDatabase; import org.opennms.netmgt.mock.MockEventIpcManager; import org.opennms.netmgt.model.events.EventBuilder; import org.opennms.netmgt.xml.event.Event; import org.opennms.netmgt.xml.event.Parm; import org.opennms.test.ConfigurationTestUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.transaction.annotation.Transactional; @RunWith(OpenNMSJUnit4ClassRunner.class) @ContextConfiguration(locations={ "classpath:/META-INF/opennms/applicationContext-dao.xml", "classpath*:/META-INF/opennms/component-dao.xml", "classpath:/META-INF/opennms/applicationContext-daemon.xml", "classpath:/META-INF/opennms/mockEventIpcManager.xml", "classpath:/META-INF/opennms/applicationContext-setupIpLike-enabled.xml", "classpath:/META-INF/opennms/applicationContext-databasePopulator.xml", "classpath:/META-INF/opennms/applicationContext-minimal-conf.xml" }) @JUnitConfigurationEnvironment @JUnitTemporaryDatabase(dirtiesContext=false,tempDbClass=MockDatabase.class) @Transactional public class SyslogdTest implements InitializingBean { String m_localhost = "127.0.0.1"; private Syslogd m_syslogd; private final List<ExecutorService> m_executorServices = Arrays.asList(new ExecutorService[] { Executors.newFixedThreadPool(3), Executors.newFixedThreadPool(3) }); @Autowired private MockEventIpcManager m_eventIpcManager; @Override public void afterPropertiesSet() throws Exception { BeanUtils.assertAutowiring(this); } @Before public void setUp() throws Exception { MockLogAppender.setupLogging(); InputStream stream = null; try { stream = ConfigurationTestUtils.getInputStreamForResource(this, "/etc/syslogd-configuration.xml"); SyslogdConfigFactory.setInstance(new SyslogdConfigFactory(stream)); } finally { if (stream != null) { IOUtils.closeQuietly(stream); } } m_syslogd = new Syslogd(); m_syslogd.init(); // Verify that the test syslogd-configuration.xml file was loaded boolean foundBeer = false; boolean foundMalt = false; assertEquals(10514, SyslogdConfigFactory.getInstance().getSyslogPort()); for (final UeiMatch match : SyslogdConfigFactory.getInstance().getUeiList().getUeiMatch()) { if (match.getProcessMatch() != null) { if (!foundBeer && "beerd".equals(match.getProcessMatch().getExpression())) { foundBeer = true; } else if (!foundMalt && "maltd".equals(match.getProcessMatch().getExpression())) { foundMalt = true; } } } assertTrue(foundBeer); assertTrue(foundMalt); } @After public void tearDown() throws Exception { MockLogAppender.assertNotGreaterOrEqual(Level.FATAL); } /** * Send a raw syslog message and expect a given event as a result * * @param testPDU The raw syslog message as it would appear on the wire (just the UDP payload) * @param expectedHost The host from which the event should be resolved as originating * @param expectedUEI The expected UEI of the resulting event * @param expectedLogMsg The expected contents of the logmsg for the resulting event * * @throws UnknownHostException * @throws InterruptedException * @throws ExecutionException */ private List<Event> doMessageTest(String testPDU, String expectedHost, String expectedUEI, String expectedLogMsg) throws UnknownHostException, InterruptedException, ExecutionException { startSyslogdGracefully(); final EventBuilder expectedEventBldr = new EventBuilder(expectedUEI, "syslogd"); expectedEventBldr.setInterface(addr(expectedHost)); expectedEventBldr.setLogDest("logndisplay"); expectedEventBldr.setLogMessage(expectedLogMsg); final EventAnticipator ea = new EventAnticipator(); m_eventIpcManager.addEventListener(ea); ea.anticipateEvent(expectedEventBldr.getEvent()); final SyslogClient sc = new SyslogClient(null, 10, SyslogClient.LOG_DAEMON); final DatagramPacket pkt = sc.getPacket(SyslogClient.LOG_DEBUG, testPDU); final SyslogdConfig config = SyslogdConfigFactory.getInstance(); WaterfallExecutor.waterfall(m_executorServices, new SyslogConnection(pkt, config.getForwardingRegexp(), config.getMatchingGroupHost(), config.getMatchingGroupMessage(), config.getUeiList(), config.getHideMessages(), config.getDiscardUei())); ea.verifyAnticipated(5000,0,0,0,0); final Event receivedEvent = ea.getAnticipatedEventsRecieved().get(0); assertEquals("Log messages do not match", expectedLogMsg, receivedEvent.getLogmsg().getContent()); return ea.getAnticipatedEventsRecieved(); } private List<Event> doMessageTest(String testPDU, String expectedHost, String expectedUEI, String expectedLogMsg, Map<String,String> expectedParams) throws UnknownHostException, InterruptedException, ExecutionException { final List<Event> receivedEvents = doMessageTest(testPDU, expectedHost, expectedUEI, expectedLogMsg); final Map<String,String> actualParms = new HashMap<String,String>(); for (final Parm actualParm : receivedEvents.get(0).getParmCollection()) { actualParms.put(actualParm.getParmName(), actualParm.getValue().getContent()); } for (final String expectedKey : expectedParams.keySet()) { final String expectedValue = expectedParams.get(expectedKey); assertTrue("Actual event does not have a parameter called " + expectedKey, actualParms.containsKey(expectedKey)); assertEquals("Actual event has a parameter called " + expectedKey + " but its value does not match", expectedValue, actualParms.get(expectedKey)); } return receivedEvents; } @Test public void testMessaging() { // More of an integrations test // relies on you reading some of the logging.... SyslogClient s = null; try { s = new SyslogClient(null, 0, SyslogClient.LOG_DAEMON); s.syslog(SyslogClient.LOG_ERR, "Hello."); } catch (UnknownHostException e) { //Failures are for weenies } } @Test public void testMyPatternsSyslogNG() { SyslogClient s = null; try { s = new SyslogClient(null, 10, SyslogClient.LOG_DAEMON); s.syslog(SyslogClient.LOG_DEBUG, "2007-01-01 host.domain.com A SyslogNG style message"); } catch (UnknownHostException e) { //Failures are for weenies } } @Test public void testRegexSeverityMatch() throws Exception { startSyslogdGracefully(); MockLogAppender.setupLogging(true, "TRACE"); String localhost = m_localhost; final String testPDU = "2007-01-01 127.0.0.1 beer - Not just for dinner anymore"; final String testUEI = "uei.opennms.org/tests/syslogd/nonMessageMatch/severityOnly"; final String testMsg = "beer - Not just for dinner anymore"; final EventBuilder expectedEventBldr = new EventBuilder(testUEI, "syslogd"); expectedEventBldr.setInterface(addr(localhost)); expectedEventBldr.setLogDest("logndisplay"); expectedEventBldr.setLogMessage(testMsg); final EventAnticipator ea = new EventAnticipator(); m_eventIpcManager.addEventListener(ea); ea.anticipateEvent(expectedEventBldr.getEvent()); SyslogClient s = null; try { s = new SyslogClient(null, 10, SyslogClient.LOG_DAEMON); s.syslog(SyslogClient.LOG_CRIT, testPDU); } catch (UnknownHostException uhe) { //Failures are for weenies } ea.verifyAnticipated(5000, 0, 0, 0, 0); } @Test public void testRegexFacilitySeverityProcessMatch() throws Exception { startSyslogdGracefully(); MockLogAppender.setupLogging(true, "TRACE"); String localhost = m_localhost; final String testPDU = "2007-01-01 127.0.0.1 maltd: beer - Not just for lunch anymore"; final String testUEI = "uei.opennms.org/tests/syslogd/nonMessageMatch/facilitySeverityProcess"; final String testMsg = "beer - Not just for lunch anymore"; final EventBuilder expectedEventBldr = new EventBuilder(testUEI, "syslogd"); expectedEventBldr.setInterface(addr(localhost)); expectedEventBldr.setLogDest("logndisplay"); expectedEventBldr.setLogMessage(testMsg); expectedEventBldr.addParam("process", "maltd"); expectedEventBldr.addParam("service", "local1"); expectedEventBldr.addParam("severity", "Warning"); final EventAnticipator ea = new EventAnticipator(); m_eventIpcManager.addEventListener(ea); ea.anticipateEvent(expectedEventBldr.getEvent()); SyslogClient s = null; try { s = new SyslogClient("maltd", 10, SyslogClient.LOG_LOCAL1); s.syslog(SyslogClient.LOG_WARNING, testPDU); } catch (UnknownHostException uhe) { //Failures are for weenies } ea.verifyAnticipated(5000, 0, 0, 0, 0); } @Test public void testRegexFacilitySeverityMatch() throws Exception { startSyslogdGracefully(); MockLogAppender.setupLogging(true, "TRACE"); final String localhost = m_localhost; final String testPDU = "2007-01-01 127.0.0.1 beer - Not just for lunch anymore"; final String testUEI = "uei.opennms.org/tests/syslogd/nonMessageMatch/facilitySeverity"; final String testMsg = "beer - Not just for lunch anymore"; final EventBuilder expectedEventBldr = new EventBuilder(testUEI, "syslogd"); expectedEventBldr.setInterface(addr(localhost)); expectedEventBldr.setLogDest("logndisplay"); expectedEventBldr.setLogMessage(testMsg); expectedEventBldr.addParam("service", "local1"); expectedEventBldr.addParam("severity", "Warning"); final EventAnticipator ea = new EventAnticipator(); m_eventIpcManager.addEventListener(ea); ea.anticipateEvent(expectedEventBldr.getEvent()); SyslogClient s = null; try { s = new SyslogClient(null, 10, SyslogClient.LOG_LOCAL1); s.syslog(SyslogClient.LOG_WARNING, testPDU); } catch (UnknownHostException uhe) { //Failures are for weenies } ea.verifyAnticipated(5000, 0, 0, 0, 0); } @Test public void testRegexFacilityMatch() throws Exception { startSyslogdGracefully(); MockLogAppender.setupLogging(true, "TRACE"); final String localhost = m_localhost; final String testPDU = "2007-01-01 127.0.0.1 beer - Not just for lunch anymore"; final String testUEI = "uei.opennms.org/tests/syslogd/nonMessageMatch/facilityOnly"; final String testMsg = "beer - Not just for lunch anymore"; final EventBuilder expectedEventBldr = new EventBuilder(testUEI, "syslogd"); expectedEventBldr.setInterface(addr(localhost)); expectedEventBldr.setLogDest("logndisplay"); expectedEventBldr.setLogMessage(testMsg); expectedEventBldr.addParam("service", "local0"); final EventAnticipator ea = new EventAnticipator(); m_eventIpcManager.addEventListener(ea); ea.anticipateEvent(expectedEventBldr.getEvent()); SyslogClient s = null; try { s = new SyslogClient(null, 10, SyslogClient.LOG_LOCAL0); s.syslog(SyslogClient.LOG_DEBUG, testPDU); } catch (UnknownHostException uhe) { //Failures are for weenies } ea.verifyAnticipated(5000, 0, 0, 0, 0); } @Test public void testRegexProcessMatch() throws Exception { startSyslogdGracefully(); MockLogAppender.setupLogging(true, "TRACE"); final String localhost = m_localhost; final String testPDU = "2007-01-01 127.0.0.1 beerd: beer - Not just for breakfast anymore"; final String testUEI = "uei.opennms.org/tests/syslogd/nonMessageMatch/processOnly"; final String testMsg = "beer - Not just for breakfast anymore"; final EventBuilder expectedEventBldr = new EventBuilder(testUEI, "syslogd"); expectedEventBldr.setInterface(addr(localhost)); expectedEventBldr.setLogDest("logndisplay"); expectedEventBldr.setLogMessage(testMsg); expectedEventBldr.addParam("process", "beerd"); final EventAnticipator ea = new EventAnticipator(); m_eventIpcManager.addEventListener(ea); ea.anticipateEvent(expectedEventBldr.getEvent()); SyslogClient s = null; try { s = new SyslogClient("beerd", 10, SyslogClient.LOG_DAEMON); s.syslog(SyslogClient.LOG_DEBUG, testPDU); } catch (UnknownHostException uhe) { //Failures are for weenies } ea.verifyAnticipated(5000, 0, 0, 0, 0); } @Test public void testIPPatternsSyslogNG() { SyslogClient s = null; try { s = new SyslogClient(null, 10, SyslogClient.LOG_DAEMON); s.syslog(SyslogClient.LOG_DEBUG, "2007-01-01 127.0.0.1 A SyslogNG style message"); } catch (UnknownHostException e) { //Failures are for weenies } } @Test public void testResolvePatternsSyslogNG() { SyslogClient s = null; try { s = new SyslogClient(null, 10, SyslogClient.LOG_DAEMON); s.syslog(SyslogClient.LOG_DEBUG, "2007-01-01 www.opennms.org A SyslogNG style message"); } catch (UnknownHostException e) { //Failures are for weenies } } private void startSyslogdGracefully() { try { m_syslogd.start(); } catch (UndeclaredThrowableException ute) { if (ute.getCause() instanceof BindException) { // continue, this was expected } else { throw ute; } } } @Test public void testSubstrUEIRewrite() throws Exception { doMessageTest("2007-01-01 localhost A CRISCO message", m_localhost, "uei.opennms.org/tests/syslogd/substrUeiRewriteTest", "A CRISCO message"); } @Test public void testRegexUEIRewrite() throws Exception { MockLogAppender.setupLogging(true, "TRACE"); doMessageTest("2007-01-01 localhost foo: 100 out of 666 tests failed for bar", m_localhost, "uei.opennms.org/tests/syslogd/regexUeiRewriteTest", "100 out of 666 tests failed for bar"); } @Test public void testSubstrTESTTestThatRemovesATESTString() throws Exception { doMessageTest("2007-01-01 localhost A CRISCO message that is also a TESTHIDING message -- hide me!", m_localhost, "uei.opennms.org/tests/syslogd/substrUeiRewriteTest", ConvertToEvent.HIDDEN_MESSAGE); } @Test public void testRegexTESTTestThatRemovesADoubleSecretString() throws Exception { doMessageTest("2007-01-01 localhost foo: 100 out of 666 tests failed for doubleSecret", m_localhost, "uei.opennms.org/tests/syslogd/regexUeiRewriteTest", ConvertToEvent.HIDDEN_MESSAGE); } @Test public void testSubstrDiscard() throws Exception { startSyslogdGracefully(); final String testPDU = "2007-01-01 127.0.0.1 A JUNK message"; final EventAnticipator ea = new EventAnticipator(); m_eventIpcManager.addEventListener(ea); SyslogClient sc = null; sc = new SyslogClient(null, 10, SyslogClient.LOG_DAEMON); sc.syslog(SyslogClient.LOG_DEBUG, testPDU); ea.verifyAnticipated(5000, 0, 0, 0, 0); } @Test public void testRegexDiscard() throws Exception { startSyslogdGracefully(); final String testPDU = "2007-01-01 127.0.0.1 A TrAsH message"; final EventAnticipator ea = new EventAnticipator(); m_eventIpcManager.addEventListener(ea); SyslogClient sc = null; sc = new SyslogClient(null, 10, SyslogClient.LOG_DAEMON); sc.syslog(SyslogClient.LOG_DEBUG, testPDU); ea.verifyAnticipated(5000, 0, 0, 0, 0); } @Test public void testRegexUEIWithBothKindsOfParameterAssignments() throws Exception { final String testPDU = "2007-01-01 127.0.0.1 coffee: Secretly replaced rangerrick's coffee with 42 wombats"; final String expectedUEI = "uei.opennms.org/tests/syslogd/regexParameterAssignmentTest/bothKinds"; final String expectedLogMsg = "Secretly replaced rangerrick's coffee with 42 wombats"; final String[] testGroups = { "rangerrick's", "42", "wombats" }; final Map<String,String> expectedParms = new HashMap<String,String>(); expectedParms.put("group1", testGroups[0]); expectedParms.put("whoseBeverage", testGroups[0]); expectedParms.put("group2", testGroups[1]); expectedParms.put("count", testGroups[1]); expectedParms.put("group3", testGroups[2]); expectedParms.put("replacementItem", testGroups[2]); doMessageTest(testPDU, m_localhost, expectedUEI, expectedLogMsg, expectedParms); } @Test public void testRegexUEIWithOnlyUserSpecifiedParameterAssignments() throws InterruptedException { startSyslogdGracefully(); final String localhost = m_localhost; final String testPDU = "2007-01-01 127.0.0.1 tea: Secretly replaced cmiskell's tea with 666 ferrets"; final String testUEI = "uei.opennms.org/tests/syslogd/regexParameterAssignmentTest/userSpecifiedOnly"; final String testMsg = "Secretly replaced cmiskell's tea with 666 ferrets"; final String[] testGroups = { "cmiskell's", "666", "ferrets" }; final EventBuilder expectedEventBldr = new EventBuilder(testUEI, "syslogd"); expectedEventBldr.setInterface(addr(localhost)); expectedEventBldr.setLogDest("logndisplay"); expectedEventBldr.setLogMessage(testMsg); expectedEventBldr.addParam("whoseBeverage", testGroups[0]); expectedEventBldr.addParam("count", testGroups[1]); expectedEventBldr.addParam("replacementItem", testGroups[2]); final EventAnticipator ea = new EventAnticipator(); m_eventIpcManager.addEventListener(ea); ea.anticipateEvent(expectedEventBldr.getEvent()); SyslogClient s = null; try { s = new SyslogClient(null, 10, SyslogClient.LOG_DAEMON); s.syslog(SyslogClient.LOG_DEBUG, testPDU); } catch (UnknownHostException uhe) { //Failures are for weenies } ea.verifyAnticipated(5000, 0, 0, 0, 0); } }