/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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 org.apache.log4j; import org.apache.log4j.spi.LoggingEvent; import org.w3c.dom.Document; import org.xml.sax.InputSource; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.Reader; import java.io.StringReader; import java.util.Hashtable; /** * Test for HTMLLayout. * * @author Curt Arnold */ public class HTMLLayoutTest extends LayoutTest { /** * Construct new instance of XMLLayoutTest. * * @param testName test name. */ public HTMLLayoutTest(final String testName) { super(testName, "text/html", false, null, null); } /** * @{inheritDoc} */ protected Layout createLayout() { return new HTMLLayout(); } /** * Parses the string as the body of an XML document and returns the document element. * @param source source string. * @return document element. * @throws Exception if parser can not be constructed or source is not a valid XML document. */ private Document parse(final String source) throws Exception { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(false); factory.setCoalescing(true); DocumentBuilder builder = factory.newDocumentBuilder(); Reader reader = new StringReader(source); return builder.parse(new InputSource(reader)); } /** * Tests formatted results. * @throws Exception if unable to create parser or output is not valid XML. */ public void testFormat() throws Exception { Logger logger = Logger.getLogger("org.apache.log4j.xml.HTMLLayoutTest"); NDC.push("NDC goes here"); LoggingEvent event = new LoggingEvent( "org.apache.log4j.Logger", logger, Level.INFO, "Hello, World", null); HTMLLayout layout = (HTMLLayout) createLayout(); layout.setLocationInfo(true); String result = layout.format(event); NDC.pop(); String src = "<!DOCTYPE body [ <!ENTITY nbsp ' '>]><body>" + result + "</body>"; parse(src); } /** * Tests getHeader. */ public void testGetHeader() { assertEquals("<!DOCTYPE", createLayout().getHeader().substring(0, 9)); } /** * Tests getHeader with locationInfo = true. */ public void testGetHeaderWithLocation() { HTMLLayout layout = (HTMLLayout) createLayout(); layout.setLocationInfo(true); assertEquals("<!DOCTYPE", layout.getHeader().substring(0, 9)); } /** * Tests getFooter. */ public void testGetFooter() { assertEquals("</table>", createLayout().getFooter().substring(0, 8)); } /** * Tests getLocationInfo and setLocationInfo. */ public void testGetSetLocationInfo() { HTMLLayout layout = new HTMLLayout(); assertEquals(false, layout.getLocationInfo()); layout.setLocationInfo(true); assertEquals(true, layout.getLocationInfo()); layout.setLocationInfo(false); assertEquals(false, layout.getLocationInfo()); } /** * Tests activateOptions(). */ public void testActivateOptions() { HTMLLayout layout = new HTMLLayout(); layout.activateOptions(); } /** * Tests getTitle and setTitle. */ public void testGetSetTitle() { HTMLLayout layout = new HTMLLayout(); assertEquals("Log4J Log Messages", layout.getTitle()); layout.setTitle(null); assertNull(layout.getTitle()); String newTitle = "A treatise on messages of log persuasion"; layout.setTitle(newTitle); assertEquals(newTitle, layout.getTitle()); } /** * Tests buffer downsizing and DEBUG and WARN colorization code paths. */ public void testFormatResize() { Logger logger = Logger.getLogger("org.apache.log4j.xml.HTMLLayoutTest"); NDC.clear(); char[] msg = new char[2000]; for (int i = 0; i < msg.length; i++) { msg[i] = 'A'; } LoggingEvent event1 = new LoggingEvent( "org.apache.log4j.Logger", logger, Level.DEBUG, new String(msg), null); HTMLLayout layout = (HTMLLayout) createLayout(); layout.setLocationInfo(true); String result = layout.format(event1); Exception ex = new IllegalArgumentException("'foo' is not a valid value."); LoggingEvent event2 = new LoggingEvent( "org.apache.log4j.Logger", logger, Level.WARN, "Hello, World", ex); result = layout.format(event2); assertEquals( Layout.LINE_SEP + "<tr>", result.substring(0, Layout.LINE_SEP.length() + 4)); } /** * Level with arbitrary toString value. */ private static final class ProblemLevel extends Level { private static final long serialVersionUID = 1L; /** * Construct new instance. * @param levelName level name, may not be null. */ public ProblemLevel(final String levelName) { super(6000, levelName, 6); } } /** * Tests problematic characters in multiple fields. * @throws Exception if parser can not be constructed * or source is not a valid XML document. */ public void testProblemCharacters() throws Exception { String problemName = "com.example.bar<>&\"'"; Logger logger = Logger.getLogger(problemName); Level level = new ProblemLevel(problemName); Exception ex = new IllegalArgumentException(problemName); String threadName = Thread.currentThread().getName(); Thread.currentThread().setName(problemName); NDC.push(problemName); Hashtable mdcMap = MDC.getContext(); if (mdcMap != null) { mdcMap.clear(); } MDC.put(problemName, problemName); LoggingEvent event = new LoggingEvent( problemName, logger, level, problemName, ex); HTMLLayout layout = (HTMLLayout) createLayout(); String result = layout.format(event); mdcMap = MDC.getContext(); if (mdcMap != null) { mdcMap.clear(); } Thread.currentThread().setName(threadName); // // do a little fixup to make output XHTML // StringBuffer buf = new StringBuffer( "<!DOCTYPE table [<!ENTITY nbsp ' '>]><table>"); buf.append(result); buf.append("</table>"); String doc = buf.toString(); for(int i = doc.lastIndexOf("<br>"); i != -1; i = doc.lastIndexOf("<br>", i - 1)) { buf.replace(i, i + 4, "<br/>"); } parse(buf.toString()); } }