// Copyright 2009 Google Inc. All Rights Reserved. // // 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 com.google.enterprise.connector.logging; import junit.framework.TestCase; import java.util.GregorianCalendar; import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.SimpleFormatter; /** * Unit Test for logging LayoutPattern. */ public class LayoutPatternTest extends TestCase { private LogRecord logRecord; private String logMessage = "That's one small step for [a] man, one giant leap for mankind."; private String className = "gov.nasa.apollo.lander.LunarModule"; private String methodName = "moonWalk"; private long threadId; private String threadName = "Armstrong"; private SimpleFormatter simpleFormatter = new SimpleFormatter(); @Override protected void setUp() throws Exception { GregorianCalendar cal = new GregorianCalendar(); cal.set(1969, 7, 20, 20, 17, 40); logRecord = new LogRecord(Level.INFO, logMessage); logRecord.setSequenceNumber(11); logRecord.setMillis(cal.getTimeInMillis()); logRecord.setSourceClassName(className); logRecord.setSourceMethodName(methodName); threadId = Thread.currentThread().getId(); logRecord.setThreadID((int)(threadId)); Thread.currentThread().setName(threadName); } @Override protected void tearDown() throws Exception { MDC.remove(); NDC.remove(); } // Check that formatting via the pattern generates the expected output. private void checkFormat(String pattern, String expected) { LayoutPattern layout = new LayoutPattern(pattern); String output = layout.format(logRecord); // System.out.println("pattern: \"" + pattern + "\" expected: \"" // + expected + "\" output: \"" + output + "\""); assertEquals(expected, output); } /** Test constant string. Should go through unmolested. */ public void testConstantString() { String pattern = "The quick brown fox jumped over the lazy dog's back."; checkFormat(pattern, pattern); } /** Test empty string. Should go through unmolested. */ public void testEmptyString() { checkFormat("", ""); } /** Just a single format element. */ public void testMessageString() { checkFormat("%m", logMessage); } /** Just a single format element, with some additional text. */ public void testMessageString1() { String pattern = "Neil said, %m"; String expected = "Neil said, " + logMessage; checkFormat(pattern, expected); } /** Just a single format element, with some additional text. */ public void testMessageString2() { String pattern = "%m - Neil"; String expected = logMessage + " - Neil"; checkFormat(pattern, expected); } /** Just a single format element, with some surrounding text. */ public void testMessageString3() { String pattern = "Neil said, %m Buzz was silent."; String expected = "Neil said, " + logMessage + " Buzz was silent."; checkFormat(pattern, expected); } /** Two adjacent format elements. */ public void testTwoAdjacent() { checkFormat("%m%m", logMessage + logMessage); } /** Test '%%' is quoted percent. */ public void testPercentPercent() { checkFormat("%%", "%"); } /** Test '%%' is quoted percent, and some additional text. */ public void testPercentPercent1() { checkFormat("50%%", "50%"); } /** Test '%%' is quoted percent, and some additional text. */ public void testPercentPercent2() { checkFormat("%% percent", "% percent"); } /** Test '%%' is quoted percent, and some surrounding text. */ public void testPercentPercent3() { checkFormat("50%% off!", "50% off!"); } /** Test '%%%%' is quoted percent, should return '%%'. */ public void testPercentPercent4() { checkFormat("%%%%", "%%"); } /** * Test '%%' is quoted percent, followed by what looks like a * conversion char. */ public void testPercentPercent5() { checkFormat("%%C", "%C"); } /** * Test '%%' is quoted percent, followed by what looks like a * modifier + conversion char. */ public void testPercentPercent6() { checkFormat("%%-5C", "%-5C"); } /** Test '%%' is quoted percent, followed by valid conversion char. */ public void testPercentPercent7() { checkFormat("%%%M", "%moonWalk"); } /** Test '%%' is quoted percent, followed by modified conversion char. */ public void testPercentPercent8() { checkFormat("%%%-10M", "%moonWalk "); } /** Test '%%' is quoted percent, followed by valid conversion char. */ public void testPercentPercent9() { checkFormat("%%-5C", "%-5C"); } /** Test unimplemented Conversion, should be silently dropped. */ public void testUnimplemented() { checkFormat("%F", ""); } /** Test unimplemented Conversion, should be silently dropped. */ public void testUnimplemented1() { checkFormat("Not %F implemented", "Not implemented"); } /** Test thread id and name. */ public void testThreadIdName() { String pattern = "%T - %t"; String expected = threadId + " - " + threadName; checkFormat(pattern, expected); } /** Test className and methodName. */ public void testClassAndMethodName() { String pattern = "%C - %M"; String expected = className + " - " + methodName; checkFormat(pattern, expected); } /** Test %n newline. */ public void testNewLine() { String pattern = "line1%nline2"; String expected = "line1" + System.getProperty("line.separator") + "line2"; checkFormat(pattern, expected); } /** Test SequenceNumber. */ public void testSequenceNumber() { checkFormat("Apollo %N", "Apollo 11"); } /** Test Default Date format. */ public void testDefaultDate() { String pattern = "%d"; String expected = "1969-08-20 20:17:40"; checkFormat(pattern, expected); } /** Test Default Date format with additional text. */ public void testDefaultDate1() { String pattern = "%d moon landing"; String expected = "1969-08-20 20:17:40 moon landing"; checkFormat(pattern, expected); } /** Test non-default Date format. */ public void testFormattedDate() { String pattern = "%d{yyyy-MM-dd'T'HH:mm'Z'}"; String expected = "1969-08-20T20:17Z"; checkFormat(pattern, expected); } /** Test non-default Date format with some text. */ public void testFormattedDate1() { String pattern = "%d{yyyy-MM-dd'T'HH:mm'Z'} touch down"; String expected = "1969-08-20T20:17Z touch down"; checkFormat(pattern, expected); } /** Test invalid Date format. */ public void testInvalidDateFormat() { String pattern = "%d{xyzzy}"; String expected = "xyzzy"; try { checkFormat(pattern, expected); fail("Expected IllegalArgumentException to be thrown."); } catch (IllegalArgumentException expect) { assertTrue(expect.getMessage().startsWith("Illegal pattern character")); } } /** Test partial ClassName with %C{n}. Just leaf classname. */ public void testPartialClassName() { checkFormat("%C{1}", "LunarModule"); } /** Test partial ClassName with %C{n}. 4 segments. */ public void testPartialClassName1() { checkFormat("%C{4}", "nasa.apollo.lander.LunarModule"); } /** Test partial ClassName with %C{n}. 5 segments - the exact size. */ public void testPartialClassName2() { checkFormat("%C{5}", className); } /** Test partial ClassName with %C{n}. Should give the whole thing. */ public void testPartialClassName3() { checkFormat("%C{10}", className); } /** Test partial ClassName with %C{n}. Should give the whole thing. */ public void testPartialClassName4() { checkFormat("%C{0}", className); } /** Test format Modifier minWidth. */ public void testModifierMinWidth() { checkFormat("%10M", " moonWalk"); } /** Test format Modifier minWidth. */ public void testModifierMinWidth2() { checkFormat("%5M", "moonWalk"); } /** Test format Modifier minWidth - left justified. */ public void testModifierLeftJustified() { checkFormat("%-10M", "moonWalk "); } /** Test format Modifier minWidth - left justified. */ public void testModifierLeftJustified1() { checkFormat("%-5M", "moonWalk"); } /** Test format Modifier maxWidth. */ public void testModifierMaxWidth() { checkFormat("%.33m", "That's one small step for [a] man"); } /** Test format Modifier maxWidth. */ public void testModifierMaxWidth1() { checkFormat("%.133m", logMessage); } /** Test format Modifier minWidth:maxWidth. */ public void testModifierMinMaxWidth() { checkFormat("%10.133m", logMessage); } /** Test format Modifier minWidth:maxWidth. */ public void testModifierMinMaxWidth1() { checkFormat("%10.133M", " moonWalk"); } /** Test format Modifier minWidth:maxWidth. */ public void testModifierMinMaxWidth2() { checkFormat("%5.133M", "moonWalk"); } /** Test format Modifier minWidth:maxWidth. */ public void testModifierMinMaxWidth3() { checkFormat("%5.33m", "That's one small step for [a] man"); } /** Test format Modifier -minWidth:maxWidth. */ public void testModifierMinMaxWidthLeftJustified() { checkFormat("%-10.133m", logMessage); } /** Test format Modifier -minWidth:maxWidth. */ public void testModifierMinMaxWidthLeftJustified1() { checkFormat("%-10.133M", "moonWalk "); } /** Test format Modifier -minWidth:maxWidth. */ public void testModifierMinMaxWidthLeftJustified2() { checkFormat("%-5.133M", "moonWalk"); } /** Test format Modifier -minWidth:maxWidth. */ public void testModifierMinMaxWidthLeftJustified3() { checkFormat("%-5.33m", "That's one small step for [a] man"); } /** Test format Modifier 0 minWidth. */ public void testModifierMinWidth0() { checkFormat("%0M", "moonWalk"); } /** Test format Modifier 0 maxWidth. */ public void testModifierMaxWidth0() { checkFormat("%.0M", ""); } /** Test Wrapped formatter - %f */ public void testWrappedFormatter() { String simpleOutput = simpleFormatter.format(logRecord); LayoutPattern layout = new LayoutPattern("%-4N [%T %t] %f", simpleFormatter); String output = layout.format(logRecord); String expected = "11 [" + threadId + " Armstrong] " + simpleOutput; assertEquals(output, expected); } /** Test Wrapped formatter - %m */ public void testWrappedFormatter1() { LayoutPattern layout = new LayoutPattern("%-4N [%t] %m", simpleFormatter); String output = layout.format(logRecord); String expected = "11 [Armstrong] " + logMessage; assertEquals(output, expected); } /** Replicate SimpleFormatter. */ public void testReplicateSimpleFormatter() { String simpleOutput = simpleFormatter.format(logRecord); // Try to replicate the SimpleFormatter layout. String pattern = "%d{MMM dd, yyyy h:mm:ss a} %C %M%n%p: %m%n"; LayoutPattern layout = new LayoutPattern(pattern); String output = layout.format(logRecord); assertEquals(output, simpleOutput); } /** Test NDC logging with %x. */ public void testNDC() { String pattern = "[%x] %M"; // No context should be empty string. checkFormat(pattern, "[] moonWalk"); NDC.push("Neil Armstrong"); checkFormat(pattern, "[Neil Armstrong] moonWalk"); NDC.push("Buzz Aldrin"); checkFormat(pattern, "[Buzz Aldrin] moonWalk"); NDC.pop(); checkFormat(pattern, "[Neil Armstrong] moonWalk"); NDC.clear(); checkFormat(pattern, "[] moonWalk"); } /** Test MDC logging with %X. */ public void testMDC() { String pattern = "[%X{Astronaut}] %M"; // No context should be empty string. checkFormat(pattern, "[] moonWalk"); MDC.put("Astronaut", "Neil Armstrong"); checkFormat(pattern, "[Neil Armstrong] moonWalk"); MDC.put("Astronaut", "Buzz Aldrin"); checkFormat(pattern, "[Buzz Aldrin] moonWalk"); MDC.put("Astronaut", "Neil Armstrong"); checkFormat(pattern, "[Neil Armstrong] moonWalk"); MDC.remove("Astronaut"); checkFormat(pattern, "[] moonWalk"); MDC.clear(); } /** Test MDC logging with %X and multiple key/value pairs. */ public void testMDC2() { String pattern = "[%X{Astronaut} %X{WingMan}] %M"; // No context should be empty string. checkFormat(pattern, "[ ] moonWalk"); MDC.put("Astronaut", "Neil Armstrong"); checkFormat(pattern, "[Neil Armstrong ] moonWalk"); MDC.put("WingMan", "Buzz Aldrin"); checkFormat(pattern, "[Neil Armstrong Buzz Aldrin] moonWalk"); MDC.remove("Astronaut"); checkFormat(pattern, "[ Buzz Aldrin] moonWalk"); MDC.remove("WingMan"); checkFormat(pattern, "[ ] moonWalk"); MDC.clear(); } }