Permalink
Browse files

Refactored the core test code to build as OSGi bundles.

  • Loading branch information...
soleger committed May 24, 2012
1 parent dfbeeae commit 8d1be26b59746fdb2c1a1ba4a0253bd3b83e4614
@@ -0,0 +1,346 @@
+/*******************************************************************************
+ * This file is part of OpenNMS(R).
+ *
+ * Copyright (C) 2011 The OpenNMS Group, Inc.
+ * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc.
+ *
+ * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
+ *
+ * OpenNMS(R) is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * OpenNMS(R) is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with OpenNMS(R). If not, see:
+ * http://www.gnu.org/licenses/
+ *
+ * For more information contact:
+ * OpenNMS(R) Licensing <license@opennms.org>
+ * http://www.opennms.org/
+ * http://www.opennms.com/
+ *******************************************************************************/
+
+package org.opennms.core.test;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+
+import junit.framework.AssertionFailedError;
+
+import org.apache.log4j.AppenderSkeleton;
+import org.apache.log4j.Level;
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.log4j.spi.LoggingEvent;
+
+/**
+ * <p>MockLogAppender class. If you do not specify the log level specifically, the level
+ * will default to DEBUG and you can control the level by setting the <code>mock.logLevel</code>
+ * system property.</p>
+ *
+ * Used in unit tests to check that the level of logging produced by a test was suitable.
+ * In some cases, the test will be that no messages were logged at a higher priority than
+ * specified, e.g. Error messages logged when only Notice were expected.
+ *
+ * Some other tests may wish to ensure that an Error or Warn message was indeed logged as expected
+ *
+ * Remember: "Greater" in regards to level relates to priority; the higher the level, the less should
+ * usually be logged (e.g. Errors (highest) should be only the highest priority messages about really bad things,
+ * as compared to Debug (lowest) which is any old rubbish that might be interesting to a developer)
+ *
+ * @author brozow
+ * @version $Id: $
+ */
+public class MockLogAppender extends AppenderSkeleton {
+ private static List<LoggingEvent> s_events = null;
+
+ private static Level s_logLevel = Level.ALL;
+
+ /**
+ * <p>Constructor for MockLogAppender.</p>
+ */
+ public MockLogAppender() {
+ super();
+ resetEvents();
+ resetLogLevel();
+ }
+
+ /** {@inheritDoc} */
+ public synchronized void doAppend(final LoggingEvent event) {
+ super.doAppend(event);
+ receivedLogLevel(event.getLevel());
+ }
+
+ /** {@inheritDoc} */
+ protected void append(final LoggingEvent event) {
+ s_events.add(event);
+ }
+
+ /**
+ * <p>close</p>
+ */
+ public void close() {
+ }
+
+ /**
+ * <p>requiresLayout</p>
+ *
+ * @return a boolean.
+ */
+ public boolean requiresLayout() {
+ return false;
+ }
+
+ /**
+ * <p>resetEvents</p>
+ */
+ public static void resetEvents() {
+ s_events = Collections.synchronizedList(new LinkedList<LoggingEvent>());
+ }
+
+ /**
+ * <p>getEvents</p>
+ *
+ * @return an array of {@link org.apache.log4j.spi.LoggingEvent} objects.
+ */
+ public static LoggingEvent[] getEvents() {
+ return (LoggingEvent[]) s_events.toArray(new LoggingEvent[0]);
+ }
+
+ /**
+ * <p>getEventsGreaterOrEqual</p>
+ *
+ * @param level a {@link org.apache.log4j.Level} object.
+ * @return an array of {@link org.apache.log4j.spi.LoggingEvent} objects.
+ */
+ public static LoggingEvent[] getEventsGreaterOrEqual(final Level level) {
+ LinkedList<LoggingEvent> matching = new LinkedList<LoggingEvent>();
+
+ synchronized (s_events) {
+ for (final LoggingEvent event : s_events) {
+ if (event.getLevel().isGreaterOrEqual(level)) {
+ matching.add(event);
+ }
+ }
+ }
+
+ return matching.toArray(new LoggingEvent[0]);
+ }
+
+ /**
+ * <p>getEventsAtLevel</p>
+ *
+ * Returns events that were logged at the specified level
+ *
+ * @param level a {@link org.apache.log4j.Level} object.
+ * @return an array of {@link org.apache.log4j.spi.LoggingEvent} objects.
+ */
+ public static LoggingEvent[] getEventsAtLevel(final Level level) {
+ LinkedList<LoggingEvent> matching = new LinkedList<LoggingEvent>();
+
+ synchronized (s_events) {
+ for (final LoggingEvent event : s_events) {
+ if (event.getLevel().isGreaterOrEqual(level)) {
+ matching.add(event);
+ }
+ }
+ }
+
+ return matching.toArray(new LoggingEvent[0]);
+ }
+
+ /**
+ * <p>setupLogging</p>
+ */
+ public static void setupLogging() {
+ setupLogging(new Properties());
+ }
+
+ /**
+ * <p>setupLogging</p>
+ *
+ * @param config a {@link java.util.Properties} object.
+ */
+ public static void setupLogging(final Properties config) {
+ setupLogging(true, config);
+ }
+
+ /**
+ * <p>setupLogging</p>
+ *
+ * @param toConsole a boolean.
+ */
+ public static void setupLogging(final boolean toConsole) {
+ setupLogging(toConsole, new Properties());
+ }
+
+ /**
+ * <p>setupLogging</p>
+ *
+ * @param toConsole a boolean.
+ * @param props a {@link java.util.Properties} object.
+ */
+ public static void setupLogging(final boolean toConsole, final Properties props) {
+ final String level = System.getProperty("mock.logLevel", "DEBUG");
+ setupLogging(toConsole, level, props);
+ }
+
+ /**
+ * <p>setupLogging</p>
+ *
+ * @param toConsole a boolean.
+ * @param level a {@link java.lang.String} object.
+ */
+ public static void setupLogging(final boolean toConsole, final String level) {
+ setupLogging(toConsole, level, new Properties());
+ }
+
+ /**
+ * <p>setupLogging</p>
+ *
+ * @param toConsole a boolean.
+ * @param level a {@link java.lang.String} object.
+ * @param config a {@link java.util.Properties} object.
+ */
+ public static void setupLogging(final boolean toConsole, final String level, final Properties config) {
+ resetLogLevel();
+
+ final Properties logConfig = new Properties(config);
+ final String consoleAppender = (toConsole ? ", CONSOLE" : "");
+
+ setProperty(logConfig, "log4j.appender.CONSOLE", "org.apache.log4j.ConsoleAppender");
+ setProperty(logConfig, "log4j.appender.CONSOLE.layout", "org.apache.log4j.PatternLayout");
+ setProperty(logConfig, "log4j.appender.CONSOLE.layout.ConversionPattern", "%d %-5p [%t] %c: %m%n");
+ setProperty(logConfig, "log4j.appender.MOCK", MockLogAppender.class.getName());
+ setProperty(logConfig, "log4j.appender.MOCK.layout", "org.apache.log4j.PatternLayout");
+ setProperty(logConfig, "log4j.appender.MOCK.layout.ConversionPattern", "%-5p [%t] %c: %m%n");
+
+ setProperty(logConfig, "log4j.rootCategory", level + consoleAppender + ", MOCK");
+ setProperty(logConfig, "log4j.logger.org.apache.commons.httpclient.HttpMethodBase", "ERROR");
+ setProperty(logConfig, "log4j.logger.org.exolab.castor", "INFO");
+ setProperty(logConfig, "log4j.logger.org.snmp4j", "ERROR");
+ setProperty(logConfig, "log4j.logger.org.snmp4j.agent", "ERROR");
+ setProperty(logConfig, "log4j.logger.com.mchange.v2.c3p0.impl", "WARN");
+ setProperty(logConfig, "log4j.logger.org.hibernate.cfg.AnnotationBinder", "ERROR" + consoleAppender + ", MOCK");
+
+ PropertyConfigurator.configure(logConfig);
+ }
+
+ private static void setProperty(final Properties logConfig, final String key, final String value) {
+ if (!logConfig.containsKey(key)) {
+ logConfig.put(key, value);
+ }
+ }
+
+ /**
+ * <p>isLoggingSetup</p>
+ *
+ * @return a boolean.
+ */
+ public static boolean isLoggingSetup() {
+ return s_events != null;
+ }
+
+ /**
+ * <p>receivedLogLevel</p>
+ *
+ * @param level a {@link org.apache.log4j.Level} object.
+ */
+ public static void receivedLogLevel(final Level level) {
+ if (level.isGreaterOrEqual(s_logLevel)) {
+ s_logLevel = level;
+ }
+ }
+
+ /**
+ * <p>resetLogLevel</p>
+ */
+ public static void resetLogLevel() {
+ s_logLevel = Level.ALL;
+ }
+
+ /**
+ * <p>noWarningsOrHigherLogged</p>
+ *
+ * @return a boolean.
+ */
+ public static boolean noWarningsOrHigherLogged() {
+ return Level.INFO.isGreaterOrEqual(s_logLevel);
+ }
+
+ /**
+ * <p>assertNotGreaterOrEqual</p>
+ *
+ * @param level a {@link org.apache.log4j.Level} object.
+ * @throws junit.framework.AssertionFailedError if any.
+ */
+ public static void assertNotGreaterOrEqual(final Level level) throws AssertionFailedError {
+ if (!isLoggingSetup()) {
+ throw new AssertionFailedError("MockLogAppender has not been initialized");
+ }
+
+ try {
+ Thread.sleep(500);
+ } catch (final InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ final LoggingEvent[] events = getEventsGreaterOrEqual(level);
+ if (events.length == 0) {
+ return;
+ }
+
+ StringBuffer message = new StringBuffer("Log messages at or greater than the log level ").append(level).append(" received:");
+
+ for (final LoggingEvent event : events) {
+ message.append("\n\t[").append(event.getLevel()).append("] ")
+ .append(event.getLoggerName()).append(": ")
+ .append(event.getMessage());
+ }
+
+ throw new AssertionFailedError(message.toString());
+ }
+
+ /**
+ * <p>assertNoWarningsOrGreater</p>
+ *
+ * @throws junit.framework.AssertionFailedError if any.
+ */
+ public static void assertNoWarningsOrGreater() throws AssertionFailedError {
+ assertNotGreaterOrEqual(Level.WARN);
+ }
+
+ /**
+ * <p>assertLogAtLevel</p>
+ * Asserts that a message was logged at the requested level.
+ *
+ * Useful for testing code that *should* have logged an error message
+ * (or a notice or some other special case)
+ *
+ * @param level a {@link org.apache.log4j.Level} object.
+ * @throws junit.framework.AssertionFailedError if any.
+ */
+ public static void assertLogAtLevel(final Level level) throws AssertionFailedError {
+ if (!isLoggingSetup()) {
+ throw new AssertionFailedError("MockLogAppender has not been initialized");
+ }
+
+ try {
+ Thread.sleep(500);
+ } catch (final InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ final LoggingEvent[] events = getEventsAtLevel(level);
+ if (events.length == 0) {
+ throw new AssertionFailedError("No messages were received at level " + level);
+ }
+
+ }
+
+}

0 comments on commit 8d1be26

Please sign in to comment.