    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.net;
    19
    20  import junit.framework.TestCase;
    21  import junit.framework.TestSuite;
    22  import junit.framework.Test;
    23
    24  import org.apache.log4j.*;
    25  import org.apache.log4j.util.*;
    26
    27
    28  import org.apache.log4j.Logger;
    29  import org.apache.log4j.NDC;
    30  import org.apache.log4j.xml.XLevel;
    31
    32  /**
    33     @author  Ceki G&uuml;lc&uuml;
    34  */
    35  public class SocketServerTestCase extends TestCase {
    36
    37    static String TEMP = "output/temp";
    38    static String FILTERED = "output/filtered";
    39
    40    // %5p %x [%t] %c %m%n
    41    // DEBUG T1 [main] org.apache.log4j.net.SocketAppenderTestCase Message 1
    42    static String PAT1 = "^(TRACE|DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) T1 \\[main]\\ "
    43                         + ".* Message \\d{1,2}";
    44
    45    // DEBUG T2 [main] ? (?:?) Message 1
    46    static String PAT2 = "^(TRACE|DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) T2 \\[main]\\ "
    47                         + "\\? \\(\\?:\\?\\) Message \\d{1,2}";
    48
    49
    50    // DEBUG T3 [main] org.apache.log4j.net.SocketServerTestCase (SocketServerTestCase.java:121) Message 1
    51    static String PAT3 = "^(TRACE|DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) T3 \\[main]\\ "
    52                         + "org.apache.log4j.net.SocketServerTestCase "
    53                         + "\\(SocketServerTestCase.java:\\d{3}\\) Message \\d{1,2}";
    54
    55
    56    // DEBUG some T4 MDC-TEST4 [main] SocketAppenderTestCase - Message 1
    57    // DEBUG some T4 MDC-TEST4 [main] SocketAppenderTestCase - Message 1
    58    static String PAT4 = "^(TRACE|DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some T4 MDC-TEST4 \\[main]\\"
    59                         + " (root|SocketServerTestCase) - Message \\d{1,2}";
    60
    61    static String PAT5 = "^(TRACE|DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some5 T5 MDC-TEST5 \\[main]\\"
    62                         + " (root|SocketServerTestCase) - Message \\d{1,2}";
    63
    64    static String PAT6 = "^(TRACE|DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some6 T6 client-test6 MDC-TEST6"
    65                         + " \\[main]\\ (root|SocketServerTestCase) - Message \\d{1,2}";
    66
    67    static String PAT7 = "^(TRACE|DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some7 T7 client-test7 MDC-TEST7"
    68                         + " \\[main]\\ (root|SocketServerTestCase) - Message \\d{1,2}";
    69
    70    // DEBUG some8 T8 shortSocketServer MDC-TEST7 [main] SocketServerTestCase - Message 1
    71    static String PAT8 = "^(TRACE|DEBUG| INFO| WARN|ERROR|FATAL|LETHAL) some8 T8 shortSocketServer"
    72                         + " MDC-TEST8 \\[main]\\ (root|SocketServerTestCase) - Message \\d{1,2}";
    73
    74
    75
    76    static String EXCEPTION1 = "java.lang.Exception: Just testing";
    77    static String EXCEPTION2 = "\\s*at .*\\(.*\\)";
    78    static String EXCEPTION3 = "\\s*at .*\\(Native Method\\)";
    79    static String EXCEPTION4 = "\\s*at .*\\(.*Compiled Code\\)";
    80    static String EXCEPTION5 = "\\s*at .*\\(.*libgcj.*\\)";
    81
    82
    83    static Logger logger = Logger.getLogger(SocketServerTestCase.class);
    84    static public final int PORT = 12345;
    85    static Logger rootLogger = Logger.getRootLogger();
    86    SocketAppender socketAppender;
    87
    88    public SocketServerTestCase(String name) {
    89      super(name);
    90    }
    91
    92    public void setUp() {
    93      System.out.println("Setting up test case.");
    94    }
    95
    96    public void tearDown() {
    97      System.out.println("Tearing down test case.");
    98      socketAppender = null;
    99      rootLogger.removeAllAppenders();
    100   }
    101
    102   /**
    103    * The pattern on the server side: %5p %x [%t] %c %m%n
    104    *
    105    * We are testing NDC functionality across the wire.
    106    */
    107   public void test1() throws Exception {
    108     socketAppender = new SocketAppender("localhost", PORT);
    109     rootLogger.addAppender(socketAppender);
    110     common("T1", "key1", "MDC-TEST1");
    111     delay(1);
    112     ControlFilter cf = new ControlFilter(new String[]{PAT1, EXCEPTION1,
    113 						       EXCEPTION2, EXCEPTION3, EXCEPTION4, EXCEPTION5});
    114
    115     Transformer.transform(
    116       TEMP, FILTERED,
    117       new Filter[] { cf, new LineNumberFilter(),
    118           new JunitTestRunnerFilter(),
    119           new SunReflectFilter() });
    120
    121     assertTrue(Compare.compare(FILTERED, "witness/socketServer.1"));
    122   }
    123
    124   /**
    125    * The pattern on the server side: %5p %x [%t] %C (%F:%L) %m%n
    126    *
    127    * We are testing NDC across the wire. Localization is turned off by
    128    * default so it is not tested here even if the conversion pattern
    129    * uses localization. */
    130   public void test2() throws Exception {
    131     socketAppender = new SocketAppender("localhost", PORT);
    132     rootLogger.addAppender(socketAppender);
    133
    134     common("T2", "key2", "MDC-TEST2");
    135     delay(1);
    136     ControlFilter cf = new ControlFilter(new String[]{PAT2, EXCEPTION1,
    137 						       EXCEPTION2, EXCEPTION3, EXCEPTION4, EXCEPTION5});
    138
    139     Transformer.transform(
    140       TEMP, FILTERED,
    141       new Filter[] { cf, new LineNumberFilter(),
    142           new JunitTestRunnerFilter(),
    143           new SunReflectFilter() });
    144
    145     assertTrue(Compare.compare(FILTERED, "witness/socketServer.2"));
    146   }
    147
    148   /**
    149    *  The pattern on the server side: %5p %x [%t] %C (%F:%L) %m%n
    150    *  meaning that we are testing NDC and locatization functionality
    151    *  across the wire.  */
    152   public void test3() throws Exception {
    153     socketAppender = new SocketAppender("localhost", PORT);
    154     socketAppender.setLocationInfo(true);
    155     rootLogger.addAppender(socketAppender);
    156
    157     common("T3", "key3", "MDC-TEST3");
    158     delay(1);
    159     ControlFilter cf = new ControlFilter(new String[]{PAT3, EXCEPTION1,
    160 						       EXCEPTION2, EXCEPTION3, EXCEPTION4, EXCEPTION5});
    161
    162     Transformer.transform(
    163       TEMP, FILTERED,
    164       new Filter[] { cf, new LineNumberFilter(),
    165           new JunitTestRunnerFilter(),
    166           new SunReflectFilter() });
    167
    168     assertTrue(Compare.compare(FILTERED, "witness/socketServer.3"));
    169   }
    170
    171   /**
    172    *  The pattern on the server side: %5p %x %X{key1}%X{key4} [%t] %c{1} - %m%n
    173    *  meaning that we are testing NDC, MDC and localization functionality across
    174    *  the wire.
    175   */
    176   public void test4() throws Exception {
    177     socketAppender = new SocketAppender("localhost", PORT);
    178     socketAppender.setLocationInfo(true);
    179     rootLogger.addAppender(socketAppender);
    180
    181     NDC.push("some");
    182     common("T4", "key4", "MDC-TEST4");
    183     NDC.pop();
    184     delay(1);
    185     //
    186     //  These tests check MDC operation which
    187     //    requires JDK 1.2 or later
    188     if(!System.getProperty("java.version").startsWith("1.1.")) {
    189
    190         ControlFilter cf = new ControlFilter(new String[]{PAT4, EXCEPTION1,
    191 						           EXCEPTION2, EXCEPTION3, EXCEPTION4, EXCEPTION5});
    192         Transformer.transform(
    193           TEMP, FILTERED,
    194           new Filter[] { cf, new LineNumberFilter(),
    195               new JunitTestRunnerFilter(),
    196               new SunReflectFilter() });
    197
    198         assertTrue(Compare.compare(FILTERED, "witness/socketServer.4"));
    199     }
    200   }
    201
    202   /**
    203    * The pattern on the server side: %5p %x %X{key1}%X{key5} [%t] %c{1} - %m%n
    204    *
    205    * The test case uses wraps an AsyncAppender around the
    206    * SocketAppender. This tests was written specifically for bug
    207    * report #9155.
    208
    209    * Prior to the bug fix the output on the server did not contain the
    210    * MDC-TEST5 string because the MDC clone operation (in getMDCCopy
    211    * method) operation is performed twice, once from the main thread
    212    * which is correct, and a second time from the AsyncAppender's
    213    * dispatch thread which is incrorrect.
    214
    215    */
    216   public void test5() throws Exception {
    217     socketAppender = new SocketAppender("localhost", PORT);
    218     socketAppender.setLocationInfo(true);
    219     AsyncAppender asyncAppender = new AsyncAppender();
    220     asyncAppender.setLocationInfo(true);
    221     asyncAppender.addAppender(socketAppender);
    222     rootLogger.addAppender(asyncAppender);
    223
    224     NDC.push("some5");
    225     common("T5", "key5", "MDC-TEST5");
    226     NDC.pop();
    227     delay(2);
    228     //
    229     //  These tests check MDC operation which
    230     //    requires JDK 1.2 or later
    231     if(!System.getProperty("java.version").startsWith("1.1.")) {
    232         ControlFilter cf = new ControlFilter(new String[]{PAT5, EXCEPTION1,
    233 						           EXCEPTION2, EXCEPTION3, EXCEPTION4, EXCEPTION5});
    234
    235         Transformer.transform(
    236           TEMP, FILTERED,
    237           new Filter[] { cf, new LineNumberFilter(),
    238               new JunitTestRunnerFilter(),
    239               new SunReflectFilter() });
    240
    241         assertTrue(Compare.compare(FILTERED, "witness/socketServer.5"));
    242     }
    243   }
    244
    245   /**
    246    * The pattern on the server side: %5p %x %X{hostID}${key6} [%t] %c{1} - %m%n
    247    *
    248    * This test checks whether client-side MDC overrides the server side.
    249    * It uses an AsyncAppender encapsulating a SocketAppender
    250    */
    251   public void test6() throws Exception {
    252     socketAppender = new SocketAppender("localhost", PORT);
    253     socketAppender.setLocationInfo(true);
    254     AsyncAppender asyncAppender = new AsyncAppender();
    255     asyncAppender.setLocationInfo(true);
    256     asyncAppender.addAppender(socketAppender);
    257     rootLogger.addAppender(asyncAppender);
    258
    259     NDC.push("some6");
    260     MDC.put("hostID", "client-test6");
    261     common("T6", "key6", "MDC-TEST6");
    262     NDC.pop();
    263     MDC.remove("hostID");
    264     delay(2);
    265     //
    266     //  These tests check MDC operation which
    267     //    requires JDK 1.2 or later
    268     if(!System.getProperty("java.version").startsWith("1.1.")) {
    269         ControlFilter cf = new ControlFilter(new String[]{PAT6, EXCEPTION1,
    270 						           EXCEPTION2, EXCEPTION3, EXCEPTION4, EXCEPTION5});
    271
    272         Transformer.transform(
    273           TEMP, FILTERED,
    274           new Filter[] { cf, new LineNumberFilter(),
    275               new JunitTestRunnerFilter(),
    276               new SunReflectFilter() });
    277
    278         assertTrue(Compare.compare(FILTERED, "witness/socketServer.6"));
    279     }
    280   }
    281
    282   /**
    283    * The pattern on the server side: %5p %x %X{hostID}${key7} [%t] %c{1} - %m%n
    284    *
    285    * This test checks whether client-side MDC overrides the server side.
    286    */
    287   public void test7() throws Exception {
    288     socketAppender = new SocketAppender("localhost", PORT);
    289     socketAppender.setLocationInfo(true);
    290     rootLogger.addAppender(socketAppender);
    291
    292     NDC.push("some7");
    293     MDC.put("hostID", "client-test7");
    294     common("T7", "key7", "MDC-TEST7");
    295     NDC.pop();
    296     MDC.remove("hostID");
    297     delay(2);
    298     //
    299     //  These tests check MDC operation which
    300     //    requires JDK 1.2 or later
    301     if(!System.getProperty("java.version").startsWith("1.1.")) {
    302         ControlFilter cf = new ControlFilter(new String[]{PAT7, EXCEPTION1,
    303 						           EXCEPTION2, EXCEPTION3, EXCEPTION4, EXCEPTION5});
    304
    305         Transformer.transform(
    306           TEMP, FILTERED,
    307           new Filter[] { cf, new LineNumberFilter(),
    308               new JunitTestRunnerFilter(),
    309               new SunReflectFilter() });
    310         assertTrue(Compare.compare(FILTERED, "witness/socketServer.7"));
    311     }
    312   }
    313
    314   /**
    315    * The pattern on the server side: %5p %x %X{hostID} ${key8} [%t] %c{1} - %m%n
    316    *
    317    * This test checks whether server side MDC works.
    318    */
    319   public void test8() throws Exception {
    320     socketAppender = new SocketAppender("localhost", PORT);
    321     socketAppender.setLocationInfo(true);
    322     rootLogger.addAppender(socketAppender);
    323
    324     NDC.push("some8");
    325
    326     //
    327     //   The test has relied on the receiving code to
    328     //      combine the sent MDC with the receivers MDC
    329     //      (which contains a value for hostID).
    330     //      The mechanism of how that happens is not clear
    331     //      and it does not work with Apache Harmony.
    332     //      Unclear if it is a Harmony issue.
    333     if (System.getProperty("java.vendor").indexOf("Apache") != -1) {
    334         MDC.put("hostID", "shortSocketServer");
    335     }
    336
    337     common("T8", "key8", "MDC-TEST8");
    338     NDC.pop();
    339     delay(2);
    340     //
    341     //  These tests check MDC operation which
    342     //    requires JDK 1.2 or later
    343     if(!System.getProperty("java.version").startsWith("1.1.")) {
    344         ControlFilter cf = new ControlFilter(new String[]{PAT8, EXCEPTION1,
    345 						           EXCEPTION2, EXCEPTION3, EXCEPTION4, EXCEPTION5});
    346
    347         Transformer.transform(
    348           TEMP, FILTERED,
    349           new Filter[] { cf, new LineNumberFilter(),
    350               new JunitTestRunnerFilter(),
    351               new SunReflectFilter() });
    352         assertTrue(Compare.compare(FILTERED, "witness/socketServer.8"));
    353     }
    354   }
    355
    356   static
    357   void common(String dc, String key, Object o) {
    358     String oldThreadName = Thread.currentThread().getName();
    359     Thread.currentThread().setName("main");
    360
    361     int i = -1;
    362     NDC.push(dc);
    363     MDC.put(key, o);
    364     Logger root = Logger.getRootLogger();
    365
    366     logger.setLevel(Level.DEBUG);
    367     rootLogger.setLevel(Level.DEBUG);
    368
    369     logger.log(XLevel.TRACE, "Message " + ++i);
    370
    371     logger.setLevel(Level.TRACE);
    372     rootLogger.setLevel(Level.TRACE);
    373
    374     logger.trace("Message " + ++i);
    375     root.trace("Message " + ++i);
    376     logger.debug("Message " + ++i);
    377     root.debug("Message " + ++i);
    378     logger.info("Message " + ++i);
    379     logger.warn("Message " + ++i);
    380     logger.log(XLevel.LETHAL, "Message " + ++i); //5
    381
    382     Exception e = new Exception("Just testing");
    383     logger.debug("Message " + ++i, e);
    384     root.error("Message " + ++i, e);
    385     NDC.pop();
    386     MDC.remove(key);
    387
    388     Thread.currentThread().setName(oldThreadName);
    389   }
    390
    391   public void delay(int secs) {
    392     try {Thread.sleep(secs*1000);} catch(Exception e) {}
    393   }
    394
    395
    396   public static Test suite() {
    397     TestSuite suite = new TestSuite();
    398     suite.addTest(new SocketServerTestCase("test1"));
    399     suite.addTest(new SocketServerTestCase("test2"));
    400     suite.addTest(new SocketServerTestCase("test3"));
    401     suite.addTest(new SocketServerTestCase("test4"));
    402     suite.addTest(new SocketServerTestCase("test5"));
    403     suite.addTest(new SocketServerTestCase("test6"));
    404     suite.addTest(new SocketServerTestCase("test7"));
    405     suite.addTest(new SocketServerTestCase("test8"));
    406     return suite;
    407   }
    408 }