/*
* Copyright 2010 Proofpoint, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.airlift.log;
import com.google.common.collect.ImmutableList;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
@Test(singleThreaded = true)
public class TestLogger
{
private MockHandler handler;
private Logger logger;
private java.util.logging.Logger inner;
@BeforeMethod
public void setUp()
throws Exception
{
handler = new MockHandler();
inner = java.util.logging.Logger.getAnonymousLogger();
inner.setUseParentHandlers(false);
inner.setLevel(Level.ALL);
inner.addHandler(handler);
logger = new Logger(inner);
}
@AfterMethod(alwaysRun = true)
public void teardown()
{
assertTrue(handler.isEmpty(), "Some log messages were not verified by test");
}
@Test
public void testIsDebugEnabled()
{
inner.setLevel(Level.FINE);
assertTrue(logger.isDebugEnabled());
inner.setLevel(Level.INFO);
assertFalse(logger.isDebugEnabled());
inner.setLevel(Level.WARNING);
assertFalse(logger.isDebugEnabled());
inner.setLevel(Level.SEVERE);
assertFalse(logger.isDebugEnabled());
}
@Test
public void testDebugFormat()
{
inner.setLevel(Level.FINE);
logger.debug("hello, %s", "you");
assertLog(Level.FINE, "hello, you");
}
@Test
public void testInfoFormat()
{
inner.setLevel(Level.INFO);
logger.info("hello, %s", "you");
assertLog(Level.INFO, "hello, you");
}
@Test
public void testWarnFormat()
{
inner.setLevel(Level.WARNING);
// message-only version
logger.warn("hello, %s", "you");
assertLog(Level.WARNING, "hello, you");
// throwable with message
@SuppressWarnings({"ThrowableInstanceNeverThrown"})
Throwable exception = new Throwable();
logger.warn(exception, "got exception: %s", "foo");
assertLog(Level.WARNING, "got exception: foo", exception);
}
@Test
public void testErrorFormat()
{
// message-only version
logger.error("hello, %s", "you");
assertLog(Level.SEVERE, "hello, you");
// throwable with message
@SuppressWarnings({"ThrowableInstanceNeverThrown"})
Throwable exception = new Throwable();
logger.error(exception, "got exception: %s", "foo");
assertLog(Level.SEVERE, "got exception: foo", exception);
// throwable alone
@SuppressWarnings({"ThrowableInstanceNeverThrown"})
Throwable exception2 = new Throwable("the message");
logger.error(exception2);
assertLog(Level.SEVERE, exception2.getMessage(), exception2);
}
@Test
public void testDebugShortCircuit()
{
inner.setLevel(Level.OFF);
logger.debug("hello");
assertTrue(handler.isEmpty());
}
@Test
public void testInfoShortCircuit()
{
inner.setLevel(Level.OFF);
logger.info("hello");
assertTrue(handler.isEmpty());
}
@Test
public void testWarnShortCircuit()
{
inner.setLevel(Level.OFF);
logger.warn("hello");
assertTrue(handler.isEmpty());
}
@Test
public void testWarnWithThrowableShortCircuit()
{
inner.setLevel(Level.OFF);
@SuppressWarnings({"ThrowableInstanceNeverThrown"})
Throwable e = new Throwable();
logger.warn(e, "hello");
assertTrue(handler.isEmpty());
}
@Test
public void testErrorShortCircuit()
{
inner.setLevel(Level.OFF);
logger.error("hello");
assertTrue(handler.isEmpty());
}
@Test
public void testErrorWithThrowableShortCircuit()
{
inner.setLevel(Level.OFF);
@SuppressWarnings({"ThrowableInstanceNeverThrown"})
Throwable e = new Throwable();
logger.error(e, "hello");
assertTrue(handler.isEmpty());
}
@Test
public void testErrorWithThrowableNoMessageShortCircuit()
{
inner.setLevel(Level.OFF);
@SuppressWarnings({"ThrowableInstanceNeverThrown"})
Throwable e = new Throwable();
logger.error(e);
assertTrue(handler.isEmpty());
}
@Test
public void testInsufficientArgsLogsErrorForDebug()
{
String format = "some message: %s, %d";
String param = "blah";
logger.debug(format, param);
assertLogLike(Level.SEVERE, ImmutableList.of("Invalid format", "DEBUG", format, param), IllegalArgumentException.class);
assertLog(Level.FINE, String.format("'%s' [%s]", format, param));
}
@Test
public void testInsufficientArgsLogsErrorForInfo()
{
String format = "some message: %s, %d";
String param = "blah";
logger.info(format, param);
assertLogLike(Level.SEVERE, ImmutableList.of("Invalid format", "INFO", format, param), IllegalArgumentException.class);
assertLog(Level.INFO, String.format("'%s' [%s]", format, param));
}
@Test
public void testInsufficientArgsLogsErrorForWarn()
{
String format = "some message: %s, %d";
String param = "blah";
logger.warn(format, param);
assertLogLike(Level.SEVERE, ImmutableList.of("Invalid format", "WARN", format, param), IllegalArgumentException.class);
assertLog(Level.WARNING, String.format("'%s' [%s]", format, param));
}
@Test
public void testInsufficientArgsLogsErrorForError()
{
String format = "some message: %s, %d";
String param = "blah";
logger.error(format, param);
assertLogLike(Level.SEVERE, ImmutableList.of("Invalid format", "ERROR", format, param), IllegalArgumentException.class);
assertLog(Level.SEVERE, String.format("'%s' [%s]", format, param));
}
@Test
public void testInsufficientArgsLogsOriginalExceptionForWarn()
{
Throwable exception = new Throwable("foo");
String format = "some message: %s, %d";
String param = "blah";
logger.warn(exception, format, param);
assertLogLike(Level.SEVERE, ImmutableList.of("Invalid format", "WARN", format, param), IllegalArgumentException.class);
assertLog(Level.WARNING, String.format("'%s' [%s]", format, param), exception);
}
@Test
public void testInsufficientArgsLogsOriginalExceptionForError()
{
Throwable exception = new Throwable("foo");
String format = "some message: %s, %d";
String param = "blah";
logger.error(exception, format, param);
assertLogLike(Level.SEVERE, ImmutableList.of("Invalid format", "ERROR", format, param), IllegalArgumentException.class);
assertLog(Level.SEVERE, String.format("'%s' [%s]", format, param), exception);
}
private void assertLog(Level level, String message, Throwable exception)
{
LogRecord record = handler.takeRecord();
assertEquals(record.getLevel(), level);
assertEquals(record.getMessage(), message);
assertEquals(record.getThrown(), exception);
}
private void assertLog(Level level, String message)
{
LogRecord record = handler.takeRecord();
assertEquals(record.getLevel(), level);
assertEquals(record.getMessage(), message);
assertNull(record.getThrown());
}
private void assertLogLike(Level level, List<String> substrings, Class<? extends Throwable> exceptionClass)
{
LogRecord record = handler.takeRecord();
assertEquals(record.getLevel(), level);
assertTrue(stringContains(record.getMessage(), substrings));
assertTrue(exceptionClass.isAssignableFrom(record.getThrown().getClass()));
}
private boolean stringContains(String value, List<String> substrings)
{
for (String str : substrings) {
if (!value.contains(str)) {
return false;
}
}
return true;
}
private static class MockHandler
extends Handler
{
private final List<LogRecord> records = new ArrayList<>();
private MockHandler()
{
setLevel(Level.ALL);
}
@Override
public void publish(LogRecord record)
{
records.add(record);
}
@Override
public void flush()
{
}
@Override
public void close()
throws SecurityException
{
}
public LogRecord takeRecord()
{
assertTrue(!records.isEmpty(), "No messages logged");
return records.remove(0);
}
public boolean isEmpty()
{
return records.isEmpty();
}
}
}