/*******************************************************************************
* 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/
*******************************************************************************/
/*
* Created on Nov 11, 2004
*/
package org.opennms.netmgt.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.opennms.core.xml.JaxbUtils;
import org.opennms.netmgt.model.events.EventBuilder;
import org.opennms.netmgt.xml.eventconf.AlarmData;
import org.opennms.netmgt.xml.eventconf.Event;
import org.opennms.netmgt.xml.eventconf.Events;
import org.opennms.test.ConfigurationTestUtils;
import org.opennms.test.DaoTestConfigBean;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException;
import org.springframework.util.StringUtils;
/**
* @author brozow
*
*/
public class EventconfFactoryTest {
private static final String knownUEI1="uei.opennms.org/internal/capsd/snmpConflictsWithDb";
private static final String knownLabel1="OpenNMS-defined capsd event: snmpConflictsWithDb";
private static final String knownSubfileUEI1="uei.opennms.org/IETF/Bridge/traps/newRoot";
private static final String knownSubfileLabel1="BRIDGE-MIB defined trap event: newRoot";
private static final String unknownUEI1="uei.opennms.org/foo/thisShouldBeAnUnknownUEI";
@Before
public void setUp() throws Exception {
DaoTestConfigBean daoTestConfig = new DaoTestConfigBean();
daoTestConfig.setRelativeHomeDirectory("src/test/resources");
daoTestConfig.afterPropertiesSet();
EventconfFactory.reinit();
}
@Test
public void testIsSecureTagWhenExists() {
assertTrue("isSecureTag(\"logmsg\") should be true", EventconfFactory.getInstance().isSecureTag("logmsg"));
}
@Test
public void testIsSecureTagWhenDoesNotExist() {
assertFalse("isSecureTag(\"foobarbaz\") should be false", EventconfFactory.getInstance().isSecureTag("foobarbaz"));
}
@Test
public void testFindByUeiKnown() {
Event eventConf = EventconfFactory.getInstance().findByUei(knownUEI1);
assertNotNull("returned event configuration for known UEI '" + knownUEI1 + "' should not be null", eventConf);
assertEquals("UEI", knownUEI1, eventConf.getUei());
assertEquals("label", knownLabel1, eventConf.getEventLabel());
}
@Test
public void testFindByUeiUnknown() {
Event eventConf = EventconfFactory.getInstance().findByUei(unknownUEI1);
assertNull("returned event configuration for unknown UEI '" + unknownUEI1 + "' should be null", eventConf);
}
@Test
public void testFindByEventUeiKnown() {
EventBuilder bldr = new EventBuilder(knownUEI1, "testFindByEventUeiKnown");
Event eventConf = EventconfFactory.getInstance().findByEvent(bldr.getEvent());
assertNotNull("returned event configuration for event with known UEI '" + knownUEI1 + "' should not be null", eventConf);
assertEquals("UEI", bldr.getEvent().getUei(), eventConf.getUei());
}
@Test
public void testFindByEventUnknown() {
EventBuilder bldr = new EventBuilder(unknownUEI1, "testFindByEventUnknown");
Event eventConf = EventconfFactory.getInstance().findByEvent(bldr.getEvent());
assertNull("returned event configuration for event with unknown UEI '" + unknownUEI1 + "' should be null", eventConf);
}
@Test
public void testGetEventsByLabel() {
List<Event> events = getEventsByLabel();
ArrayList<String> beforeSort = new ArrayList<String>(events.size());
for (Event e : events) {
String label = e.getEventLabel();
beforeSort.add(label);
}
ArrayList<String> afterSort = new ArrayList<String>(beforeSort);
Collections.sort(afterSort, String.CASE_INSENSITIVE_ORDER);
assertEquals(beforeSort.size(), afterSort.size());
for (int i = 0; i < beforeSort.size(); i++) {
assertEquals("Lists unequals at index " + i, beforeSort.get(i), afterSort.get(i));
}
}
private List<Event> getEventsByLabel() {
return EventconfFactory.getInstance().getEventsByLabel();
}
@Test
public void testGetEventByUEI() {
List<Event> result=EventconfFactory.getInstance().getEvents(knownUEI1);
assertEquals("Should only be one result", 1, result.size());
Event firstEvent=(Event)result.get(0);
assertEquals("UEI should be "+knownUEI1, knownUEI1, firstEvent.getUei());
result=EventconfFactory.getInstance().getEvents("uei.opennms.org/internal/capsd/nonexistent");
assertNull("Should be null list for non-existent URI", result);
//Find an event that's in a sub-file
result=EventconfFactory.getInstance().getEvents(knownSubfileUEI1);
assertEquals("Should only be one result", 1, result.size());
firstEvent=(Event)result.get(0);
assertEquals("UEI should be "+knownSubfileUEI1,knownSubfileUEI1, firstEvent.getUei());
}
@Test
public void testGetEventUEIS() {
List<String> ueis=EventconfFactory.getInstance().getEventUEIs();
//This test assumes the test eventconf files only have X events in them. Adjust as you modify eventconf.xml and sub files
assertEquals("Count must be correct", 10011, ueis.size());
assertTrue("Must contain known UEI", ueis.contains(knownUEI1));
assertTrue("Must contain known UEI", ueis.contains(knownSubfileUEI1));
}
@Test
public void testGetLabels() {
Map<String,String> labels=EventconfFactory.getInstance().getEventLabels();
//This test assumes the test eventconf files only have X events in them. Adjust as you modify eventconf.xml and sub files
assertEquals("Count must be correct", 10011, labels.size());
assertTrue("Must contain known UEI", labels.containsKey(knownUEI1));
assertEquals("Must have known Label", labels.get(knownUEI1), knownLabel1);
assertTrue("Must contain known UEI", labels.containsKey(knownSubfileUEI1));
assertEquals("Must have known Label", labels.get(knownSubfileUEI1), knownSubfileLabel1);
}
@Test
public void testGetLabel() {
assertEquals("Must have correct label"+knownLabel1, knownLabel1, EventconfFactory.getInstance().getEventLabel(knownUEI1));
assertEquals("Must have correct label"+knownSubfileLabel1, knownSubfileLabel1, EventconfFactory.getInstance().getEventLabel(knownSubfileUEI1));
}
@Test
public void testGetAlarmType() {
Event event = new Event();
AlarmData data = new AlarmData();
data.setAlarmType(2);
data.setClearKey("uei.opennms.org.testUei:localhost:1");
data.setReductionKey("reduceme");
event.setAlarmData(data);
int i = event.getAlarmData().getAlarmType();
assertEquals(2, i);
assertTrue("uei.opennms.org.testUei:localhost:1".equals(event.getAlarmData().getClearKey()));
assertTrue("reduceme".equals(event.getAlarmData().getReductionKey()));
}
//Ensure reload does indeed reload fresh data
@Test
public void testReload() {
String newUEI="uei.opennms.org/custom/newTestUEI";
List<Event> events=EventconfFactory.getInstance().getEvents(knownUEI1);
Event event=(Event)events.get(0);
event.setUei(newUEI);
//Check that the new UEI is there
List<Event> events2=EventconfFactory.getInstance().getEvents(newUEI);
Event event2=((Event)events2.get(0));
assertNotNull("Must have some events", event2);
assertEquals("Must be exactly 1 event", 1, events2.size());
assertEquals("uei must be the new one", newUEI, event2.getUei());
//Now reload without saving - should not find the new one, but should find the old one
try {
EventconfFactory.getInstance().reload();
} catch (Throwable e) {
e.printStackTrace();
fail("Should not have had exception while reloading factory "+e.getMessage());
}
List<Event> events3=EventconfFactory.getInstance().getEvents(knownUEI1);
assertNotNull("Must have some events", events3);
assertEquals("Must be exactly 1 event", 1, events3.size());
Event event3=(Event)events3.get(0);
assertEquals("uei must be the new one", knownUEI1, event3.getUei());
//Check that the new UEI is *not* there this time
List<Event> events4=EventconfFactory.getInstance().getEvents(newUEI);
assertNull("Must be no events by that name", events4);
}
/**
* Test an eventconf.xml with only <event> elements and no
* <event-file> elements.
*/
@Test
public void testLoadConfigurationSingleConfig() throws Exception {
loadConfiguration("singleConfig/eventconf.xml");
}
/**
* Test an eventconf.xml with <event> elements and <event-file>
* elements that contain absolute paths. The included <event-file>
* has no errors.
*/
@Test
public void testLoadConfigurationTwoDeepConfigAbsolutePaths() throws Exception {
loadConfiguration("twoDeepConfig/eventconf.xml");
}
/**
* Test an eventconf.xml with <event> elements and <event-file>
* elements that contain absolute paths. The included <event-file>
* references additional <event-file>s which is an error.
*/
@Test
public void testLoadConfigurationThreeDeepConfig() throws Exception {
boolean caughtExceptionThatWeWanted = false;
try {
loadConfiguration("threeDeepConfig/eventconf.xml");
} catch (DataAccessException e) {
if (e.getMessage().contains("cannot include other configuration files")) {
caughtExceptionThatWeWanted = true;
} else {
throw e;
}
}
if (!caughtExceptionThatWeWanted) {
fail("Did not get the exception that we wanted");
}
}
/**
* Test an eventconf.xml with <event> elements and <event-file>
* elements that contain absolute paths. The included <event-file>
* has a <global> element which is an error.
*/
@Test
public void testLoadConfigurationTwoDeepConfigWithGlobal() throws Exception {
boolean caughtExceptionThatWeWanted = false;
try {
loadConfiguration("twoDeepConfigWithGlobal/eventconf.xml");
} catch (DataAccessException e) {
if (e.getMessage().contains("cannot have a 'global' element")) {
caughtExceptionThatWeWanted = true;
} else {
throw e;
}
}
if (!caughtExceptionThatWeWanted) {
fail("Did not get the exception that we wanted");
}
}
/**
* Test an eventconf.xml with <event> elements and <event-file>
* elements that contain relative paths. The included <event-file>
* has no errors.
*/
@Test
public void testLoadConfigurationRelativeTwoDeepConfig() throws Exception {
loadConfiguration("relativeTwoDeepConfig/eventconf.xml");
}
/**
* Test loading a configuration with relative included <event-file>
* entries but without passing a File object to loadConfiguration, which
* should fail because the relative path cannot be resolved.
*
* @throws Exception
*/
@Test
public void testLoadConfigurationWithNoFileRelativePathFailure() throws Exception {
boolean caughtExceptionThatWeWanted = false;
try {
loadConfiguration("relativeTwoDeepConfig/eventconf.xml", false);
} catch (DataAccessException e) {
if (e.getMessage().contains("so the relative path cannot be resolved")) {
caughtExceptionThatWeWanted = true;
} else {
throw e;
}
}
if (!caughtExceptionThatWeWanted) {
fail("Did not get the exception that we wanted");
}
}
/**
* Test loading a configuration with relative included <event-file>
* entries but without passing a File object to loadConfiguration, which
* should fail because the relative path cannot be resolved.
*
* @throws Exception
*/
@Test
public void testLoadConfigurationWithClassPathInclude() throws Exception {
loadConfiguration("classpathTwoDeep/eventconf.xml", false);
}
/**
* Test that every file included in eventconf.xml actually exists on disk
* and that there are no files on disk that aren't included.
*/
@Test
public void testIncludedEventFilesExistAndNoExtras() throws Exception {
File eventConfFile = new File("src/test/resources/etc/eventconf.xml");
File eventsDirFile = new File(eventConfFile.getParentFile(), "events");
assertTrue("events directory exists at " + eventsDirFile.getAbsolutePath(), eventsDirFile.exists());
assertTrue("events directory is a directory at " + eventsDirFile.getAbsolutePath(), eventsDirFile.isDirectory());
File[] eventFilesOnDiskArray = eventsDirFile.listFiles(new FilenameFilter() {
public boolean accept(File file, String name) {
return name.endsWith(".xml");
} });
Set<File> eventFilesOnDisk = new HashSet<File>(Arrays.asList(eventFilesOnDiskArray));
Reader r = new FileReader(eventConfFile);
Events events = JaxbUtils.unmarshal(Events.class, r);
r.close();
Set<File> eventFilesIncluded = new HashSet<File>(events.getEventFileCollection().size());
for (String eventFile : events.getEventFileCollection()) {
eventFilesIncluded.add(new File(eventConfFile.getParentFile(), eventFile));
}
Set<File> includedNotOnDisk = new HashSet<File>(eventFilesIncluded);
includedNotOnDisk.removeAll(eventFilesOnDisk);
if (!includedNotOnDisk.isEmpty()) {
fail("Event configuration file " + eventConfFile.getAbsolutePath() + " references included files that could not be found:\n\t"
+ StringUtils.collectionToDelimitedString(includedNotOnDisk, "\n\t"));
}
Set<File> onDiskNotIncluded = new HashSet<File>(eventFilesOnDisk);
onDiskNotIncluded.removeAll(eventFilesIncluded);
if (!onDiskNotIncluded.isEmpty()) {
fail("Events directory " + eventsDirFile.getAbsolutePath() + " contains event files that are not referenced in event configuration file " + eventConfFile.getAbsolutePath() + ":\n\t"
+ StringUtils.collectionToDelimitedString(onDiskNotIncluded, "\n\t"));
}
}
/**
* Test the standard eventconf.xml configuration file and its include files.
*/
@Test
public void testLoadStandardConfiguration() throws Exception {
DefaultEventConfDao dao = new DefaultEventConfDao();
dao.setConfigResource(new FileSystemResource(ConfigurationTestUtils.getFileForConfigFile("eventconf.xml")));
dao.afterPropertiesSet();
}
private void loadConfiguration(String relativeResourcePath) throws DataAccessException, IOException {
loadConfiguration(relativeResourcePath, true);
}
private void loadConfiguration(String relativeResourcePath, boolean passFile) throws DataAccessException, IOException {
DefaultEventConfDao dao = new DefaultEventConfDao();
if (passFile) {
URL url = getUrlForRelativeResourcePath(relativeResourcePath);
dao.setConfigResource(new MockFileSystemResourceWithInputStream(new File(url.getFile()), getFilteredInputStreamForConfig(relativeResourcePath)));
} else {
dao.setConfigResource(new InputStreamResource(getFilteredInputStreamForConfig(relativeResourcePath)));
}
dao.afterPropertiesSet();
}
private InputStream getFilteredInputStreamForConfig(String resourceSuffix) throws IOException {
URL url = getUrlForRelativeResourcePath(resourceSuffix);
return ConfigurationTestUtils.getInputStreamForResourceWithReplacements(this, getResourceForRelativePath(resourceSuffix),
new String[] { "\\$\\{install.etc.dir\\}", new File(url.getFile()).getParent() });
}
private URL getUrlForRelativeResourcePath(String resourceSuffix) {
URL url = getClass().getResource(getResourceForRelativePath(resourceSuffix));
assertNotNull("URL for resource " + getResourceForRelativePath(resourceSuffix) + " must not be null", url);
return url;
}
private String getResourceForRelativePath(String resourceSuffix) {
return "/org/opennms/netmgt/config/eventd/" + resourceSuffix;
}
private class MockFileSystemResourceWithInputStream implements Resource {
private Resource m_delegate;
private InputStream m_inputStream;
public MockFileSystemResourceWithInputStream(File file, InputStream inputStream) {
m_delegate = new FileSystemResource(file);
m_inputStream = inputStream;
}
public InputStream getInputStream() {
return m_inputStream;
}
public Resource createRelative(String relative) throws IOException {
return m_delegate.createRelative(relative);
}
public boolean exists() {
return m_delegate.exists();
}
public String getDescription() {
return m_delegate.getDescription();
}
public File getFile() throws IOException {
return m_delegate.getFile();
}
public String getFilename() {
return m_delegate.getFilename();
}
public URL getURL() throws IOException {
return m_delegate.getURL();
}
public boolean isOpen() {
return m_delegate.isOpen();
}
public URI getURI() throws IOException {
return m_delegate.getURI();
}
public boolean isReadable() {
return m_delegate.isReadable();
}
public long lastModified() throws IOException {
return m_delegate.lastModified();
}
public long contentLength() throws IOException {
return m_delegate.contentLength();
}
}
}