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