View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package org.apache.log4j;
    19
    20  import org.apache.log4j.spi.LoggingEvent;
    21  import org.w3c.dom.Document;
    22  import org.xml.sax.InputSource;
    23
    24  import javax.xml.parsers.DocumentBuilder;
    25  import javax.xml.parsers.DocumentBuilderFactory;
    26  import java.io.Reader;
    27  import java.io.StringReader;
    28  import java.util.Hashtable;
    29
    30
    31  /***
    32   * Test for HTMLLayout.
    33   *
    34   * @author Curt Arnold
    35   */
    36  public class HTMLLayoutTest extends LayoutTest {
    37    /***
    38     * Construct new instance of XMLLayoutTest.
    39     *
    40     * @param testName test name.
    41     */
    42    public HTMLLayoutTest(final String testName) {
    43      super(testName, "text/html", false, null, null);
    44    }
    45
    46    /***
    47     * @{inheritDoc}
    48     */
    49    protected Layout createLayout() {
    50      return new HTMLLayout();
    51    }
    52
    53    /***
    54     * Parses the string as the body of an XML document and returns the document element.
    55     * @param source source string.
    56     * @return document element.
    57     * @throws Exception if parser can not be constructed or source is not a valid XML document.
    58     */
    59    private Document parse(final String source) throws Exception {
    60      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    61      factory.setNamespaceAware(false);
    62      factory.setCoalescing(true);
    63
    64      DocumentBuilder builder = factory.newDocumentBuilder();
    65      Reader reader = new StringReader(source);
    66
    67      return builder.parse(new InputSource(reader));
    68    }
    69
    70    /***
    71     * Tests formatted results.
    72     * @throws Exception if unable to create parser or output is not valid XML.
    73     */
    74    public void testFormat() throws Exception {
    75      Logger logger = Logger.getLogger("org.apache.log4j.xml.HTMLLayoutTest");
    76      NDC.push("NDC goes here");
    77
    78      LoggingEvent event =
    79        new LoggingEvent(
    80          "org.apache.log4j.Logger", logger, Level.INFO, "Hello, World", null);
    81      HTMLLayout layout = (HTMLLayout) createLayout();
    82      layout.setLocationInfo(true);
    83
    84      String result = layout.format(event);
    85      NDC.pop();
    86
    87      String src =
    88        "<!DOCTYPE body [ <!ENTITY nbsp ' '>]><body>" + result + "</body>";
    89      Document doc = parse(src);
    90    }
    91
    92    /***
    93     * Tests getHeader.
    94     */
    95    public void testGetHeader() {
    96      assertEquals("<!DOCTYPE", createLayout().getHeader().substring(0, 9));
    97    }
    98
    99    /***
    100    * Tests getHeader with locationInfo = true.
    101    */
    102   public void testGetHeaderWithLocation() {
    103     HTMLLayout layout = (HTMLLayout) createLayout();
    104     layout.setLocationInfo(true);
    105     assertEquals("<!DOCTYPE", layout.getHeader().substring(0, 9));
    106   }
    107
    108   /***
    109    * Tests getFooter.
    110    */
    111   public void testGetFooter() {
    112     assertEquals("</table>", createLayout().getFooter().substring(0, 8));
    113   }
    114
    115   /***
    116    * Tests getLocationInfo and setLocationInfo.
    117    */
    118   public void testGetSetLocationInfo() {
    119     HTMLLayout layout = new HTMLLayout();
    120     assertEquals(false, layout.getLocationInfo());
    121     layout.setLocationInfo(true);
    122     assertEquals(true, layout.getLocationInfo());
    123     layout.setLocationInfo(false);
    124     assertEquals(false, layout.getLocationInfo());
    125   }
    126
    127   /***
    128    * Tests activateOptions().
    129    */
    130   public void testActivateOptions() {
    131     HTMLLayout layout = new HTMLLayout();
    132     layout.activateOptions();
    133   }
    134
    135   /***
    136    * Tests getTitle and setTitle.
    137    */
    138   public void testGetSetTitle() {
    139     HTMLLayout layout = new HTMLLayout();
    140     assertEquals("Log4J Log Messages", layout.getTitle());
    141     layout.setTitle(null);
    142     assertNull(layout.getTitle());
    143
    144     String newTitle = "A treatise on messages of log persuasion";
    145     layout.setTitle(newTitle);
    146     assertEquals(newTitle, layout.getTitle());
    147   }
    148
    149   /***
    150    * Tests buffer downsizing and DEBUG and WARN colorization code paths.
    151    */
    152   public void testFormatResize() {
    153     Logger logger = Logger.getLogger("org.apache.log4j.xml.HTMLLayoutTest");
    154     NDC.clear();
    155
    156     char[] msg = new char[2000];
    157
    158     for (int i = 0; i < msg.length; i++) {
    159       msg[i] = 'A';
    160     }
    161
    162     LoggingEvent event1 =
    163       new LoggingEvent(
    164         "org.apache.log4j.Logger", logger, Level.DEBUG, new String(msg), null);
    165     HTMLLayout layout = (HTMLLayout) createLayout();
    166     layout.setLocationInfo(true);
    167
    168     String result = layout.format(event1);
    169     Exception ex = new IllegalArgumentException("'foo' is not a valid value.");
    170     LoggingEvent event2 =
    171       new LoggingEvent(
    172         "org.apache.log4j.Logger", logger, Level.WARN, "Hello, World", ex);
    173     result = layout.format(event2);
    174     assertEquals(
    175       Layout.LINE_SEP + "<tr>",
    176       result.substring(0, Layout.LINE_SEP.length() + 4));
    177   }
    178
    179
    180     /***
    181      * Level with arbitrary toString value.
    182      */
    183     private static final class ProblemLevel extends Level {
    184         /***
    185          * Construct new instance.
    186          * @param levelName level name, may not be null.
    187          */
    188         public ProblemLevel(final String levelName) {
    189             super(6000, levelName, 6);
    190         }
    191     }
    192
    193     /***
    194      * Tests problematic characters in multiple fields.
    195      * @throws Exception if parser can not be constructed
    196      *  or source is not a valid XML document.
    197      */
    198     public void testProblemCharacters() throws Exception {
    199       String problemName = "com.example.bar<>&\"'";
    200       Logger logger = Logger.getLogger(problemName);
    201       Level level = new ProblemLevel(problemName);
    202       Exception ex = new IllegalArgumentException(problemName);
    203       String threadName = Thread.currentThread().getName();
    204       Thread.currentThread().setName(problemName);
    205       NDC.push(problemName);
    206       Hashtable mdcMap = MDC.getContext();
    207       if (mdcMap != null) {
    208           mdcMap.clear();
    209       }
    210       MDC.put(problemName, problemName);
    211       LoggingEvent event =
    212         new LoggingEvent(
    213           problemName, logger, level, problemName, ex);
    214       HTMLLayout layout = (HTMLLayout) createLayout();
    215       String result = layout.format(event);
    216       mdcMap = MDC.getContext();
    217       if (mdcMap != null) {
    218         mdcMap.clear();
    219       }
    220
    221       Thread.currentThread().setName(threadName);
    222
    223       //
    224       //  do a little fixup to make output XHTML
    225       //
    226       StringBuffer buf = new StringBuffer(
    227               "<!DOCTYPE table [<!ENTITY nbsp ' '>]><table>");
    228       buf.append(result);
    229       buf.append("</table>");
    230       String doc = buf.toString();
    231       for(int i = doc.lastIndexOf("<br>");
    232           i != -1;
    233           i = doc.lastIndexOf("<br>", i - 1)) {
    234           buf.replace(i, i + 4, "<br/>");
    235       }
    236
    237       parse(buf.toString());
    238     }
    239
    240 }