513 lines
23 KiB
Java
513 lines
23 KiB
Java
|
/*
|
||
|
* 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();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|