--- a/jdk/src/share/classes/java/util/logging/Logger.java Thu Sep 12 01:47:05 2013 -0700
+++ b/jdk/src/share/classes/java/util/logging/Logger.java Thu Sep 12 17:01:39 2013 +0200
@@ -635,7 +635,7 @@
* @param record the LogRecord to be published
*/
public void log(LogRecord record) {
- if (record.getLevel().intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(record.getLevel())) {
return;
}
Filter theFilter = filter;
@@ -689,7 +689,7 @@
* @param msg The string message (or a key in the message catalog)
*/
public void log(Level level, String msg) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
@@ -710,7 +710,7 @@
* desired log message
*/
public void log(Level level, Supplier<String> msgSupplier) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msgSupplier.get());
@@ -729,7 +729,7 @@
* @param param1 parameter to the message
*/
public void log(Level level, String msg, Object param1) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
@@ -750,7 +750,7 @@
* @param params array of parameters to the message
*/
public void log(Level level, String msg, Object params[]) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
@@ -775,7 +775,7 @@
* @param thrown Throwable associated with log message.
*/
public void log(Level level, String msg, Throwable thrown) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
@@ -803,7 +803,7 @@
* @since 1.8
*/
public void log(Level level, Throwable thrown, Supplier<String> msgSupplier) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msgSupplier.get());
@@ -829,7 +829,7 @@
* @param msg The string message (or a key in the message catalog)
*/
public void logp(Level level, String sourceClass, String sourceMethod, String msg) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
@@ -856,7 +856,7 @@
*/
public void logp(Level level, String sourceClass, String sourceMethod,
Supplier<String> msgSupplier) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msgSupplier.get());
@@ -881,7 +881,7 @@
*/
public void logp(Level level, String sourceClass, String sourceMethod,
String msg, Object param1) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
@@ -908,7 +908,7 @@
*/
public void logp(Level level, String sourceClass, String sourceMethod,
String msg, Object params[]) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
@@ -939,7 +939,7 @@
*/
public void logp(Level level, String sourceClass, String sourceMethod,
String msg, Throwable thrown) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
@@ -973,7 +973,7 @@
*/
public void logp(Level level, String sourceClass, String sourceMethod,
Throwable thrown, Supplier<String> msgSupplier) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msgSupplier.get());
@@ -1021,7 +1021,7 @@
*/
public void logrb(Level level, String sourceClass, String sourceMethod,
String bundleName, String msg) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
@@ -1052,7 +1052,7 @@
*/
public void logrb(Level level, String sourceClass, String sourceMethod,
String bundleName, String msg, Object param1) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
@@ -1085,7 +1085,7 @@
*/
public void logrb(Level level, String sourceClass, String sourceMethod,
String bundleName, String msg, Object params[]) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
@@ -1122,7 +1122,7 @@
*/
public void logrb(Level level, String sourceClass, String sourceMethod,
String bundleName, String msg, Throwable thrown) {
- if (level.intValue() < levelValue || levelValue == offValue) {
+ if (!isLoggable(level)) {
return;
}
LogRecord lr = new LogRecord(level, msg);
@@ -1148,9 +1148,6 @@
* @param sourceMethod name of method that is being entered
*/
public void entering(String sourceClass, String sourceMethod) {
- if (Level.FINER.intValue() < levelValue) {
- return;
- }
logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
}
@@ -1167,11 +1164,7 @@
* @param param1 parameter to the method being entered
*/
public void entering(String sourceClass, String sourceMethod, Object param1) {
- if (Level.FINER.intValue() < levelValue) {
- return;
- }
- Object params[] = { param1 };
- logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", params);
+ logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", param1);
}
/**
@@ -1188,14 +1181,12 @@
* @param params array of parameters to the method being entered
*/
public void entering(String sourceClass, String sourceMethod, Object params[]) {
- if (Level.FINER.intValue() < levelValue) {
- return;
- }
String msg = "ENTRY";
if (params == null ) {
logp(Level.FINER, sourceClass, sourceMethod, msg);
return;
}
+ if (!isLoggable(Level.FINER)) return;
for (int i = 0; i < params.length; i++) {
msg = msg + " {" + i + "}";
}
@@ -1213,9 +1204,6 @@
* @param sourceMethod name of the method
*/
public void exiting(String sourceClass, String sourceMethod) {
- if (Level.FINER.intValue() < levelValue) {
- return;
- }
logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
}
@@ -1233,10 +1221,6 @@
* @param result Object that is being returned
*/
public void exiting(String sourceClass, String sourceMethod, Object result) {
- if (Level.FINER.intValue() < levelValue) {
- return;
- }
- Object params[] = { result };
logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
}
@@ -1262,7 +1246,7 @@
* @param thrown The Throwable that is being thrown.
*/
public void throwing(String sourceClass, String sourceMethod, Throwable thrown) {
- if (Level.FINER.intValue() < levelValue || levelValue == offValue ) {
+ if (!isLoggable(Level.FINER)) {
return;
}
LogRecord lr = new LogRecord(Level.FINER, "THROW");
@@ -1286,9 +1270,6 @@
* @param msg The string message (or a key in the message catalog)
*/
public void severe(String msg) {
- if (Level.SEVERE.intValue() < levelValue) {
- return;
- }
log(Level.SEVERE, msg);
}
@@ -1302,9 +1283,6 @@
* @param msg The string message (or a key in the message catalog)
*/
public void warning(String msg) {
- if (Level.WARNING.intValue() < levelValue) {
- return;
- }
log(Level.WARNING, msg);
}
@@ -1318,9 +1296,6 @@
* @param msg The string message (or a key in the message catalog)
*/
public void info(String msg) {
- if (Level.INFO.intValue() < levelValue) {
- return;
- }
log(Level.INFO, msg);
}
@@ -1334,9 +1309,6 @@
* @param msg The string message (or a key in the message catalog)
*/
public void config(String msg) {
- if (Level.CONFIG.intValue() < levelValue) {
- return;
- }
log(Level.CONFIG, msg);
}
@@ -1350,9 +1322,6 @@
* @param msg The string message (or a key in the message catalog)
*/
public void fine(String msg) {
- if (Level.FINE.intValue() < levelValue) {
- return;
- }
log(Level.FINE, msg);
}
@@ -1366,9 +1335,6 @@
* @param msg The string message (or a key in the message catalog)
*/
public void finer(String msg) {
- if (Level.FINER.intValue() < levelValue) {
- return;
- }
log(Level.FINER, msg);
}
@@ -1382,9 +1348,6 @@
* @param msg The string message (or a key in the message catalog)
*/
public void finest(String msg) {
- if (Level.FINEST.intValue() < levelValue) {
- return;
- }
log(Level.FINEST, msg);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/Logger/isLoggable/TestIsLoggable.java Thu Sep 12 17:01:39 2013 +0200
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code 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
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+/**
+ * @test
+ * @bug 8024525
+ * @summary checks that isLoggable() can be overridden to control logging.
+ * @author danielfuchs
+ * @run main/othervm TestIsLoggable
+ */
+public class TestIsLoggable {
+
+ // This logger can be configured to override its default level
+ // for a particular set of thread ids
+ public static final class ThreadLogger extends Logger {
+
+ final Map<Long, Level> threadMap =
+ Collections.synchronizedMap(new HashMap<Long, Level>());
+
+ public ThreadLogger(String name) {
+ super(name, null);
+ }
+
+ @Override
+ public boolean isLoggable(Level level) {
+ final Level threadLevel = threadMap.get(Thread.currentThread().getId());
+ if (threadLevel == null) return super.isLoggable(level);
+ final int levelValue = threadLevel.intValue();
+ final int offValue = Level.OFF.intValue();
+ if (level.intValue() < levelValue || levelValue == offValue) {
+ return false;
+ }
+ return true;
+ }
+
+ }
+
+ public static final class TestHandler extends Handler {
+
+ final List<String> messages = new CopyOnWriteArrayList<>();
+
+ @Override
+ public void publish(LogRecord record) {
+ messages.add(record.getMessage());
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void close() throws SecurityException {
+ messages.clear();
+ }
+
+ }
+
+ // Sorted list of standard levels
+ static final List<Level> LEVELS = Collections.unmodifiableList(
+ java.util.Arrays.asList(new Level[] {
+ Level.SEVERE, Level.WARNING, Level.INFO, Level.CONFIG,
+ Level.FINE, Level.FINER, Level.FINEST
+ }));
+
+ // Test cases:
+ // LEV_ test logger.severe(msg) .. logger.finest(msg)
+ // LOG_ logger.log(Level.SEVERE, msg) ... logger.log(Level.FINEST, msg)
+ // LOG1_ logger.log(Level.SEVERE, msg, param1) ...
+ // LOG2_ logger.log(Level.SEVERE, msg, params[]) ...
+ // LOG3_ logger.log(Level.SEVERE, msg, throwable) ...
+ // LOGP_ logger.logp(Level.SEVERE, class, method, msg) ...
+ // LOGP1_ logger.logp(Level.SEVERE, class, method, msg, param1) ...
+ // LOGP2_ logger.logp(Level.SEVERE, class, method, msg, params[]) ...
+ // LOGP3_ logger.logp(Level.SEVERE, class, method, msg, throwable) ...
+ public static enum LogTest {
+ LEV_SEVERE, LEV_WARNING, LEV_INFO, LEV_CONFIG, LEV_FINE, LEV_FINER, LEV_FINEST,
+ LOG_SEVERE, LOG_WARNING, LOG_INFO, LOG_CONFIG, LOG_FINE, LOG_FINER, LOG_FINEST,
+ LOG1_SEVERE, LOG1_WARNING, LOG1_INFO, LOG1_CONFIG, LOG1_FINE, LOG1_FINER, LOG1_FINEST,
+ LOG2_SEVERE, LOG2_WARNING, LOG2_INFO, LOG2_CONFIG, LOG2_FINE, LOG2_FINER, LOG2_FINEST,
+ LOG3_SEVERE, LOG3_WARNING, LOG3_INFO, LOG3_CONFIG, LOG3_FINE, LOG3_FINER, LOG3_FINEST,
+ LOGP_SEVERE, LOGP_WARNING, LOGP_INFO, LOGP_CONFIG, LOGP_FINE, LOGP_FINER, LOGP_FINEST,
+ LOGP1_SEVERE, LOGP1_WARNING, LOGP1_INFO, LOGP1_CONFIG, LOGP1_FINE, LOGP1_FINER, LOGP1_FINEST,
+ LOGP2_SEVERE, LOGP2_WARNING, LOGP2_INFO, LOGP2_CONFIG, LOGP2_FINE, LOGP2_FINER, LOGP2_FINEST,
+ LOGP3_SEVERE, LOGP3_WARNING, LOGP3_INFO, LOGP3_CONFIG, LOGP3_FINE, LOGP3_FINER, LOGP3_FINEST;
+
+ // call the method Logger.severe() ... Logger.finest() corresponding
+ // to the given level 'l' (severe() for SEVERE etc...)
+ public void loglevel(Level l, Logger logger, String message) {
+ LogTest test = LogTest.valueOf("LEV_"+l.getName());
+ switch(test) {
+ case LEV_SEVERE:
+ logger.severe(message);
+ break;
+ case LEV_WARNING:
+ logger.warning(message);
+ break;
+ case LEV_INFO:
+ logger.info(message);
+ break;
+ case LEV_CONFIG:
+ logger.config(message);
+ break;
+ case LEV_FINE:
+ logger.fine(message);
+ break;
+ case LEV_FINER:
+ logger.finer(message);
+ break;
+ case LEV_FINEST:
+ logger.finest(message);
+ break;
+ }
+ }
+
+ // The threshold at which the logger is expected to start logging.
+ // trick: we derive the threshold level from the testcase name...
+ public Level threshold() {
+ for (Level l : LEVELS ) {
+ if (this.toString().endsWith(l.getName())) {
+ return l;
+ }
+ }
+ return Level.OFF;
+ }
+
+ // Levels for which the logger is expected to log something.
+ public List<Level> loggable() {
+ return LEVELS.subList(0, LEVELS.indexOf(threshold())+1);
+ }
+
+ // Levels which will be blocked because they are weaker than the
+ // threshold()
+ public List<Level> weaker() {
+ return LEVELS.subList(LEVELS.indexOf(threshold())+1, LEVELS.size());
+ }
+
+ // Log a message at this testcase threshold, using this testcase method.
+ public void log(Logger logger, String message) {
+ log(threshold(), logger, message);
+ }
+
+ // Log a message at the given level, using this testcase method.
+ public void log(Level level, Logger logger, String message) {
+ if (this.toString().startsWith("LOG_")) {
+ logger.log(level, message);
+ } else if (this.toString().startsWith("LOG1_")) {
+ logger.log(level, message, "dummy param");
+ } else if (this.toString().startsWith("LOG2_")) {
+ logger.log(level, message, new Object[] {"dummy", "param"});
+ } else if (this.toString().startsWith("LOG3_")) {
+ logger.log(level, message, new Exception("dummy exception"));
+ } else if (this.toString().startsWith("LOGP_")) {
+ logger.logp(level, "TestCase", "log", message);
+ } else if (this.toString().startsWith("LOGP1_")) {
+ logger.logp(level, "TestCase", "log", message, "dummy param");
+ } else if (this.toString().startsWith("LOGP2_")) {
+ logger.logp(level, "TestCase", "log", message,
+ new Object[] {"dummy", "param"});
+ } else if (this.toString().startsWith("LOGP3_")) {
+ logger.logp(level, "TestCase", "log", message,
+ new Exception("dummy exception"));
+ } else if (this.toString().startsWith("LEV_")) {
+ loglevel(level, logger, message);
+ }
+ }
+
+ // String description of the logging method called.
+ public String method() {
+ if (this.toString().startsWith("LOG_")) {
+ return "Logger.log(Level." + threshold().getName() +", msg): ";
+ } else if (this.toString().startsWith("LOG1_")) {
+ return "Logger.log(Level." + threshold().getName() +", msg, param1): ";
+ } else if (this.toString().startsWith("LOG2_")) {
+ return "Logger.log(Level." + threshold().getName() +", msg, params[]): ";
+ } else if (this.toString().startsWith("LOG3_")) {
+ return "Logger.log(Level." + threshold().getName() +", msg, throwable): ";
+ } else if (this.toString().startsWith("LEV_")) {
+ return "Logger."+threshold().getName().toLowerCase(Locale.ROOT)+"(): ";
+ } else if (this.toString().startsWith("LOGP_")) {
+ return "Logger.logp(Level." + threshold().getName() +", msg): ";
+ } else if (this.toString().startsWith("LOGP1_")) {
+ return "Logger.logp(Level." + threshold().getName() +", msg, param1): ";
+ } else if (this.toString().startsWith("LOGP2_")) {
+ return "Logger.logp(Level." + threshold().getName() +", msg, params[]): ";
+ } else if (this.toString().startsWith("LOGP3_")) {
+ return "Logger.logp(Level." + threshold().getName() +", msg, throwable): ";
+ }
+ throw new RuntimeException("Unknown test case: "+this);
+ }
+ }
+
+ // The purpose of this test is to verify that the various log methods in
+ // Logger now call Logger.isLoggable().
+ // To do that - we're going to use a subclass of Logger, ThreadLogger, which
+ // only overrides isLoggable() - and compare the level it is given to a level
+ // it finds in a map indexed with the current thread id.
+ // We will register a TestHandler with our ThreadLogger which will store
+ // the messages in a messages map. This will allow us to verify whether the
+ // logging method we're testing has or hasn't logged.
+ //
+ // The TestCase enum above allows us to test a combination of every possible
+ // log method with every possible level inside a loop - with the
+ // exception of exiting/entering/throwing that we will be testing
+ // outside of that loop.
+ //
+ public static void main(String... args) {
+ LogManager manager = LogManager.getLogManager();
+ ThreadLogger logger = new ThreadLogger("foo.bar");
+ //manager.addLogger(logger);
+ TestHandler handler = new TestHandler();
+ logger.addHandler(handler);
+
+ //By default, logger's level is Level.INFO
+ final List<Level> loggable = LEVELS.subList(0, LEVELS.indexOf(Level.INFO)+1);
+
+ // Check our test implementation of logger.isLoggable();
+ //
+ // Since we haven't put anything in the threadMap, isLoggable() should
+ // return true for all levels stronger or equals to Level.INFO.
+ // here we're just checking that our implementation of
+ // ThreadLogger.isLoggable() returns what we want - we're just testing
+ // the test code...
+ for (Level level : LEVELS) {
+ if (logger.isLoggable(level) != loggable.contains(level)) {
+ throw new RuntimeException(level +
+ ": unexpected result for isLoggable(): expected " +
+ (loggable.contains(level)));
+ }
+ }
+
+ // Test that entering/exiting/throwing call isLoggable()
+
+ // Here we test the default behavior: this call shouldn't log anything
+ // because by default the logger level is Level.INFO and these
+ // methods log at Level.FINER.
+ // So by default - these methods don't log anything. We check it here.
+ logger.entering("blah", "blah");
+ logger.entering("blah", "blah", "blah");
+ logger.entering("blah", "blah", new Object[] {"blah"});
+ if (!handler.messages.isEmpty()) {
+ throw new RuntimeException("Expected empty, got "+handler.messages);
+ }
+
+ logger.exiting("blah", "blah");
+ logger.exiting("blah", "blah", "blah");
+ logger.exiting("blah", "blah", new Object[] {"blah"});
+ if (!handler.messages.isEmpty()) {
+ throw new RuntimeException("Expected empty, got "+handler.messages);
+ }
+
+ logger.throwing("blah", "blah", new Exception("blah"));
+ if (!handler.messages.isEmpty()) {
+ throw new RuntimeException("Expected empty, got "+handler.messages);
+ }
+
+ // Now we're going to put each level in turn in the threadMap.
+ // This means that isLoggable(Level.FINER) should now return true if the
+ // level in the map is not one of the level in the 'stronger' list below
+ // (here stronger=stronger than FINER)
+ final List<Level> stronger = LEVELS.subList(0, LEVELS.indexOf(Level.FINER));
+ for (Level l : LEVELS) {
+
+ logger.threadMap.put(Thread.currentThread().getId(), l);
+
+ // Check that our implementation of isLoggable(level) now returns true
+ // if 'level' is stronger or equals to 'l' - here we're just checking
+ // that our implementation of ThreadLogger.isLoggable() returns what
+ // we want - we're just testing the test code...
+ final List<Level> loggableLevels = LEVELS.subList(0, LEVELS.indexOf(l)+1);
+ for (Level level : LEVELS) {
+ if (logger.isLoggable(level) != loggableLevels.contains(level)) {
+ throw new RuntimeException(level +
+ ": unexpected result for isLoggable(): expected " +
+ (loggableLevels.contains(level)));
+ }
+ }
+
+ // These methods should now start to log when the level we put in
+ // the map is weaker or equals to Level.FINER.
+ // This validates that these methods now call ThreadLogger.isLoggable()
+ // since the default level for our logger is still Level.INFO.
+ // If the methods didn't call ThreadLogger.isLoggable() they wouldn't
+ // log anything, whatever we put in the threadMap...
+
+ logger.entering("blah", "blah");
+ logger.entering("blah", "blah", "blah");
+ logger.entering("blah", "blah", new Object[] {"blah"});
+ if (stronger.contains(l)) {
+ if (!handler.messages.isEmpty()) {
+ throw new RuntimeException(l +
+ ": Expected empty, got " + handler.messages);
+ }
+ } else {
+ if (handler.messages.size() != 3) {
+ throw new RuntimeException(l +
+ ": Expected size 3, got " + handler.messages);
+ }
+ }
+
+ logger.exiting("blah", "blah");
+ logger.exiting("blah", "blah", "blah");
+ logger.exiting("blah", "blah", new Object[] {"blah"});
+ if (stronger.contains(l)) {
+ if (!handler.messages.isEmpty()) {
+ throw new RuntimeException(l +
+ ": Expected empty, got " + handler.messages);
+ }
+ } else {
+ if (handler.messages.size() != 6) {
+ throw new RuntimeException(l +
+ ": Expected size 6, got " + handler.messages);
+ }
+ }
+
+ logger.throwing("blah", "blah", new Exception("blah"));
+ if (stronger.contains(l)) {
+ if (!handler.messages.isEmpty()) {
+ throw new RuntimeException(l +
+ ": Expected empty, got " + handler.messages);
+ }
+ } else {
+ if (handler.messages.size() != 7) {
+ throw new RuntimeException(l +
+ ": Expected size 7, got " + handler.messages);
+ }
+ }
+ if (!stronger.contains(l)) {
+ System.out.println(l + ": Logger.entering/exiting/throwing: " +
+ handler.messages);
+ }
+ handler.messages.clear();
+ }
+
+ // Cleanup so that we can start the next test with a clean plate...
+ handler.messages.clear();
+ logger.threadMap.clear();
+
+ // Test that each logging method calls isLoggable()
+ //
+ for (LogTest testCase : LogTest.values()) {
+ // Each test case is a combination of:
+ // 1. A level to put in the threadMap.
+ // 2. A log method to call
+ final String method = testCase.method();
+
+ // check our implementation of logger.isLoggable();
+ // by default the logger level is Level.INFO, so our implementation
+ // of isLoggable() should return true for all levels stronger or
+ // equal to INFO and false for the others.
+ // We check that here.
+ for (Level level : LEVELS) {
+ if (logger.isLoggable(level) != loggable.contains(level)) {
+ throw new RuntimeException(level +
+ ": unexpected result for isLoggable(): expected " +
+ (loggable.contains(level)));
+ }
+ }
+
+ // Check that by default the log method will not log for level
+ // weaker than Level.INFO.
+ for (Level l : LEVELS.subList(LEVELS.indexOf(Level.INFO) + 1, LEVELS.size())) {
+ final String test = method + l + ": ";
+ testCase.log(l, logger, "blah");
+ if (!handler.messages.isEmpty()) {
+ throw new RuntimeException(test +
+ "Expected empty, got " + handler.messages);
+ }
+ }
+
+ // Let's put Level.OFF in the threadMap. Nothing should be logged,
+ // whichever level is used...
+ logger.threadMap.put(Thread.currentThread().getId(), Level.OFF);
+
+ // Check that isLoggable() now always return false.
+ for (Level level : LEVELS) {
+ if (logger.isLoggable(level)) {
+ throw new RuntimeException(level +
+ ": unexpected result for isLoggable(): expected " +
+ false);
+ }
+ }
+
+ // Check that the log method of the test case won't log, whatever
+ // level we pass to it. This validates that level method calls
+ // isLoggable() - because otherwise it would log for levels stronger
+ // or equal to INFO.
+ for (Level l : LEVELS) {
+ final String test = "[threadMap=OFF] " + method + l + ": ";
+ testCase.log(l, logger, "blah");
+ if (!handler.messages.isEmpty()) {
+ throw new RuntimeException(test +
+ "Expected empty, got " + handler.messages);
+ }
+ }
+ System.out.println("[threadMap=OFF] " + method + "logged " + handler.messages);
+
+ // Now put the testcase's level in the threadMap.
+ logger.threadMap.put(Thread.currentThread().getId(), testCase.threshold());
+
+ // The levels for which logging should happen are those that are stronger
+ // or equals to the testcase's thresholds.
+ final List<Level> loggableLevels =
+ LEVELS.subList(0, LEVELS.indexOf(testCase.threshold())+1);
+
+ // Check that our implementation of isLoggable() is taking into account
+ // what we put in the map.
+ for (Level level : LEVELS) {
+ if (logger.isLoggable(level) != loggableLevels.contains(level)) {
+ throw new RuntimeException(level +
+ ": unexpected result for isLoggable(): expected " +
+ (loggableLevels.contains(level)));
+ }
+ }
+
+ // Now check that the log method is indeed calling our implementation
+ // of isLoggable(). We do this by first verifying that it won't log
+ // for levels weaker than what we put in the map.
+ //
+ for (Level l : testCase.weaker()) {
+ final String test = method + l + ": ";
+ testCase.log(l, logger, "blah");
+ if (!handler.messages.isEmpty()) {
+ throw new RuntimeException(test +
+ "Expected empty, got " + handler.messages);
+ }
+ }
+
+ // Then we check that it will log for the testcase threshold.
+ final String test2 = method + testCase.threshold() + ": ";
+ testCase.log(logger, testCase.threshold() + " blah");
+ if (handler.messages.isEmpty()) {
+ throw new RuntimeException(test2 +
+ "Expected 1 message, but list is empty");
+ }
+ if (!handler.messages.contains(testCase.threshold() + " blah")) {
+ throw new RuntimeException(test2 + " blah not found: "
+ + handler.messages);
+ }
+ handler.messages.clear();
+
+ // Now we check that it logs for all 'loggable' level (and doesn't
+ // log for the others).
+ for (Level l : LEVELS) {
+ final String test = method + l + ": ";
+ testCase.log(l, logger, l + ": blah");
+ if (testCase.loggable().contains(l)) {
+ if (!handler.messages.contains(l + ": blah")) {
+ throw new RuntimeException(test + "blah not found: " +
+ handler.messages);
+ }
+ } else {
+ if (handler.messages.contains(l + ": blah")) {
+ throw new RuntimeException(test + "blah found: " +
+ handler.messages);
+ }
+ }
+ }
+ if (handler.messages.size() != testCase.loggable().size()) {
+ throw new RuntimeException(method +
+ " Sizes don't match: expected " +
+ testCase.loggable().size() + " got " +
+ handler.messages);
+ }
+
+ // Some visual feedback on what happened.
+ System.out.println(method + "logged " + handler.messages);
+
+ // Cleanup for next step.
+ // Since we're iterating over all possible levels we can be
+ // sure that we haven't missed anything.
+ // For instance - it could be argued that logger.severe() will
+ // always log. But since we have 1 case where we put Level.OFF in
+ // the map and we have verified that severe() didn't log in that
+ // case, but that it logged in any other case, then we know
+ // beyond doubt that it called our implementation of isLoggable().
+ logger.threadMap.clear();
+ handler.messages.clear();
+ }
+
+ }
+}