Return-Path: X-Original-To: apmail-geode-commits-archive@minotaur.apache.org Delivered-To: apmail-geode-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id CE9B518C52 for ; Tue, 4 Aug 2015 21:40:52 +0000 (UTC) Received: (qmail 87001 invoked by uid 500); 4 Aug 2015 21:40:52 -0000 Delivered-To: apmail-geode-commits-archive@geode.apache.org Received: (qmail 86964 invoked by uid 500); 4 Aug 2015 21:40:52 -0000 Mailing-List: contact commits-help@geode.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@geode.incubator.apache.org Delivered-To: mailing list commits@geode.incubator.apache.org Received: (qmail 86955 invoked by uid 99); 4 Aug 2015 21:40:52 -0000 Received: from Unknown (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 04 Aug 2015 21:40:52 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id 0A2901A9729 for ; Tue, 4 Aug 2015 21:40:52 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.771 X-Spam-Level: * X-Spam-Status: No, score=1.771 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, T_RP_MATCHES_RCVD=-0.01, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-us-west.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id VJoH4ZiLfXnG for ; Tue, 4 Aug 2015 21:40:40 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-us-west.apache.org (ASF Mail Server at mx1-us-west.apache.org) with SMTP id AFF65213B7 for ; Tue, 4 Aug 2015 21:40:40 +0000 (UTC) Received: (qmail 86872 invoked by uid 99); 4 Aug 2015 21:40:40 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 04 Aug 2015 21:40:40 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 76CADE03E8; Tue, 4 Aug 2015 21:40:40 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: klund@apache.org To: commits@geode.incubator.apache.org Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: incubator-geode git commit: GEODE-181: Add new unit and integration tests for FastLogger Date: Tue, 4 Aug 2015 21:40:40 +0000 (UTC) Repository: incubator-geode Updated Branches: refs/heads/develop fa9bd37ab -> 1c4cd8f79 GEODE-181: Add new unit and integration tests for FastLogger Add new TestSuites for logging tests. Extract default config testing to FastLoggerWithDefaultConfigJUnitTest. Move FastLoggerJUnitTest integration tests to FastLoggerIntegrationJUnitTest. Create new unit tests in FastLoggerJUnitTest. Update tests to full JUnit 4 syntax and use Rules (GEODE-89). Add mockito dependency to build for unit testing. Completes: GEODE-89, GEODE-181, GEODE-10 Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/1c4cd8f7 Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/1c4cd8f7 Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/1c4cd8f7 Branch: refs/heads/develop Commit: 1c4cd8f7909ba20f3c321001d26424e6853fe6a9 Parents: fa9bd37 Author: Kirk Lund Authored: Tue Aug 4 11:39:44 2015 -0700 Committer: Kirk Lund Committed: Tue Aug 4 14:35:24 2015 -0700 ---------------------------------------------------------------------- build.gradle | 1 + .../gemfire/internal/logging/LogService.java | 53 +- .../internal/logging/log4j/Configurator.java | 65 ++- .../internal/logging/log4j/FastLogger.java | 48 +- .../DistributedSystemLogFileJUnitTest.java | 20 +- .../logging/LoggingIntegrationTestSuite.java | 14 + .../internal/logging/LoggingUnitTestSuite.java | 12 + .../log4j/FastLoggerIntegrationJUnitTest.java | 557 +++++++++++++++++++ .../logging/log4j/FastLoggerJUnitTest.java | 274 ++++----- .../FastLoggerWithDefaultConfigJUnitTest.java | 74 +++ .../log4j/Log4jIntegrationTestSuite.java | 12 + .../logging/log4j/Log4jUnitTestSuite.java | 16 + 12 files changed, 914 insertions(+), 232 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1c4cd8f7/build.gradle ---------------------------------------------------------------------- diff --git a/build.gradle b/build.gradle index c82e82a..42b4a14 100755 --- a/build.gradle +++ b/build.gradle @@ -278,6 +278,7 @@ subprojects { testCompile 'com.github.stefanbirkner:system-rules:1.9.0' testCompile 'edu.umd.cs.mtc:multithreadedtc:1.01' testCompile 'junit:junit:4.12' + testCompile 'org.mockito:mockito-core:1.10.19' testCompile 'org.hamcrest:hamcrest-all:1.3' testCompile 'org.jmock:jmock:2.8.1' testCompile 'org.jmock:jmock-junit4:2.8.1' http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1c4cd8f7/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/LogService.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/LogService.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/LogService.java index 6298cf6..a4a399d 100644 --- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/LogService.java +++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/LogService.java @@ -12,6 +12,7 @@ import java.beans.PropertyChangeListener; import java.io.File; import java.net.URISyntaxException; import java.net.URL; +import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; @@ -21,9 +22,11 @@ import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.Filter.Result; import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.AppenderRef; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.ConfigurationFactory; import org.apache.logging.log4j.core.config.LoggerConfig; +import org.apache.logging.log4j.core.filter.AbstractFilterable; import org.apache.logging.log4j.core.lookup.Interpolator; import org.apache.logging.log4j.core.lookup.StrSubstitutor; import org.apache.logging.log4j.status.StatusLogger; @@ -78,10 +81,9 @@ public class LogService extends LogManager { private static void init() { setLog4jConfigFileProperty(); LoggerContext context = ((org.apache.logging.log4j.core.Logger) LogManager.getLogger(BASE_LOGGER_NAME, GemFireParameterizedMessageFactory.INSTANCE)).getContext(); - context.reconfigure(); context.removePropertyChangeListener(propertyChangeListener); context.addPropertyChangeListener(propertyChangeListener); - setFastLoggerDebugAvailableFlag(); + context.reconfigure(); // propertyChangeListener invokes configureFastLoggerDelegating configureLoggers(false, false); } @@ -117,15 +119,17 @@ public class LogService extends LogManager { /** * Check to see if the user has specified a Log4j configuration file. If not, attempt * to find a GemFire Log4j configuration file in various locations. + * + * @return true if log4j.configurationFile property was set; false if it was unchanged */ - private static final void setLog4jConfigFileProperty() { + private static final boolean setLog4jConfigFileProperty() { // fix bug #52175 final URL configInClasspath = ConfigLocator.findConfigInClasspath(); if (configInClasspath != null ) { // Log4J 2 will find the configuration file in classpath so do nothing configFileInformation = "Using log4j configuration found in classpath: '" + configInClasspath.toString() + "'"; StatusLogger.getLogger().info(configFileInformation); - return; + return false; } // If the user set the log4j system property then there's nothing else to do. @@ -137,16 +141,14 @@ public class LogService extends LogManager { //We will let log4j2 handle the null case and just log what file we are attempting to use configFileInformation = "Using log4j configuration file specified by " + ConfigurationFactory.CONFIGURATION_FILE_PROPERTY + ": '" + configFileName + "'"; StatusLogger.getLogger().info(configFileInformation); - return; + return false; } else { //If the resource can be found and in cases where the resource is in gemfire jar, //we set the log location to the file that was found - String configFilePropertyValue = configUrl.toString(); - System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, configFilePropertyValue); - configFileInformation = "Using log4j configuration file specified by " + ConfigurationFactory.CONFIGURATION_FILE_PROPERTY + ": '" + configFilePropertyValue + "'"; + configFileInformation = "Using log4j configuration file specified by " + ConfigurationFactory.CONFIGURATION_FILE_PROPERTY + ": '" + configFileName + "'"; StatusLogger.getLogger().info(configFileInformation); - return; + return true; } } @@ -164,7 +166,7 @@ public class LogService extends LogManager { System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, configFilePropertyValue); configFileInformation = "Setting " + ConfigurationFactory.CONFIGURATION_FILE_PROPERTY + " to specify log4j configuration file in current directory: '" + configFilePropertyValue + "'"; StatusLogger.getLogger().debug(configFileInformation); - return; + return true; } // Use the log4j config file found on the classpath in the gemfire jar file. @@ -173,7 +175,7 @@ public class LogService extends LogManager { System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, configFilePropertyValue); configFileInformation = "Setting " + ConfigurationFactory.CONFIGURATION_FILE_PROPERTY + " to specify log4j configuration file: '" + configFilePropertyValue + "'"; StatusLogger.getLogger().info(configFileInformation); - return; + return true; } public static String getConfigInformation() { @@ -244,25 +246,18 @@ public class LogService extends LogManager { return new Throwable().getStackTrace()[depth].getClassName(); } - public static void setFastLoggerDebugAvailableFlag() { + public static void configureFastLoggerDelegating() { final Configuration config = ((org.apache.logging.log4j.core.Logger) - LogManager.getLogger(BASE_LOGGER_NAME, GemFireParameterizedMessageFactory.INSTANCE)).getContext().getConfiguration(); + LogManager.getLogger(ROOT_LOGGER_NAME, GemFireParameterizedMessageFactory.INSTANCE)).getContext().getConfiguration(); - // Check for debug/trace and filters on each logger - for (LoggerConfig loggerConfig : config.getLoggers().values()) { - if (loggerConfig.getName().startsWith(BASE_LOGGER_NAME) - && ((loggerConfig.hasFilter() && !GEMFIRE_VERBOSE_FILTER.equals(loggerConfig.getFilter().toString())) - || loggerConfig.getLevel().isLessSpecificThan(Level.DEBUG))){ - FastLogger.setDebugAvailable(true); - return; - } - } - - // Check for context filters - if (config.hasFilter()) { - FastLogger.setDebugAvailable(true); + if (Configurator.hasContextWideFilter(config) || + Configurator.hasAppenderFilter(config) || + Configurator.hasDebugOrLower(config) || + Configurator.hasLoggerFilter(config) || + Configurator.hasAppenderRefFilter(config)) { + FastLogger.setDelegating(true); } else { - FastLogger.setDebugAvailable(false); + FastLogger.setDelegating(false); } } @@ -274,11 +269,11 @@ public class LogService extends LogManager { evt.getPropertyName()); if (evt.getPropertyName().equals(LoggerContext.PROPERTY_CONFIG)) { - setFastLoggerDebugAvailableFlag(); + configureFastLoggerDelegating(); } } } - + public static void setBaseLogLevel(Level level) { if (isUsingGemFireDefaultConfig()) { Configurator.setLevel(ROOT_LOGGER_NAME, level); http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1c4cd8f7/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/log4j/Configurator.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/log4j/Configurator.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/log4j/Configurator.java index c7ae945..ccb2639 100755 --- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/log4j/Configurator.java +++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/log4j/Configurator.java @@ -6,11 +6,13 @@ import java.util.Set; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.core.Appender; import org.apache.logging.log4j.core.LoggerContext; import org.apache.logging.log4j.core.config.AppenderRef; import org.apache.logging.log4j.core.config.Configuration; import org.apache.logging.log4j.core.config.LoggerConfig; import org.apache.logging.log4j.core.config.Property; +import org.apache.logging.log4j.core.filter.AbstractFilterable; import com.gemstone.gemfire.internal.logging.LogService; @@ -34,7 +36,7 @@ public class Configurator { context.updateLoggers(); if (level.isLessSpecificThan(Level.DEBUG)) { - LogService.setFastLoggerDebugAvailableFlag(); + LogService.configureFastLoggerDelegating(); } } @@ -110,4 +112,65 @@ public class Configurator { } return logConfig; } + + public static boolean hasContextWideFilter(final Configuration config) { + return config.hasFilter(); + } + + public static boolean hasAppenderFilter(final Configuration config) { + for (Appender appender : config.getAppenders().values()) { + if (appender instanceof AbstractFilterable) { + if (((AbstractFilterable) appender).hasFilter()) { + return true; + } + } + } + return false; + } + + public static boolean hasDebugOrLower(final Configuration config) { + for (LoggerConfig loggerConfig : config.getLoggers().values()) { + boolean isDebugOrLower = loggerConfig.getLevel().isLessSpecificThan(Level.DEBUG); + if (isDebugOrLower) { + return true; + } + } + return false; + } + + public static boolean hasLoggerFilter(final Configuration config) { + for (LoggerConfig loggerConfig : config.getLoggers().values()) { + boolean isRoot = loggerConfig.getName().equals(""); + boolean isGemFire = loggerConfig.getName().startsWith(LogService.BASE_LOGGER_NAME); + boolean hasFilter = loggerConfig.hasFilter(); + boolean isGemFireVerboseFilter = hasFilter && LogService.GEMFIRE_VERBOSE_FILTER.equals(loggerConfig.getFilter().toString()); + + if (isRoot || isGemFire) { + // check for Logger Filter + if (hasFilter && !isGemFireVerboseFilter) { + return true; + } + } + } + return false; + } + + public static boolean hasAppenderRefFilter(final Configuration config) { + for (LoggerConfig loggerConfig : config.getLoggers().values()) { + boolean isRoot = loggerConfig.getName().equals(""); + boolean isGemFire = loggerConfig.getName().startsWith(LogService.BASE_LOGGER_NAME); + boolean hasFilter = loggerConfig.hasFilter(); + boolean isGemFireVerboseFilter = hasFilter && LogService.GEMFIRE_VERBOSE_FILTER.equals(loggerConfig.getFilter().toString()); + + if (isRoot || isGemFire) { + // check for AppenderRef Filter + for (AppenderRef appenderRef : loggerConfig.getAppenderRefs()) { + if (appenderRef.getFilter() != null) { + return true; + } + } + } + } + return false; + } } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1c4cd8f7/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/log4j/FastLogger.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/log4j/FastLogger.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/log4j/FastLogger.java index 21d7965..9583429 100644 --- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/log4j/FastLogger.java +++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/logging/log4j/FastLogger.java @@ -1,6 +1,5 @@ package com.gemstone.gemfire.internal.logging.log4j; -import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.message.MessageFactory; @@ -9,8 +8,9 @@ import org.apache.logging.log4j.spi.ExtendedLoggerWrapper; import org.apache.logging.log4j.status.StatusLogger; /** - * Overrides is enabled checks for log levels below INFO to avoid performance - * penalties when the log level is INFO or above. + * Overrides is-enabled checks for log levels below INFO to avoid performance + * penalties when the log level is INFO or above. If delegating is true + * then it will always delegate to ExtendedLoggerWrapper for is-enabled checks. * * @author Kirk Lund * @author David Hoots @@ -18,7 +18,7 @@ import org.apache.logging.log4j.status.StatusLogger; public class FastLogger extends ExtendedLoggerWrapper { private static final long serialVersionUID = 7084130827962463327L; - private static volatile boolean debugAvailable = true; + private static volatile boolean delegating = true; public FastLogger(final Logger logger) { this((ExtendedLogger) logger, logger.getName(), logger.getMessageFactory()); @@ -28,55 +28,33 @@ public class FastLogger extends ExtendedLoggerWrapper { super(logger, name, messageFactory); } - public static void setDebugAvailable(final boolean newValue) { - StatusLogger.getLogger().debug("Setting debugAvailable to {}", newValue); - debugAvailable = newValue; + public static void setDelegating(final boolean newValue) { + StatusLogger.getLogger().debug("Setting delegating to {}", newValue); + delegating = newValue; } - /** - * Checks whether this Logger is enabled for the {@link Level#DEBUG DEBUG} Level. - * - * @return boolean - {@code true} if this Logger is enabled for level DEBUG, {@code false} otherwise. - */ @Override public boolean isDebugEnabled() { - return debugAvailable && super.isDebugEnabled(); + return delegating && super.isDebugEnabled(); } - /** - * Checks whether this Logger is enabled for the {@link Level#DEBUG DEBUG} Level. - * - * @param marker The marker data specific to this log statement. - * @return boolean - {@code true} if this Logger is enabled for level DEBUG, {@code false} otherwise. - */ @Override public boolean isDebugEnabled(final Marker marker) { - return debugAvailable && super.isDebugEnabled(marker); + return delegating && super.isDebugEnabled(marker); } - /** - * Checks whether this Logger is enabled for the {@link Level#TRACE TRACE} level. - * - * @return boolean - {@code true} if this Logger is enabled for level TRACE, {@code false} otherwise. - */ @Override public boolean isTraceEnabled() { - return debugAvailable && super.isTraceEnabled(); + return delegating && super.isTraceEnabled(); } - /** - * Checks whether this Logger is enabled for the {@link Level#TRACE TRACE} level. - * - * @param marker The marker data specific to this log statement. - * @return boolean - {@code true} if this Logger is enabled for level TRACE, {@code false} otherwise. - */ @Override public boolean isTraceEnabled(final Marker marker) { - return debugAvailable && super.isTraceEnabled(marker); + return delegating && super.isTraceEnabled(marker); } - public boolean isDebugAvailable() { - return debugAvailable; + public boolean isDelegating() { + return delegating; } public Logger getExtendedLogger() { http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1c4cd8f7/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/DistributedSystemLogFileJUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/DistributedSystemLogFileJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/DistributedSystemLogFileJUnitTest.java index 9c7ba58..8dfd5a4 100644 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/DistributedSystemLogFileJUnitTest.java +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/DistributedSystemLogFileJUnitTest.java @@ -487,7 +487,7 @@ public class DistributedSystemLogFileJUnitTest { assertTrue(logWriter.fineEnabled()); assertTrue(((LogWriterLogger)logWriter).isDebugEnabled()); assertTrue(logWriter instanceof FastLogger); - assertTrue(((FastLogger)logWriter).isDebugAvailable()); + assertTrue(((FastLogger)logWriter).isDelegating()); DistributedTestCase.waitForCriterion(new WaitCriterion() { @Override @@ -703,7 +703,7 @@ public class DistributedSystemLogFileJUnitTest { assertTrue(logWriter.fineEnabled()); assertTrue(((LogWriterLogger)logWriter).isDebugEnabled()); assertTrue(logWriter instanceof FastLogger); - assertTrue(((FastLogger)logWriter).isDebugAvailable()); + assertTrue(((FastLogger)logWriter).isDelegating()); DistributedTestCase.waitForCriterion(new WaitCriterion() { @Override @@ -942,8 +942,8 @@ public class DistributedSystemLogFileJUnitTest { //Because debug available is a static volatile, it is shared between the two writers //However we should not see any debug level logging due to the config level set in //the log writer itself - assertTrue(((FastLogger)securityLogWriter).isDebugAvailable()); - assertTrue(((FastLogger)logWriter).isDebugAvailable()); + assertTrue(((FastLogger)securityLogWriter).isDelegating()); + assertTrue(((FastLogger)logWriter).isDelegating()); DistributedTestCase.waitForCriterion(new WaitCriterion() { @@ -1058,8 +1058,8 @@ public class DistributedSystemLogFileJUnitTest { assertTrue(((LogWriterLogger)logWriter).isDebugEnabled()); assertTrue(securityLogWriter instanceof FastLogger); assertTrue(logWriter instanceof FastLogger); - assertTrue(((FastLogger)securityLogWriter).isDebugAvailable()); - assertTrue(((FastLogger)logWriter).isDebugAvailable()); + assertTrue(((FastLogger)securityLogWriter).isDelegating()); + assertTrue(((FastLogger)logWriter).isDelegating()); DistributedTestCase.waitForCriterion(new WaitCriterion() { @Override @@ -1230,8 +1230,8 @@ public class DistributedSystemLogFileJUnitTest { assertTrue(((LogWriterLogger)logWriter).isDebugEnabled()); assertTrue(securityLogWriter instanceof FastLogger); assertTrue(logWriter instanceof FastLogger); - assertTrue(((FastLogger)securityLogWriter).isDebugAvailable()); - assertTrue(((FastLogger)logWriter).isDebugAvailable()); + assertTrue(((FastLogger)securityLogWriter).isDelegating()); + assertTrue(((FastLogger)logWriter).isDelegating()); DistributedTestCase.waitForCriterion(new WaitCriterion() { @Override @@ -1379,8 +1379,8 @@ public class DistributedSystemLogFileJUnitTest { assertFalse(((LogWriterLogger)logWriter).isDebugEnabled()); assertTrue(securityLogWriter instanceof FastLogger); assertTrue(logWriter instanceof FastLogger); - assertTrue(((FastLogger)securityLogWriter).isDebugAvailable()); - assertTrue(((FastLogger)logWriter).isDebugAvailable()); + assertTrue(((FastLogger)securityLogWriter).isDelegating()); + assertTrue(((FastLogger)logWriter).isDelegating()); DistributedTestCase.waitForCriterion(new WaitCriterion() { @Override http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1c4cd8f7/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/LoggingIntegrationTestSuite.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/LoggingIntegrationTestSuite.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/LoggingIntegrationTestSuite.java new file mode 100755 index 0000000..1efaa59 --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/LoggingIntegrationTestSuite.java @@ -0,0 +1,14 @@ +package com.gemstone.gemfire.internal.logging; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + DistributedSystemLogFileJUnitTest.class, + LocatorLogFileJUnitTest.class, + LogServiceJUnitTest.class, + MergeLogFilesJUnitTest.class, +}) +public class LoggingIntegrationTestSuite { +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1c4cd8f7/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/LoggingUnitTestSuite.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/LoggingUnitTestSuite.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/LoggingUnitTestSuite.java new file mode 100755 index 0000000..cd39a9d --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/LoggingUnitTestSuite.java @@ -0,0 +1,12 @@ +package com.gemstone.gemfire.internal.logging; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + LogWriterImplJUnitTest.class, + SortLogFileJUnitTest.class +}) +public class LoggingUnitTestSuite { +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1c4cd8f7/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerIntegrationJUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerIntegrationJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerIntegrationJUnitTest.java new file mode 100644 index 0000000..f1c7ab9 --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerIntegrationJUnitTest.java @@ -0,0 +1,557 @@ +package com.gemstone.gemfire.internal.logging.log4j; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.MarkerManager; +import org.apache.logging.log4j.core.LoggerContext; +import org.apache.logging.log4j.core.config.ConfigurationFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.RestoreSystemProperties; +import org.junit.experimental.categories.Category; +import org.junit.rules.TemporaryFolder; + +import com.gemstone.gemfire.internal.logging.LogService; +import com.gemstone.gemfire.test.junit.categories.IntegrationTest; + +/** + * Tests FastLogger isDebugEnabled and isTraceEnabled with various configurations. + * + * For filters see https://logging.apache.org/log4j/2.0/manual/filters.html + * + * @author Kirk Lund + * @author David Hoots + */ +@Category(IntegrationTest.class) +public class FastLoggerIntegrationJUnitTest { + + private static final String TEST_LOGGER_NAME = FastLogger.class.getPackage().getName(); + private static final String ENABLED_MARKER_NAME = "ENABLED"; + private static final String UNUSED_MARKER_NAME = "UNUSED"; + + @Rule + public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties(); + + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + + private File configFile; + private Logger logger; + private LoggerContext appenderContext; + private Marker enabledMarker; + private Marker unusedMarker; + + @Before + public void setUp() throws Exception { + System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY); + this.configFile = new File(this.temporaryFolder.getRoot(), "log4j2-test.xml"); + this.enabledMarker = MarkerManager.getMarker(ENABLED_MARKER_NAME); + this.unusedMarker = MarkerManager.getMarker(UNUSED_MARKER_NAME); + setUpLogService(); + } + + @After + public void tearDown() { + System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY); + LogService.reconfigure(); + } + + private void setUpLogService() throws Exception { + // Load a base config and do some sanity checks + writeSimpleConfigFile(this.configFile, Level.WARN); + System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, this.configFile.toURI().toURL().toString()); + + LogService.reconfigure(); + LogService.getLogger().getName(); // This causes the config file to be loaded + this.logger = LogService.getLogger(TEST_LOGGER_NAME); + this.appenderContext = ((org.apache.logging.log4j.core.Logger) LogService.getRootLogger()).getContext(); + + assertThat(LogService.getLogger(LogService.BASE_LOGGER_NAME).getLevel(), is(Level.FATAL)); + assertThat(this.logger, is(instanceOf(FastLogger.class))); + assertThat(this.logger.getLevel(), is(Level.WARN)); + } + + @Test + public void debugConfigIsDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.DEBUG, expectDelegating(true)); + } + @Test + public void traceConfigIsDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.TRACE, expectDelegating(true)); + } + @Test + public void infoConfigIsNotDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.INFO, expectDelegating(false)); + } + @Test + public void warnConfigIsNotDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.WARN, expectDelegating(false)); + } + @Test + public void errorConfigIsNotDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.ERROR, expectDelegating(false)); + } + @Test + public void fatalConfigIsNotDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.FATAL, expectDelegating(false)); + } + + @Test + public void fromDebugToInfoSetsDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.DEBUG, expectDelegating(true)); + verifyIsDelegatingForDebugOrLower(Level.INFO, expectDelegating(false)); + } + @Test + public void fromInfoToDebugUnsetsDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.INFO, expectDelegating(false)); + verifyIsDelegatingForDebugOrLower(Level.DEBUG, expectDelegating(true)); + } + + @Test + public void fromDebugToContextWideFilterKeepsDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.DEBUG, expectDelegating(true)); + verifyIsDelegatingForContextWideFilter(Level.INFO, expectDelegating(true)); + } + @Test + public void fromInfoToContextWideFilterSetsDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.INFO, expectDelegating(false)); + verifyIsDelegatingForContextWideFilter(Level.INFO, expectDelegating(true)); + } + @Test + public void fromContextWideFilterToInfoUnsetsDelegating() throws Exception { + verifyIsDelegatingForContextWideFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForDebugOrLower(Level.INFO, expectDelegating(false)); + } + @Test + public void fromContextWideFilterToDebugKeepsDelegating() throws Exception { + verifyIsDelegatingForContextWideFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForDebugOrLower(Level.DEBUG, expectDelegating(true)); + } + + @Test + public void fromDebugToAppenderFilterKeepsDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.DEBUG, expectDelegating(true)); + verifyIsDelegatingForAppenderFilter(Level.INFO, expectDelegating(true)); + } + @Test + public void fromInfoToAppenderFilterSetsDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.INFO, expectDelegating(false)); + verifyIsDelegatingForAppenderFilter(Level.INFO, expectDelegating(true)); + } + @Test + public void fromAppenderFilterToInfoUnsetsDelegating() throws Exception { + verifyIsDelegatingForAppenderFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForDebugOrLower(Level.INFO, expectDelegating(false)); + } + @Test + public void fromAppenderFilterToDebugKeepsDelegating() throws Exception { + verifyIsDelegatingForAppenderFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForDebugOrLower(Level.DEBUG, expectDelegating(true)); + } + + @Test + public void fromDebugToLoggerFilterKeepsDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.DEBUG, expectDelegating(true)); + verifyIsDelegatingForLoggerFilter(Level.INFO, expectDelegating(true)); + } + @Test + public void fromInfoToLoggerFilterSetsDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.INFO, expectDelegating(false)); + verifyIsDelegatingForLoggerFilter(Level.INFO, expectDelegating(true)); + } + @Test + public void fromLoggerFilterToInfoUnsetsDelegating() throws Exception { + verifyIsDelegatingForLoggerFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForDebugOrLower(Level.INFO, expectDelegating(false)); + } + @Test + public void fromLoggerFilterToDebugKeepsDelegating() throws Exception { + verifyIsDelegatingForLoggerFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForDebugOrLower(Level.DEBUG, expectDelegating(true)); + } + + @Test + public void fromDebugToAppenderRefFilterKeepsDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.DEBUG, expectDelegating(true)); + verifyIsDelegatingForAppenderRefFilter(Level.INFO, expectDelegating(true)); + } + @Test + public void fromInfoToAppenderRefFilterSetsDelegating() throws Exception { + verifyIsDelegatingForDebugOrLower(Level.INFO, expectDelegating(false)); + verifyIsDelegatingForAppenderRefFilter(Level.INFO, expectDelegating(true)); + } + @Test + public void fromAppenderRefFilterToInfoUnsetsDelegating() throws Exception { + verifyIsDelegatingForAppenderRefFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForDebugOrLower(Level.INFO, expectDelegating(false)); + } + @Test + public void fromAppenderRefFilterToDebugKeepsDelegating() throws Exception { + verifyIsDelegatingForAppenderRefFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForDebugOrLower(Level.DEBUG, expectDelegating(true)); + } + + @Test + public void fromContextWideFilterToLoggerFilterKeepsDelegating() throws Exception { + verifyIsDelegatingForContextWideFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForLoggerFilter(Level.INFO, expectDelegating(true)); + } + @Test + public void fromLoggerFilterToContextWideFilterKeepsDelegating() throws Exception { + verifyIsDelegatingForLoggerFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForContextWideFilter(Level.INFO, expectDelegating(true)); + } + + @Test + public void contextWideFilterIsDelegating() throws Exception { + verifyIsDelegatingForContextWideFilter(Level.TRACE, expectDelegating(true)); + verifyIsDelegatingForContextWideFilter(Level.DEBUG, expectDelegating(true)); + verifyIsDelegatingForContextWideFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForContextWideFilter(Level.WARN, expectDelegating(true)); + verifyIsDelegatingForContextWideFilter(Level.ERROR, expectDelegating(true)); + verifyIsDelegatingForContextWideFilter(Level.FATAL, expectDelegating(true)); + } + + @Test + public void loggerFilterIsDelegating() throws Exception { + verifyIsDelegatingForLoggerFilter(Level.TRACE, expectDelegating(true)); + verifyIsDelegatingForLoggerFilter(Level.DEBUG, expectDelegating(true)); + verifyIsDelegatingForLoggerFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForLoggerFilter(Level.WARN, expectDelegating(true)); + verifyIsDelegatingForLoggerFilter(Level.ERROR, expectDelegating(true)); + verifyIsDelegatingForLoggerFilter(Level.FATAL, expectDelegating(true)); + } + + @Test + public void appenderFilterIsDelegating() throws Exception { + verifyIsDelegatingForAppenderFilter(Level.TRACE, expectDelegating(true)); + verifyIsDelegatingForAppenderFilter(Level.DEBUG, expectDelegating(true)); + verifyIsDelegatingForAppenderFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForAppenderFilter(Level.WARN, expectDelegating(true)); + verifyIsDelegatingForAppenderFilter(Level.ERROR, expectDelegating(true)); + verifyIsDelegatingForAppenderFilter(Level.FATAL, expectDelegating(true)); + } + + @Test + public void appenderRefFilterIsDelegating() throws Exception { + verifyIsDelegatingForAppenderRefFilter(Level.TRACE, expectDelegating(true)); + verifyIsDelegatingForAppenderRefFilter(Level.DEBUG, expectDelegating(true)); + verifyIsDelegatingForAppenderRefFilter(Level.INFO, expectDelegating(true)); + verifyIsDelegatingForAppenderRefFilter(Level.WARN, expectDelegating(true)); + verifyIsDelegatingForAppenderRefFilter(Level.ERROR, expectDelegating(true)); + verifyIsDelegatingForAppenderRefFilter(Level.FATAL, expectDelegating(true)); + } + + /** + * Verifies FastLogger isDelegating if Level is DEBUG or TRACE. + * + * @param level the log Level + * @param expectIsDelegating true if expecting FastLogger.isDelegating to be true + */ + private void verifyIsDelegatingForDebugOrLower(final Level level, final boolean expectIsDelegating) throws Exception { + writeSimpleConfigFile(this.configFile, level); + this.appenderContext.reconfigure(); + + assertThat(this.logger.getLevel(), is(level)); + + assertThat(this.logger.isTraceEnabled(), is(level.isLessSpecificThan(Level.TRACE))); + assertThat(this.logger.isDebugEnabled(), is(level.isLessSpecificThan(Level.DEBUG))); + assertThat(this.logger.isInfoEnabled(), is(level.isLessSpecificThan(Level.INFO))); + assertThat(this.logger.isWarnEnabled(), is(level.isLessSpecificThan(Level.WARN))); + assertThat(this.logger.isErrorEnabled(), is(level.isLessSpecificThan(Level.ERROR))); + assertThat(this.logger.isFatalEnabled(), is(level.isLessSpecificThan(Level.FATAL))); + + assertThat(this.logger.isTraceEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.TRACE))); + assertThat(this.logger.isDebugEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.DEBUG))); + assertThat(this.logger.isInfoEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.INFO))); + assertThat(this.logger.isWarnEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.WARN))); + assertThat(this.logger.isErrorEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.ERROR))); + assertThat(this.logger.isFatalEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.FATAL))); + + final boolean delegating = ((FastLogger)this.logger).isDelegating(); + assertThat(delegating, is(expectIsDelegating)); + assertThat(delegating, is(level.isLessSpecificThan(Level.DEBUG))); + assertThat(delegating, is(expectIsDelegating)); + } + + /** + * Verifies FastLogger isDelegating if there is a Logger Filter. + * + * @param level the log Level + * @param expectIsDelegating true if expecting FastLogger.isDelegating to be true + */ + private void verifyIsDelegatingForLoggerFilter(final Level level, final boolean expectIsDelegating) throws Exception { + assertThat(expectIsDelegating, is(true)); // always true for Logger Filter + + writeLoggerFilterConfigFile(this.configFile, level); + this.appenderContext.reconfigure(); + + assertThat(this.logger.getLevel(), is(level)); + + assertThat(this.logger.isTraceEnabled(), is(level.isLessSpecificThan(Level.TRACE))); + assertThat(this.logger.isDebugEnabled(), is(level.isLessSpecificThan(Level.DEBUG))); + assertThat(this.logger.isInfoEnabled(), is(level.isLessSpecificThan(Level.INFO))); + assertThat(this.logger.isWarnEnabled(), is(level.isLessSpecificThan(Level.WARN))); + assertThat(this.logger.isErrorEnabled(), is(level.isLessSpecificThan(Level.ERROR))); + assertThat(this.logger.isFatalEnabled(), is(level.isLessSpecificThan(Level.FATAL))); + + assertThat(this.logger.isTraceEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.TRACE))); + assertThat(this.logger.isDebugEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.DEBUG))); + assertThat(this.logger.isInfoEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.INFO))); + assertThat(this.logger.isWarnEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.WARN))); + assertThat(this.logger.isErrorEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.ERROR))); + assertThat(this.logger.isFatalEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.FATAL))); + + assertThat(this.logger.isTraceEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.TRACE))); + assertThat(this.logger.isDebugEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.DEBUG))); + assertThat(this.logger.isInfoEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.INFO))); + assertThat(this.logger.isWarnEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.WARN))); + assertThat(this.logger.isErrorEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.ERROR))); + assertThat(this.logger.isFatalEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.FATAL))); + + assertThat(((FastLogger)this.logger).isDelegating(), is(expectIsDelegating)); + } + + /** + * Verifies FastLogger isDelegating if there is a Context-wide Filter. + * + * @param level the log Level + * @param expectIsDelegating true if expecting FastLogger.isDelegating to be true + */ + private void verifyIsDelegatingForContextWideFilter(final Level level, final boolean expectIsDelegating) throws Exception { + assertThat(expectIsDelegating, is(true)); // always true for Context-wide Filter + + writeContextWideFilterConfigFile(this.configFile, level); + this.appenderContext.reconfigure(); + + assertThat(this.logger.getLevel(), is(level)); + + // note: unlike other filters, Context-wide filters are processed BEFORE isEnabled checks + + assertThat(this.logger.isTraceEnabled(), is(false)); + assertThat(this.logger.isDebugEnabled(), is(false)); + assertThat(this.logger.isInfoEnabled(), is(false)); + assertThat(this.logger.isWarnEnabled(), is(false)); + assertThat(this.logger.isErrorEnabled(), is(false)); + assertThat(this.logger.isFatalEnabled(), is(false)); + + assertThat(this.logger.isTraceEnabled(this.enabledMarker), is(true)); + assertThat(this.logger.isDebugEnabled(this.enabledMarker), is(true)); + assertThat(this.logger.isInfoEnabled(this.enabledMarker), is(true)); + assertThat(this.logger.isWarnEnabled(this.enabledMarker), is(true)); + assertThat(this.logger.isErrorEnabled(this.enabledMarker), is(true)); + assertThat(this.logger.isFatalEnabled(this.enabledMarker), is(true)); + + assertThat(this.logger.isTraceEnabled(this.unusedMarker), is(false)); + assertThat(this.logger.isDebugEnabled(this.unusedMarker), is(false)); + assertThat(this.logger.isInfoEnabled(this.unusedMarker), is(false)); + assertThat(this.logger.isWarnEnabled(this.unusedMarker), is(false)); + assertThat(this.logger.isErrorEnabled(this.unusedMarker), is(false)); + assertThat(this.logger.isFatalEnabled(this.unusedMarker), is(false)); + + assertThat(((FastLogger)this.logger).isDelegating(), is(expectIsDelegating)); + } + + /** + * Verifies FastLogger isDelegating if there is a Appender Filter. + * + * @param level the log Level + * @param expectIsDelegating true if expecting FastLogger.isDelegating to be true + */ + private void verifyIsDelegatingForAppenderFilter(final Level level, final boolean expectIsDelegating) throws Exception { + assertThat(expectIsDelegating, is(true)); // always true for Appender Filter + + writeAppenderFilterConfigFile(this.configFile, level); + this.appenderContext.reconfigure(); + + assertThat(this.logger.getLevel(), is(level)); + + assertThat(this.logger.isTraceEnabled(), is(level.isLessSpecificThan(Level.TRACE))); + assertThat(this.logger.isDebugEnabled(), is(level.isLessSpecificThan(Level.DEBUG))); + assertThat(this.logger.isInfoEnabled(), is(level.isLessSpecificThan(Level.INFO))); + assertThat(this.logger.isWarnEnabled(), is(level.isLessSpecificThan(Level.WARN))); + assertThat(this.logger.isErrorEnabled(), is(level.isLessSpecificThan(Level.ERROR))); + assertThat(this.logger.isFatalEnabled(), is(level.isLessSpecificThan(Level.FATAL))); + + assertThat(this.logger.isTraceEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.TRACE))); + assertThat(this.logger.isDebugEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.DEBUG))); + assertThat(this.logger.isInfoEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.INFO))); + assertThat(this.logger.isWarnEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.WARN))); + assertThat(this.logger.isErrorEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.ERROR))); + assertThat(this.logger.isFatalEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.FATAL))); + + assertThat(this.logger.isTraceEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.TRACE))); + assertThat(this.logger.isDebugEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.DEBUG))); + assertThat(this.logger.isInfoEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.INFO))); + assertThat(this.logger.isWarnEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.WARN))); + assertThat(this.logger.isErrorEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.ERROR))); + assertThat(this.logger.isFatalEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.FATAL))); + + assertThat(((FastLogger)this.logger).isDelegating(), is(expectIsDelegating)); + } + + /** + * Verifies FastLogger isDelegating if there is a AppenderRef Filter. + * + * @param level the log Level + * @param expectIsDelegating true if expecting FastLogger.isDelegating to be true + */ + private void verifyIsDelegatingForAppenderRefFilter(final Level level, final boolean expectIsDelegating) throws Exception { + assertThat(expectIsDelegating, is(true)); // always true for AppenderRef Filter + + writeAppenderRefFilterConfigFile(this.configFile, level); + this.appenderContext.reconfigure(); + + assertThat(this.logger.getLevel(), is(level)); + + assertThat(this.logger.isTraceEnabled(), is(level.isLessSpecificThan(Level.TRACE))); + assertThat(this.logger.isDebugEnabled(), is(level.isLessSpecificThan(Level.DEBUG))); + assertThat(this.logger.isInfoEnabled(), is(level.isLessSpecificThan(Level.INFO))); + assertThat(this.logger.isWarnEnabled(), is(level.isLessSpecificThan(Level.WARN))); + assertThat(this.logger.isErrorEnabled(), is(level.isLessSpecificThan(Level.ERROR))); + assertThat(this.logger.isFatalEnabled(), is(level.isLessSpecificThan(Level.FATAL))); + + assertThat(this.logger.isTraceEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.TRACE))); + assertThat(this.logger.isDebugEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.DEBUG))); + assertThat(this.logger.isInfoEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.INFO))); + assertThat(this.logger.isWarnEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.WARN))); + assertThat(this.logger.isErrorEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.ERROR))); + assertThat(this.logger.isFatalEnabled(this.enabledMarker), is(level.isLessSpecificThan(Level.FATAL))); + + assertThat(this.logger.isTraceEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.TRACE))); + assertThat(this.logger.isDebugEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.DEBUG))); + assertThat(this.logger.isInfoEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.INFO))); + assertThat(this.logger.isWarnEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.WARN))); + assertThat(this.logger.isErrorEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.ERROR))); + assertThat(this.logger.isFatalEnabled(this.unusedMarker), is(level.isLessSpecificThan(Level.FATAL))); + + assertThat(((FastLogger)this.logger).isDelegating(), is(expectIsDelegating)); + } + + private boolean expectDelegating(final boolean value) { + return value; + } + + private static String writeSimpleConfigFile(final File configFile, final Level level) throws IOException { + final String xml = + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + final BufferedWriter writer = new BufferedWriter(new FileWriter(configFile)); + writer.write(xml); + writer.close(); + return xml; + } + + private static String writeLoggerFilterConfigFile(final File configFile, final Level level) throws IOException { + final String xml = + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + final BufferedWriter writer = new BufferedWriter(new FileWriter(configFile)); + writer.write(xml); + writer.close(); + return xml; + } + + private static String writeContextWideFilterConfigFile(final File configFile, final Level level) throws IOException { + final String xml = + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + final BufferedWriter writer = new BufferedWriter(new FileWriter(configFile)); + writer.write(xml); + writer.close(); + return xml; + } + + private static String writeAppenderFilterConfigFile(final File configFile, final Level level) throws IOException { + final String xml = + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + final BufferedWriter writer = new BufferedWriter(new FileWriter(configFile)); + writer.write(xml); + writer.close(); + return xml; + } + + private static String writeAppenderRefFilterConfigFile(final File configFile, final Level level) throws IOException { + final String xml = + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + final BufferedWriter writer = new BufferedWriter(new FileWriter(configFile)); + writer.write(xml); + writer.close(); + return xml; + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1c4cd8f7/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerJUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerJUnitTest.java old mode 100644 new mode 100755 index 2aab5df..96d8b93 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerJUnitTest.java +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerJUnitTest.java @@ -1,202 +1,162 @@ package com.gemstone.gemfire.internal.logging.log4j; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.lang.reflect.Field; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.sameInstance; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; import org.apache.logging.log4j.Level; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.core.LoggerContext; -import org.apache.logging.log4j.core.config.ConfigurationFactory; -import org.junit.After; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.message.MessageFactory; +import org.apache.logging.log4j.message.ParameterizedMessageFactory; +import org.apache.logging.log4j.spi.ExtendedLogger; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; -import com.gemstone.gemfire.internal.logging.LogService; import com.gemstone.gemfire.test.junit.categories.UnitTest; /** - * Tests FastLogger isDebugEnabled and isTraceEnabled. - * - * @author Kirk Lund - * @author David Hoots + * Unit tests the FastLogger class which wraps and delegates to an actual + * Logger with optimizations for isDebugEnabled and isTraceEnabled. */ @Category(UnitTest.class) public class FastLoggerJUnitTest { - private static final String TEST_LOGGER_NAME = "com.gemstone.gemfire.cache.internal"; - - private File configFile; + private MessageFactory messageFactory; + private ExtendedLogger mockedLogger; + private Marker mockedMarker; @Before public void setUp() { - System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY); - } - - @After - public void tearDown() { - System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY); - LogService.reconfigure(); - if (this.configFile != null && this.configFile.exists()) { - this.configFile.delete(); - } + this.messageFactory = new ParameterizedMessageFactory(); + this.mockedLogger = mock(ExtendedLogger.class); + this.mockedMarker = mock(Marker.class); + + when(this.mockedLogger.getMessageFactory()).thenReturn(this.messageFactory); + when(this.mockedMarker.getName()).thenReturn("MARKER"); } /** - * Verifies that when the configuration is changed the FastLogger - * debugAvailable field is changed. + * FastLogger should return isDelegating after setDelegating */ @Test - public final void testRespondToConfigChange() throws Exception { - final File configFile = new File(System.getProperty("java.io.tmpdir"), "log4j2-test.xml"); - - // Load a base config and do some sanity checks - writeBaseConfigFile(configFile, "WARN"); - System.setProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY, configFile.toURI().toURL().toString()); + public void returnIsDelegatingAfterSetDelegating() { + FastLogger.setDelegating(true); - LogService.reconfigure(); + FastLogger fastLogger = new FastLogger(this.mockedLogger); - LogService.getLogger().getName(); // This causes the config file to be loaded - final Logger testLogger = LogService.getLogger(TEST_LOGGER_NAME); - - final LoggerContext appenderContext = ((org.apache.logging.log4j.core.Logger) LogService.getRootLogger()).getContext(); - assertEquals(Level.FATAL, LogService.getLogger(LogService.BASE_LOGGER_NAME).getLevel()); - assertEquals(Level.WARN, LogService.getLogger(TEST_LOGGER_NAME).getLevel()); - - // Get a reference to the debugAvailable field in FastLogger - Field debugAvailableField = FastLogger.class.getDeclaredField("debugAvailable"); - debugAvailableField.setAccessible(true); - boolean debugAvailable = (Boolean) debugAvailableField.get(FastLogger.class); - assertFalse(debugAvailable); - - // Modify the config and verify that the debugAvailable field has changed - writeBaseConfigFile(configFile, "DEBUG"); - appenderContext.reconfigure(); - assertEquals(Level.DEBUG, LogService.getLogger(TEST_LOGGER_NAME).getLevel()); - debugAvailable = (Boolean) debugAvailableField.get(FastLogger.class); - assertTrue(testLogger.isDebugEnabled()); - assertFalse(testLogger.isTraceEnabled()); - assertTrue(debugAvailable); + assertThat(fastLogger.isDelegating(), is(true)); - // Modify the config and verify that the debugAvailable field has changed - writeBaseConfigFile(configFile, "ERROR"); - appenderContext.reconfigure(); - assertEquals(Level.ERROR, LogService.getLogger(TEST_LOGGER_NAME).getLevel()); - assertFalse(testLogger.isDebugEnabled()); - assertFalse((Boolean) debugAvailableField.get(FastLogger.class)); - - // Modify the config and verify that the debugAvailable field has changed - writeBaseConfigFile(configFile, "TRACE"); - appenderContext.reconfigure(); - assertEquals(Level.TRACE, LogService.getLogger(TEST_LOGGER_NAME).getLevel()); - assertTrue(testLogger.isDebugEnabled()); - assertTrue(testLogger.isTraceEnabled()); - assertTrue((Boolean) debugAvailableField.get(FastLogger.class)); + FastLogger.setDelegating(false); - // Modify the config and verify that the debugAvailable field has changed - writeBaseConfigFile(configFile, "INFO"); - appenderContext.reconfigure(); - assertEquals(Level.INFO, LogService.getLogger(TEST_LOGGER_NAME).getLevel()); - assertFalse(testLogger.isDebugEnabled()); - assertFalse((Boolean) debugAvailableField.get(FastLogger.class)); + assertThat(fastLogger.isDelegating(), is(false)); + } + + /** + * FastLogger should delegate getLevel + */ + @Test + public void delegateGetLevel() { + FastLogger.setDelegating(true); + when(this.mockedLogger.getLevel()).thenReturn(Level.DEBUG); - // A reset before the next filter test - writeBaseConfigFile(configFile, "FATAL"); - appenderContext.reconfigure(); - assertFalse((Boolean) debugAvailableField.get(FastLogger.class)); + FastLogger fastLogger = new FastLogger(this.mockedLogger); - // Modify the config and verify that the debugAvailable field has changed - writeLoggerFilterConfigFile(configFile); - appenderContext.reconfigure(); - assertEquals(Level.ERROR, LogService.getLogger(TEST_LOGGER_NAME).getLevel()); - assertFalse(testLogger.isDebugEnabled()); - assertTrue((Boolean) debugAvailableField.get(FastLogger.class)); + assertThat(fastLogger.getLevel(), is(Level.DEBUG)); + verify(this.mockedLogger, times(1)).getLevel(); + } + + /** + * FastLogger should delegate isDebugEnabled when isDelegating + */ + @Test + public void delegateIsDebugEnabledWhenIsDelegating() { + FastLogger.setDelegating(true); + when(this.mockedLogger.getLevel()).thenReturn(Level.DEBUG); + when(this.mockedLogger.isEnabled(eq(Level.DEBUG), isNull(Marker.class), isNull(String.class))).thenReturn(true); + when(this.mockedLogger.isEnabled(eq(Level.DEBUG), eq(this.mockedMarker), isNull(Object.class), isNull(Throwable.class))).thenReturn(true); + + FastLogger fastLogger = new FastLogger(this.mockedLogger); - // A reset before the next filter test - writeBaseConfigFile(configFile, "FATAL"); - appenderContext.reconfigure(); - assertFalse((Boolean) debugAvailableField.get(FastLogger.class)); + assertThat(fastLogger.isDebugEnabled(), is(true)); + assertThat(fastLogger.isDebugEnabled(this.mockedMarker), is(true)); + verify(this.mockedLogger, times(1)).isEnabled(eq(Level.DEBUG), any(Marker.class), isNull(String.class)); + verify(this.mockedLogger, times(1)).isEnabled(eq(Level.DEBUG), eq(this.mockedMarker), isNull(Object.class), isNull(Throwable.class)); + } + + /** + * FastLogger should delegate isTraceEnabled when isDelegating + */ + @Test + public void delegateIsTraceEnabledWhenIsDelegating() { + FastLogger.setDelegating(true); + when(this.mockedLogger.getLevel()).thenReturn(Level.TRACE); + when(this.mockedLogger.isEnabled(eq(Level.TRACE), isNull(Marker.class), isNull(Object.class), isNull(Throwable.class))).thenReturn(true); + when(this.mockedLogger.isEnabled(eq(Level.TRACE), eq(this.mockedMarker), isNull(Object.class), isNull(Throwable.class))).thenReturn(true); + + FastLogger fastLogger = new FastLogger(this.mockedLogger); - // Modify the config and verify that the debugAvailable field has changed - writeContextFilterConfigFile(configFile); - appenderContext.reconfigure(); - assertEquals(Level.ERROR, LogService.getLogger(TEST_LOGGER_NAME).getLevel()); - assertFalse(testLogger.isDebugEnabled()); - assertTrue((Boolean) debugAvailableField.get(FastLogger.class)); + assertThat(fastLogger.isTraceEnabled(), is(true)); + assertThat(fastLogger.isTraceEnabled(this.mockedMarker), is(true)); + verify(this.mockedLogger, times(1)).isEnabled(eq(Level.TRACE), isNull(Marker.class), isNull(Object.class), isNull(Throwable.class)); + verify(this.mockedLogger, times(1)).isEnabled(eq(Level.TRACE), eq(this.mockedMarker), isNull(Object.class), isNull(Throwable.class)); } /** - * Verifies that default the configuration sets the FastLogger debugAvailable to false. + * FastLogger should not delegate isDebugEnabled when not isDelegating */ @Test - public final void testDefaultConfig() throws Exception { - LogService.reconfigure(); - assertTrue(LogService.isUsingGemFireDefaultConfig()); + public void notDelegateIsDebugEnabledWhenNotIsDelegating() { + FastLogger.setDelegating(false); + when(this.mockedLogger.getLevel()).thenReturn(Level.INFO); + + FastLogger fastLogger = new FastLogger(this.mockedLogger); - // Get a reference to the debugAvailable field in FastLogger - Field debugAvailableField = FastLogger.class.getDeclaredField("debugAvailable"); - debugAvailableField.setAccessible(true); - boolean debugAvailable = (Boolean) debugAvailableField.get(FastLogger.class); - assertFalse("FastLogger debugAvailable should be false for default config", debugAvailable); + assertThat(fastLogger.getLevel(), is(Level.INFO)); + assertThat(fastLogger.isDebugEnabled(), is(false)); + assertThat(fastLogger.isDebugEnabled(this.mockedMarker), is(false)); + verify(this.mockedLogger, times(0)).isEnabled(eq(Level.DEBUG), isNull(Marker.class), isNull(String.class)); + verify(this.mockedLogger, times(0)).isEnabled(eq(Level.DEBUG), eq(this.mockedMarker), isNull(Object.class), isNull(Throwable.class)); } - private static void writeBaseConfigFile(final File configFile, final String level) throws IOException { - final BufferedWriter writer = new BufferedWriter(new FileWriter(configFile)); - writer.write( - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" - ); - writer.close(); + /** + * FastLogger should not delegate isTraceEnabled when not isDelegating + */ + @Test + public void notDelegateIsTraceEnabledWhenNotIsDelegating() { + FastLogger.setDelegating(false); + when(mockedLogger.getLevel()).thenReturn(Level.INFO); + + FastLogger fastLogger = new FastLogger(this.mockedLogger); + + assertThat(fastLogger.getLevel(), is(Level.INFO)); + assertThat(fastLogger.isTraceEnabled(), is(false)); + assertThat(fastLogger.isTraceEnabled(this.mockedMarker), is(false)); + verify(this.mockedLogger, times(0)).isEnabled(eq(Level.TRACE), isNull(Marker.class), isNull(String.class)); + verify(this.mockedLogger, times(0)).isEnabled(eq(Level.TRACE), eq(this.mockedMarker), isNull(Object.class), isNull(Throwable.class)); } - private static void writeLoggerFilterConfigFile(final File configFile) throws IOException { - final BufferedWriter writer = new BufferedWriter(new FileWriter(configFile)); - writer.write( - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" - ); - writer.close(); + /** + * FastLogger should wrap delegate and return from getExtendedLogger + */ + @Test + public void wrapDelegateAndReturnFromGetExtendedLogger() { + FastLogger fastLogger = new FastLogger(this.mockedLogger); + + assertThat(fastLogger.getExtendedLogger(), is(sameInstance(this.mockedLogger))); } - private static void writeContextFilterConfigFile(final File configFile) throws IOException { - final BufferedWriter writer = new BufferedWriter(new FileWriter(configFile)); - writer.write( - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" - ); - writer.close(); + /** + * FastLogger should delegate getName + */ + @Test + public void delegateGetName() { + when(this.mockedLogger.getName()).thenReturn("name"); + + FastLogger fastLogger = new FastLogger(this.mockedLogger); + + assertThat(fastLogger.getName(), is("name")); + verify(this.mockedLogger, times(1)).getName(); } } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1c4cd8f7/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerWithDefaultConfigJUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerWithDefaultConfigJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerWithDefaultConfigJUnitTest.java new file mode 100755 index 0000000..2e08500 --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/FastLoggerWithDefaultConfigJUnitTest.java @@ -0,0 +1,74 @@ +package com.gemstone.gemfire.internal.logging.log4j; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +import org.apache.logging.log4j.Logger; +import org.apache.logging.log4j.core.config.ConfigurationFactory; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.RestoreSystemProperties; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.internal.logging.LogService; +import com.gemstone.gemfire.test.junit.categories.IntegrationTest; + +/** + * Integration tests for FastLogger when using the default log4j2 config for GemFire. + * + * @author Kirk Lund + * @author David Hoots + */ +@Category(IntegrationTest.class) +public class FastLoggerWithDefaultConfigJUnitTest { + + private static final String TEST_LOGGER_NAME = FastLogger.class.getPackage().getName(); + + @Rule + public final RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties(); + + private Logger logger; + + @Before + public void setUp() throws Exception { + System.clearProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY); + LogService.reconfigure(); + } + + /** + * System property "log4j.configurationFile" should be "/com/gemstone/gemfire/internal/logging/log4j/log4j2-default.xml" + */ + @Test + public void configurationFilePropertyIsDefaultConfig() { + assertThat(System.getProperty(ConfigurationFactory.CONFIGURATION_FILE_PROPERTY), containsString(LogService.DEFAULT_CONFIG)); + } + + /** + * LogService isUsingGemFireDefaultConfig should be true + */ + @Test + public void isUsingGemFireDefaultConfig() { + assertThat(LogService.isUsingGemFireDefaultConfig(), is(true)); + } + + /** + * LogService getLogger should return loggers wrapped in FastLogger + */ + @Test + public void logServiceReturnsFastLoggers() { + this.logger = LogService.getLogger(TEST_LOGGER_NAME); + + assertThat(this.logger, is(instanceOf(FastLogger.class))); + } + + /** + * FastLogger isDelegating should be false + */ + @Test + public void isDelegatingShouldBeFalse() { + this.logger = LogService.getLogger(TEST_LOGGER_NAME); + + assertThat(((FastLogger)this.logger).isDelegating(), is(false)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1c4cd8f7/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/Log4jIntegrationTestSuite.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/Log4jIntegrationTestSuite.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/Log4jIntegrationTestSuite.java new file mode 100755 index 0000000..7cab077 --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/Log4jIntegrationTestSuite.java @@ -0,0 +1,12 @@ +package com.gemstone.gemfire.internal.logging.log4j; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + FastLoggerWithDefaultConfigJUnitTest.class, + FastLoggerIntegrationJUnitTest.class, +}) +public class Log4jIntegrationTestSuite { +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/1c4cd8f7/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/Log4jUnitTestSuite.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/Log4jUnitTestSuite.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/Log4jUnitTestSuite.java new file mode 100755 index 0000000..1441b0c --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/logging/log4j/Log4jUnitTestSuite.java @@ -0,0 +1,16 @@ +package com.gemstone.gemfire.internal.logging.log4j; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + AlertAppenderJUnitTest.class, + ConfigLocatorJUnitTest.class, + FastLoggerJUnitTest.class, + FastLoggerWithDefaultConfigJUnitTest.class, + LocalizedMessageJUnitTest.class, + LogWriterAppenderJUnitTest.class, +}) +public class Log4jUnitTestSuite { +}